-
-
Notifications
You must be signed in to change notification settings - Fork 32.1k
gh-119581: Add a test of InitVar with name shadowing #119582
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
gh-119581: Add a test of InitVar with name shadowing #119582
Conversation
As originally discussed in python/mypy#17219, MyPy has had a false-positive bug report because it errors when a dataclass has methods that shadow an `InitVar` field. It is actually a bit surprising that this works, it turns out that `__annotations__` "remembers" field assignments even if the bound names are later overwritten by methods; it will *not* work to provide a default value. There have been multiple bug reports on MyPy so we know people are actually relying on this in practice; most likely it comes up when a dataclass wants to take a "raw" value as an InitVar and transform it somehow in `__post_init__` into a different value before assigning it to a field; in that case they may choose to make the actual field private and provide a property for access. I currently provide a test of the happy path where there is no default value provided, but no tests of the behavior when no default is provided (in which case the property will override the default) and no documentation (because I'm not sure we want to consider this behavior officially supported). The main goal is to have a regression test since it would be easy for a refactor to break this.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thanks! It seems likely to me that this probably only worked "by accident" rather than being something that was deliberately designed. But nonetheless, it seems like useful behaviour that's worth preserving; and as you say, it seems like lots of people are relying on it now. So, I agree that this is a useful test to add.
(Whether or not type checkers support this pattern is irrelevant to whether it should be supported at runtime: lots of people use dataclasses without running a type checker on their code.)
Co-authored-by: Alex Waygood <[email protected]>
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
LGTM, thanks! (I'll wait a few days before merging, in case Eric or Carl have any objections)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This looks good to me. I was actually unaware of this behavior, but it does indeed look useful.
Thanks @stroxler for the PR, and @AlexWaygood for merging it 🌮🎉.. I'm working now to backport this PR to: 3.12, 3.13. |
…119582) (cherry picked from commit 6ec3712) Co-authored-by: Steven Troxler <[email protected]>
…119582) (cherry picked from commit 6ec3712) Co-authored-by: Steven Troxler <[email protected]>
GH-119672 is a backport of this pull request to the 3.13 branch. |
GH-119673 is a backport of this pull request to the 3.12 branch. |
As originally discussed in python/mypy#17219,
MyPy has had a false-positive bug report because it errors when a dataclass has methods that shadow an
InitVar
field.It is actually a bit surprising that this works, it turns out that
__annotations__
"remembers" field assignments even if the bound names are later overwritten by methods; it will not work to provide a default value.There have been multiple bug reports on MyPy so we know people are actually relying on this in practice; most likely it comes up when a dataclass wants to take a "raw" value as an InitVar and transform it somehow in
__post_init__
into a different value before assigning it to a field; in that case they may choose to make the actual field private and provide a property for access.I currently provide a test of the happy path where there is no default value provided, but no tests of the behavior when no default is provided (in which case the property will override the default) and no documentation (because I'm not sure we want to consider this behavior officially supported).
The main goal is to have a regression test since it would be easy for a refactor to break this.
dataclasses
unit tests should record behavior of shadowed init vars #119581