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
Make dataclass function idempotent. Fix for issue #92052 #92406
base: main
Are you sure you want to change the base?
Conversation
While it is already possible to determine whether a class or one of its ancestors has been processed by the `dataclass` function, there is no way to determine whether the first argument, `_cls`, has. Because of this, `dataclass(dataclass(C))` is not valid. Third party libraries (e.g. pydantic) need invoke the dataclass wrapper _if it has not already been invoked_ before adding their on functions. This patch: a) Provides a mechanism, `is_direct_datacclass`, to determine whether `dataclass` has been applied to a given class b) Uses this mechanism to make dataclass idempotent.
|
Every change to Python requires a NEWS entry. Please, add it using the blurb_it Web app or the blurb command-line tool. |
|
Can't you just check for |
|
What we (pydantic in particular, but in general) need to be able to differentiate is the following: The reason that this matters is because libraries such as pydantic are currently designed to handle: It had earlier been suggested that |
|
As an aside -- I haven't been able to get the unit tests to run on my machine. Would be happy to supply examples and unit tests if someone can offer advice on how to get the test environment running. This is my current return from (I'm developing on a Mac Mini w/ an M1 chip. |
|
As I said, you can use >>> @dataclass
... class Foo:
... x: int
...
>>> class Bar:
... y: int
...
>>> Foo.__dict__.get("__dataclass_fields__") is not None
True
>>> Bar.__dict__.get("__dataclass_fields__") is not None
FalseAdmittedly this should be done somewhere inside the What if My problem with calling I don't know if you'd want to pass in I'll probably change my patch for issue #92231 to raise |
|
@ericvsmith -- Try: We still need to process |
|
Oops, that's what the previous example was supposed to be: >>> from dataclasses import *
>>> @dataclass
... class Foo:
... x: int
...
>>> class Bar(Foo):
... y: int
...
>>> Foo.__dict__.get("__dataclass_fields__") is not None
True
>>> Bar.__dict__.get("__dataclass_fields__") is not None
False |
|
Ah-ha! I learn something new about python every day. I hadn't grasped the difference between: Because I was using an IDE, I just examined both |
No, not if my comment above about |
|
No problem with the error -- your call on that one. I (speaking for |
|
Can't you catch and ignore the exception, rather than the look-before-you-leap version? That would be the supported version, rather than poking around in the internals. That said, the |
|
Will do (w/ the obvious substitution of |
|
Wrt the catcha-and-ignore exception -- I've always shyed away from that sort of solution as a wee bit opaque, but I'll leave it up to @samuelcolvin to decide. Thanks again! Also - we wouldn't have that one available until 3.11 anyway, no? |
While it is already possible to determine whether a class
or one of its ancestors has been processed by the
dataclassfunction, there is no way to determine whether the first
argument,
_cls, has. Because of this,dataclass(dataclass(C))is not valid. Third party libraries(e.g. pydantic) need invoke the dataclass wrapper if it
has not already been invoked before adding their on functions. This patch:
a) Provides a mechanism,
is_direct_datacclass, to determine whetherdataclasshas been applied to a given classb) Uses this mechanism to make dataclass idempotent.