-
-
Notifications
You must be signed in to change notification settings - Fork 3k
Re-widen custom properties after narrowing #19296
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
Merged
Merged
Changes from all commits
Commits
Show all changes
2 commits
Select commit
Hold shift + click to select a range
File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
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.
Only now I finally realized that
mypy
narrows types of asymmetric properties. Is such a pattern really that popular in wild? In my head any property with a setter means "please do not try to narrow that from assignment" in bold, toxic yellow letters...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.
I believe that the vast majority of setters probably just assign the value as is (with some additional operations, such as checking validity), and the getter will return it. There's no guarantee that this is the case -- but narrowing types of regular attributes is already generally unsafe but still supported, since not having it would be quite tedious.
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.
@JukkaL I agree that's true iff the property is symmetric. If it is not, narrowing is too optimistic IMO, I'd prefer to see no narrowing by assignment at all for properties with different getter and setter types. I can easily envision the setter implementation (omitted in this test) creating a
C
instance and caching it, and narrowing toD
would be incorrect.I think this is quite different from regular attribute narrowing: there is some common sense expectation that attributes are "good citizens", but it does not apply to properties and especially asymmetric ones.
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.
To be focused, I think the following implementation is idiomatic, and narrowing by assignment should not happen here:
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.
@sterliakov
Yeah, I am writing subclasses of
list
every day :-) Seriously however: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.
Since you're asking...
I dunno whether this was considered and intentional - sometimes things like this may really get missed. Sometimes decisions made in past are challenged and eventually reconsidered. Since such decisions are almost always undocumented (or difficult to trace at least), I can't say for sure. And I know you were working on these parts, so you're the right person to raise my concerns to:) And I don't think 6-7 years timeline applies to properties - you only finished asymmetric properties support last month or so, the implementation is essentially newborn.
To me doing such narrowing for asymmetric properties is a mistake - I don't think this would cause a lot of false positives in real code, and this is exactly the kind of possible bug I want mypy to catch early. It's not the hill I'm going to die on, but a significant annoyance.
(though I should've probably opened a ticket to discuss this outside of a semi-related PR)
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.
It does, before I implemented the proper support, the setter type was automatically the getter type, so mypy happily narrowed it if the type of the value assigned was a subtype of the getter type.
But what if a person actually implements your example correctly? I.e. with
Also what if the getter/setter types are unions (especially with
None
)? Anyway, there were no new material information since that decision was made, so it stays.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.
But that's not necessarily "correctly"! If that class modifies
self._foo
elsewhere, the least surprising behaviour would be to always copy in setter to avoid modifying caller-provided value iff it happens to be a list.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.
Right, the least surprising behavior is when consequences of
x.foo = [1, 2, 3]
depend on whetherfoo
is a regular attribute or a fancy property :-)A bit more of educational content for you: should we prohibit overriding regular attributes with such properties? I mean we always narrow regular attributes, but
x
inx.foo
in fact may be an instance of a subclass.