attrs
attrs copied to clipboard
Accessing @attr.s() decorator parameter values
In #python today someone wanted to find out if their class was frozen. Cls.__dataclass_params__
keeps the @dataclasses.dataclass()
arguments.
_DataclassParams(init=True,repr=True,eq=True,order=False,unsafe_hash=False,frozen=True)
Is there a way to get that data in attrs?
That was me. looking at source or attr make, it seems like this metadata is not currently maintained.
The reason I want this is because I am using attr (or dataclasses) as a template to generate an object that - among other things - performs runtime checks (type validation, recursive frozen check etc). This has some more context on what I am shooting for.
I was able to detect at runtime if a dataclass is frozen but was not able to do the same for attr classes.
This seems to work, but it's very fragile:
def is_attr_frozen(type_):
import attr
return type_.__setattr__ == attr._make._frozen_setattrs
It works if I import the class normally (from foo.bar import FrozenClass), but does not work when I import using import_module.
FrozenClass = import_module("foo.bar").FrozenClass
It would be great if there was a supported API to determine that (and possibly attr parameters).
FWIW, I find exposing more attrs
-specific stuff onto classes to be problematic. That I use attrs
is, to me, an implementation detail, and I don't intend "this is an attrs
-built class" to be part of the interface to my classes.
The more attrs
-specific introspection we add, the more locked-in to attrs
classes become.
@wsanchez, I agree with the sentiment, but it should still be possible for someone who wants to do this introspection to do it reliably if they choose.
attrs and dataclasses have a pretty good feature parity already, so the any lock-in is minimal. I am planning to support both in my library. this specific thing is one of the things I feel more uncomfortable with right now.
def is_dataclass_frozen(type_):
return type_.__dataclass_params__.frozen
def is_attr_frozen(type_):
import attr
# This is very hacky and probably fragile as well.
# Unfortunately currently there isn't an official API in attr that can detect that.
return type_.__setattr__ == attr._make._frozen_setattrs
Hmmm. So the thing is that I was kinda planning to expose class settings as a class internally anyway, because the amount of arguments is getting out of control.
However I plan too many internal changes soon-ish that I don't want to lo ourselves in rn.
Good to know about __dataclass_params__
– we should follow that naming convention if/once we implement it.
Wilfredo's argument is true but we always insisted on being extensible and allow introspection into attributes. It seems like a glaring omission to not allow introspection into the class itself.
I think I'll just pinky promise to not break your use case until we have an official API. ;)
Thanks @hynek. Glad to hear you are planning on adding an official API for this. I totally understand the desire to keep things as is until you have had some time to think and figure out what the best API is, especially with a major internal change in the horizon.
Thanks for pinky promising not to break my implementation until then! :)