-
-
Notifications
You must be signed in to change notification settings - Fork 30k
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
dataclasses.replace broken if a class has any ClassVars #77977
Comments
The dataclasses.replace function does not work for classes that have class variables. See the console output below for an example. $ python
Python 3.7.0b5+ (heads/3.7:3c417610ad, Jun 7 2018, 16:21:29)
[Clang 9.1.0 (clang-902.0.39.2)] on darwin
Type "help", "copyright", "credits" or "license" for more information.
>>> import typing
>>> import dataclasses
>>> @dataclasses.dataclass(frozen=True)
... class Test:
... a: int
... class_var: typing.ClassVar[str] = 'foo'
...
>>> obj = Test(a=1)
>>> dataclasses.replace(obj, a=2)
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
File "/Users/sigurdljodal/.pyenv/versions/3.7-dev/lib/python3.7/dataclasses.py", line 1179, in replace
return obj.__class__(**changes)
TypeError: __init__() got an unexpected keyword argument 'class_var' |
Thanks for the report. This is the same error you get when using any non-field: >>> @dataclass
... class C:
... i: int
...
>>> c = C(4)
>>> replace(c, i=3)
C(i=3)
>>> replace(c, j=3)
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
File "C:\home\eric\local\python\cpython\lib\dataclasses.py", line 1179, in replace
return obj.__class__(**changes)
TypeError: __init__() got an unexpected keyword argument 'j' I think the TypeError is correct in both cases. The error message might not be the best. Are you suggesting that this shouldn't raise a TypeError? Since a ClassVar is not an instance variable, I don't think it makes any sense to replace() it. |
I think you misunderstood the issue here. I'm not trying to replace the class variable itself, I'm changing another field on a class that has a class variable. The problem is that the replace method includes the class variable in the change dict when copying fields that are not included in the function call. My call is: dataclasses.replace(obj, a=2) where I try to replace a, but it fails because class_var is included in the attributes to __init__ by the replace function. The problem is on this line: https://github.com/python/cpython/blob/master/Lib/dataclasses.py#L1162 |
Ah, you're right. I did misunderstand. Thanks for correcting me. PR soon. |
Ned: How do you feel about backporting this to 3.7? It's an unfortunate bug, but it's your call for 3.7.0 vs. 3.7.1. |
Let's fix it now. |
Thanks, Ned. I've backported it. |
Note: these values reflect the state of the issue at the time it was migrated and might not reflect the current state.
Show more details
GitHub fields:
bugs.python.org fields:
The text was updated successfully, but these errors were encountered: