Skip to content
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): improve the handling of explicit type annotations of assignment statements #17899

Conversation

tyralla
Copy link
Collaborator

@tyralla tyralla commented Oct 8, 2024

Two improvements of the current PEP 702 implementation (deprecated):

  • Analyse the explicit type annotations of "normal" assignment statements (that have an rvalue).
  • Dive into nested type annotations of assignment statements.

(I intend to continue working on PEP 702 and would prefer to do so in small steps if this is okay for the maintainers/reviewers.)

tyralla and others added 2 commits October 8, 2024 22:17
* Analyse the explicit type annotations of "normal" assignment statements (that have an rvalue).
* Dive into nested type annotations of assignment statements.

This comment has been minimized.

This comment has been minimized.

@tyralla
Copy link
Collaborator Author

tyralla commented Oct 8, 2024

Copy link
Member

@ilevkivskyi ilevkivskyi left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks! Here are couple comments.

mypy/checker.py Outdated
self.check_deprecated(typ.type, s)
for arg in typ.args:
self.search_deprecated(arg, s, visited)
elif isinstance(typ, (UnionType, TupleType)):
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is not a robust way to do it. You should write a simple visitor instead.

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I replaced search_deprecated with InstanceDeprecatedVisitor, which additionally considers CallableType and TypeAliasType. Do you see other relevant cases?

x5: Tuple[Tuple[D, C], E] # N: class __main__.C is deprecated: use C2 instead
x6: List[C] # N: class __main__.C is deprecated: use C2 instead
x7: List[List[C]] # N: class __main__.C is deprecated: use C2 instead
x8: List[Optional[Tuple[Union[List[C], int]]]] # N: class __main__.C is deprecated: use C2 instead
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Maybe add a test case involving type aliases (including generic and/or recursive ones).

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done.

This comment has been minimized.

This comment has been minimized.

mypy/checker.py Outdated
@@ -287,6 +290,96 @@ class PartialTypeScope(NamedTuple):
is_local: bool


class InstanceDeprecatedVisitor(TypeVisitor[None]):
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Sorry, this is not what I meant, you should inherit TypeTraverserVisitor instead, and override only visit_instance() and maybe visit_type_alias_type() (the latter is only needed if you want to show an error at each use place, instead of only at the type alias definition r.h.s.)

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

No problem. TypeTraverserVisitor is the more convenient base class, of course. Now I know it exists.

I also changed the name visited to seen_aliases (in agreement with TypeArgumentAnalyzer).

I was unsure whether emitting deprecation notes due to using type alias definitions is a good idea. I had a slight tendency towards it, so I implemented it this way for now. Maybe @JelleZijlstra has a better thought-out opinion on this?

This comment has been minimized.

Copy link
Member

@ilevkivskyi ilevkivskyi left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is almost ready, I have couple more comments.

I was unsure whether emitting deprecation notes due to using type alias definitions is a good idea.

It looks like PEP is intentionally vague on the details. If you want to know my opinion, I would say we should only warn once on the type alias definition.

mypy/checker.py Outdated Show resolved Hide resolved
mypy/checker.py Outdated Show resolved Hide resolved
@JelleZijlstra
Copy link
Member

It looks like PEP is intentionally vague on the details. If you want to know my opinion, I would say we should only warn once on the type alias definition.

I tried to make it concrete, but likely missed some cases. In general, I'd want people to only get one deprecation notice per deprecated thing they use. I think what you're talking about here is an alias like Alias: TypeAlias = DeprecatedThing, where DeprecatedThing has the @deprecated decorator. In that case, I'd ideally expect a deprecation notice for the Alias definition, but not for every usage of Alias.

@tyralla
Copy link
Collaborator Author

tyralla commented Oct 11, 2024

Would you say the same for cases where Alias is imported from another module/library?

import lib
x: lib.Alias  # no deprecation warning?

Then, the author of lib would have no way to pass the information that Alias has been (indirectly) deprecated.

A highly exceptional case, of course...

@JelleZijlstra
Copy link
Member

I would. PEP 702 is limited in the kinds of things it lets you mark as deprecated, and type aliases aren't on the list. We'd need a new PEP with new syntax to mark type aliases as deprecated.

@tyralla
Copy link
Collaborator Author

tyralla commented Oct 11, 2024

Okay, I did as you suggested. Thanks for your sharing your opinion, @JelleZijlstra, and doing the review, @ilevkivskyi!

Copy link
Contributor

Diff from mypy_primer, showing the effect of this PR on open source code:

anyio (https://github.com/agronholm/anyio)
+ src/anyio/_backends/_asyncio.py:1063: note: class asyncio.unix_events.AbstractChildWatcher is deprecated: Deprecated as of Python 3.12; will be removed in Python 3.14  [deprecated]

@ilevkivskyi ilevkivskyi merged commit 0c10dc3 into python:master Oct 11, 2024
18 checks passed
@ilevkivskyi
Copy link
Member

@tyralla After some more thinking it seems to me moving this visitor to earlier stages of analysis (i.e. to typeanal.py) will allow uniformly using it in all positions a type can appear. Otherwise you will chase a lot possible cases, like function annotations, type aliases targets, cast targets, type variable bounds etc.

@ilevkivskyi
Copy link
Member

Anyway, since I already merged this one, you can do it in a follow-up PR.

@tyralla
Copy link
Collaborator Author

tyralla commented Oct 11, 2024

Thanks for the tip! I will try it.

ilevkivskyi pushed a commit that referenced this pull request Oct 26, 2024
This pull request generalises #17899.  

Initially, it started with extending #17899 to function signatures only,
as can be seen from the following initial comments and the subsequent
discussions.

---------

Co-authored-by: pre-commit-ci[bot] <66853113+pre-commit-ci[bot]@users.noreply.github.com>
@tyralla tyralla added the topic-pep-702 PEP 702, @deprecated label Nov 8, 2024
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
topic-pep-702 PEP 702, @deprecated upnext
Projects
None yet
Development

Successfully merging this pull request may close these issues.

4 participants