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
dataclass copy constructor doesn't recognize default_factory #92052
Comments
Sample test code can be found at https://github.com/hsolbrig/dataclasstest/blob/main/src/dataclasscopytest.py |
See: python/cpython#92052 for details. This patch should add the patch to any module that imports linkml_runtime.
This isn't a "copy constructor", this is "apply the Can I ask what your use case is? |
The more I think about this, the more I think the right thing to do is prevent @dataclass(repr=False)
@dataclass(repr=True)
class C:
x: int result in? |
Heavens - please don't do this! This feature is currently being utilized by the pydantic community to allow For details, scroll down in https://pydantic-docs.helpmanual.io/usage/dataclasses/ to the section labeled "Convert stdlib dataclasses into pydantic dataclasses". Its use can be found at https://github.com/samuelcolvin/pydantic/blob/master/pydantic/dataclasses.py#L159 I may have used the wrong terminology by calling it a "copy constructor", but if this suggested change is objectionable, please leave the code as it is and we'll work with the pydantic community to figure out an alternative. |
I'm not going to do anything rash! What would pydantic expect from: @dataclass(repr=False)
@dataclass(repr=True)
class C:
x: int Or does it always expect that if called twice on the same class that all of the parameters to |
Let me see whether I can get the pydantic authors involved. WRT the above question, I actually have no idea what to expect. As the old joke goes, |
Just mulling it over, my recollection is that |
Hi, pydantic author here. Thanks so much @hsolbrig for bringing this up. Ignoring pydantic for a moment, I completely agree that it would make sense for @dataclass(repr=False)
@dataclass(repr=True)
class C:
x: int to be illegal. Or to put it differently - an explicit error would be better than undefined behaviour, wrong behaviour or a less clear error later on. The reason pydantic cares about this is because people want to convert a standard dataclass to a "pydantic dataclass" - e.g. a dataclass with machinery to perform full type validation. But we want the "pydantic dataclass" to be as close as possible to a vanilla standard dataclass. E.g. we want: import dataclasses
import pydantic
@dataclasses.dataclass
class Foobar:
a: str
b: list[int] = dataclasses.field(default_factory=lambda: [1, 2, 3])
Foobar2 = pydantic.dataclasses.dataclass(Foobar)
f2 = Foobar2(a="a")
print(f) To work. Currently it doesn't because the new I'd be happy/willing to rewrite how Is that something you'd consider? |
Update on the proposed patch: the last line should read:
Executing the default_factory vs. just adding it. Will be running more tests to see whether this introduces any other problems |
Does pydantic always use the same parameters every time it calls |
@hsolbrig: Could you please provide a PR or at least a diff? |
Will do -- the fix proposal is going to be a bit more complex than I'd first thought so it will probably be a day or two before I'm sure that everything works. |
PR submitted - happy to chat about it, although we will probably want to include @samuelcolvin as well. |
I suspect that the preferable behavior might be to prevent dataclass being called twice on the same class, but to provide a supported way to "look before you leap" and check if a class has had the dataclass decorator run on it already, i.e. something like the I don't think it makes sense to silently allow running the dataclass decorator twice on the same class, where the second run is a no-op. As @ericvsmith already has hinted, this leads to pretty confusing behavior if the params used are not identical for the two calls. You could have a situation where you clearly call the dataclass decorator on a class and say As far as I can tell, pydantic doesn't really need the ability to re-run the decorator on an existing dataclass -- in that case pydantic is just counting on it doing no harm (but currently it does do harm in any case where I guess it's up to pydantic whether in this case it wants to check for a match between the options given to the pydantic decorator and the ones previously used on the already-a-dataclass (this check is possible by introspecting |
Bug report
The
dataclass
copy constructor doesn't recognize the default_factory.Causes the following error`
Your environment
This bug has been shown to exist in versions 3.9 and 3.10. The test above is python 3.10.4.
Using the line numbers in python 3.10.4, this can be fixed with the following change to dataclasses.py line 958:
The text was updated successfully, but these errors were encountered: