cattrs
cattrs copied to clipboard
Recursive Attrs class generation
- cattrs version: 22.1.0
- Python version: 3.11.0-rc1
- Operating System: Fedora Linux
Description
I would like an easy way to recursively generate attrs
classes that have attributes of their type (eg Foo.foo: Foo
). Obviously, you can't directly annotate attributes as being of the same type of the class, as the class is not yet generated when specifying attrs attributes. However, Python 3.11 introduces typing.Self
, a shortcut to annotating the class. Cattrs could implement this, allowing users to avoid using __attrs_post_init__
to achieve this.
What I Did
# I would like to be able to do this:
@define
class Bar:
baz: typing.Self = None
@define
class Foo:
bar: Bar
structure({"bar": {"baz": {"baz": None}}}, Foo)
Interesting, I wasn't aware attributes could be annotates as Self
but according to PEP 673, that's valid!
We don't support it yet, so I'll leave this open as an enhancement request.
Your annotation is a little incorrect though, it should be Self | None
.
Until we fix the issue, you can use a stringified annotation instead, like this:
from attrs import define
from cattrs import structure
@define
class Bar:
baz: "Bar | None" = None
@define
class Foo:
bar: Bar
structure({"bar": {"baz": {"baz": None}}}, Foo)
This should work.
Related discussion about the None
default adding making the type annotation implicitly Optional
: https://github.com/python/cpython/issues/90353#issuecomment-1093941076. This behavior got fixed in Python 3.11+, but it pertains to previous versions.
Sounds good. I don't use cattrs anymore, but I'm happy that this feature is getting looked at.