-
-
Notifications
You must be signed in to change notification settings - Fork 2.8k
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
Assigning to an attribute with the same name as a dataclass InitVar
raises has no attribute
on 0.960
#12877
Comments
InitVar
raises has no attribute on 0.960InitVar
raises has no attribute
on 0.960
PEP 557 refers to these as "init-only" fields. An init-only field is provided as arguments to the You should use a different name for the instance variable assigned in the |
I agree with Eric that this behavior is correct, but I don't recall a change that was meant to introduce this check. Perhaps we should add a new unit test to ensure mypy's behavior remains consistent. |
A unit test was added for disallowing this behaviour in #12798, so the error being emitted is expected behaviour, not a bug. Note that if you use slotted dataclasses on Python 3.10+, this will also fail at runtime: >>> from dataclasses import dataclass, InitVar
>>> @dataclass(slots=True)
... class Foo:
... bar: InitVar[str]
... baz: InitVar[int] = 0
...
>>> f = Foo('hi', 5)
>>> f.__slots__
()
>>> f.bar = 'bye'
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
AttributeError: 'Foo' object has no attribute 'bar'
>>> f.baz = 6
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
AttributeError: 'Foo' object attribute 'baz' is read-only |
Closing this since it's a feature-not-a-bug, expected behaviour, and has a unit test. |
Thanks @AlexWaygood for linking #12798. Appreciated! Seems like a straighforward case! |
Here's an example of how to work around this -- you can define two attributes, one is a regular one and the other is an InitVar: from dataclasses import dataclass, InitVar, field
@dataclass
class D:
_x: InitVar[int]
x: str = field(init=False)
def __post_init__(self, _x: int) -> None:
self.x = str(_x) |
@JukkaL : this workaround mean you can do D(1), but not D(x=1), which is making things hard to read. This means right now there is no clean way in dataclass to both have a transformed attribute you transform from initial values and slot at the same time. It's not a huge problem, but I don't think this ticket should be closed until an alternative is proposed for that use case. |
Bug Report
On 0.960, if an attribute is typed as a
dataclasses.InitVar
and later tries to assign an attribute with the same name, mypy will complain on the assignment statement that the dataclass has no such attribute.This does not occur on 0.950.
To Reproduce
Expected Behavior
I expected that mypy would not complain about an assignment just because it shares the same name as an
InitVar
.Actual Behavior
mypy warns the user that the attribute does not exists in an assignment expression.
Your Environment
--strict
The text was updated successfully, but these errors were encountered: