-
-
Notifications
You must be signed in to change notification settings - Fork 374
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
attr.define seems to break __init_subclass__ (works with attr.s) #971
Comments
It's probably |
of course, i'm open for another hack to make some feature work with slots ;) |
The third example works if i set import attr
@attr.define(slots=False, auto_attribs=False)
class OptionType:
name: str = attr.field()
__types__: dict[str, "OptionType"] = {}
def __init_subclass__(cls, **kwargs):
super().__init_subclass__(**kwargs)
type_name = attr.fields(cls).name.default
print(type_name, cls)
cls.__types__[type_name] = cls
@classmethod
def instance_for(cls, name):
return cls.__types__[name]()
@attr.define(slots=False)
class Int(OptionType):
name: str = "int"
@attr.define(slots=False)
class IntRange(Int):
name: str = "int-range"
print(OptionType.instance_for("int"))
That’s exactly the answer I was hoping for. Please notify me when you implemented this! 🤪 |
An improved documentation that stronger points out that slots are being used by default and what possible gotchas might look like would be a good-enough solution for me. |
The hint in braces is, compared to the amount and potential severness of the issues, not visible enough. I would use an admonition ( |
Looks good, thanks :) |
I like to use
__init_subclass__
to implement simple plug-in systems, e.g.:When this is run,
__init_subclass__
is run exactly once per class:This also works with
attr.s
:However, when I use
attr.define
, everything falls appart:The main reason is, that
__init_subclass__
is now called for every class in the inheritance hierarchy. That means that:attrs.define
(orattr.fields(cls)
(orcls.name.default
) will break)__types__
must move out of the class or I’ll get aTypeError: 'member_descriptor' object does not support item assignment
(because since it is typed, an attrs attribute is created for it).IntRange
overrides the class forint
, soOptionType.instance_for("int")
now returns anIntRange()
instead of anInt()
.I have not yet time to dig deeper into it but I always had the impression that
attr.define
is just an alias forattr.s
with nicer defaults but that seems not to be the case. 🤔The text was updated successfully, but these errors were encountered: