-
-
Notifications
You must be signed in to change notification settings - Fork 2.9k
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
PEP 702 (@deprecated): "normal" overloaded methods #18477
PEP 702 (@deprecated): "normal" overloaded methods #18477
Conversation
Fixes python#18474 It seems I covered overloaded functions, descriptors, and special methods so far but completely forgot about "normal" methods (thanks to @sobolevn for pointing this out). This addition should do the trick.
for more information, see https://pre-commit.ci
This comment has been minimized.
This comment has been minimized.
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! What about @staticmethod
and @classmethod
?
mypy/checkexpr.py
Outdated
(node is None) | ||
and (member is not None) | ||
and isinstance(object_type, Instance) | ||
and ((symbol := object_type.type.names.get(member)) is not None) |
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.
(node is None) | |
and (member is not None) | |
and isinstance(object_type, Instance) | |
and ((symbol := object_type.type.names.get(member)) is not None) | |
node is None | |
and member is not None | |
and isinstance(object_type, Instance) | |
and (symbol := object_type.type.names.get(member)) is not None |
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 will have a look at it 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.
It became a one-liner followed by a loop.
Inheritance is also an issue: If the (overloaded) function is defined by a base class of The base class is not directly available. Going through the MRO might be necessary (at least for static methods). |
…ed_overload_item` for static methods
…ods' into narrowing/overloaded_normal_methods # Conflicts: # mypy/checkexpr.py
@sobolevn: |
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
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! Just two minor nitpicks :)
|
||
a = A() | ||
a.f(1) # E: overload def (self: __main__.A, v: builtins.int) of function __main__.A.f is deprecated: pass `str` instead | ||
a.f("x") |
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 would also test this case:
a.f("x") | |
a.f("x") | |
int_or_str: Union[int, str] | |
a.f(int_or_str) |
It should not raise if all is good.
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 not raise a warning, but why do you think it should not?
(There is not even a warning for a.h
, where the implementation is marked as deprecated, which is inconsistent with how functions are handled.)
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.
(There is not even a warning for a.h, where the implementation is marked as deprecated, which is inconsistent with how functions are handled.)
I made it consistent in c95f936. However, I added the in my opinion missing warnings to the test case, to prevent us from merging this too early by accident. I am curious to hear why you think the current behaviour is correct. (regarding int_or_str
).
Co-authored-by: sobolevn <[email protected]>
Co-authored-by: sobolevn <[email protected]>
This comment has been minimized.
This comment has been minimized.
…n analysing "normal" methods (like we do when in other cases).
This comment has been minimized.
This comment has been minimized.
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.
There's a failing test now, please take a look. From the brief looks it is related to the Union
type change.
It is unspecified in https://typing.readthedocs.io/en/latest/spec/directives.html#deprecated so we can ping @JelleZijlstra to see if that is correct.
Yes, the test now fails intentionally (as written somewhere above). I will wait for Jelle's response and adjust either |
I think it would make sense to issue the warning for the union, since that's the "sound" thing to do. I also checked against pyanalyze and pyright (since they were the reference impl's for PEP 702) and both of them issue a warning. pyanalyze is by Jelle, so that's probably his opinion on this (If we do this, we should also add a test case for overloaded functions — mypy doesn't currently complain about passing a union that matches a deprecated overload and whatever we decide to do, we should be consistent) |
Just so I understand correctly, the question is about whether code like this should warn about the deprecation:
And my answer is yes (as Shantanu surmised above). My rule of thumb is: if there would be an error if the deprecation was carried out (i.e., the int overload was removed), then there should be a deprecation warning now. |
Thank you very much for sharing your opinions on this. I will adjust |
This comment has been minimized.
This comment has been minimized.
Hmm, things are a little different (and eventually more complicated) than I expected. I have to study the responses of I hope to propose a fix for Unions in the next few days. |
mypy/checkexpr.py
Outdated
self.chk.warn_deprecated_overload_item(e.callee.node, e, target=callee_type) | ||
node = e.callee.node | ||
if node is None and member is not None and isinstance(object_type, Instance): | ||
for base in object_type.type.mro: |
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.
nit: I think we can use object_type.type.get(member)
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.
You're right, I adjusted it.
According to mypy_primer, this change doesn't affect type check results on a corpus of open source code. ✅ |
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.
Thank you! Let's continue the Union
work in the next PR.
Fixes #18474
It seems I covered overloaded functions, descriptors, and special methods so far but completely forgot about "normal" methods (thanks to @sobolevn for pointing this out). This addition should do the trick.