Skip to content

PEP 702 (@deprecated): improve the handling of explicit type annotations of assignment statements #17899

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
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
18 changes: 15 additions & 3 deletions mypy/checker.py
Original file line number Diff line number Diff line change
Expand Up @@ -287,6 +287,18 @@ class PartialTypeScope(NamedTuple):
is_local: bool


class InstanceDeprecatedVisitor(TypeTraverserVisitor):
"""Visitor that recursively checks for deprecations in nested instances."""

def __init__(self, typechecker: TypeChecker, context: Context) -> None:
self.typechecker = typechecker
self.context = context

def visit_instance(self, t: Instance) -> None:
super().visit_instance(t)
self.typechecker.check_deprecated(t.type, self.context)


class TypeChecker(NodeVisitor[None], CheckerPluginInterface):
"""Mypy type checker.

Expand Down Expand Up @@ -2930,14 +2942,14 @@ def visit_assignment_stmt(self, s: AssignmentStmt) -> None:
Handle all kinds of assignment statements (simple, indexed, multiple).
"""

if isinstance(s.rvalue, TempNode) and s.rvalue.no_rhs:
if s.unanalyzed_type is not None:
for lvalue in s.lvalues:
if (
isinstance(lvalue, NameExpr)
and isinstance(var := lvalue.node, Var)
and isinstance(instance := get_proper_type(var.type), Instance)
and (var.type is not None)
):
self.check_deprecated(instance.type, s)
var.type.accept(InstanceDeprecatedVisitor(typechecker=self, context=s))

# Avoid type checking type aliases in stubs to avoid false
# positives about modern type syntax available in stubs such
Expand Down
33 changes: 32 additions & 1 deletion test-data/unit/check-deprecated.test
Original file line number Diff line number Diff line change
Expand Up @@ -102,7 +102,8 @@ def h() -> None: ...

[case testDeprecatedClass]

from typing_extensions import deprecated
from typing import Callable, List, Optional, Tuple, Union
from typing_extensions import deprecated, TypeAlias, TypeVar

@deprecated("use C2 instead")
class C: ...
Expand All @@ -114,10 +115,40 @@ C.missing() # N: class __main__.C is deprecated: use C2 instead \
C.__init__(c) # N: class __main__.C is deprecated: use C2 instead
C(1) # N: class __main__.C is deprecated: use C2 instead \
# E: Too many arguments for "C"

D = C # N: class __main__.C is deprecated: use C2 instead
D()
t = (C, C, D) # N: class __main__.C is deprecated: use C2 instead

u1: Union[C, int] = 1 # N: class __main__.C is deprecated: use C2 instead
u1 = 1
u2 = 1 # type: Union[C, int] # N: class __main__.C is deprecated: use C2 instead
u2 = 1

c1 = c2 = C() # N: class __main__.C is deprecated: use C2 instead
i, c3 = 1, C() # N: class __main__.C is deprecated: use C2 instead

class E: ...

x1: Optional[C] # N: class __main__.C is deprecated: use C2 instead
x2: Union[D, C, E] # N: class __main__.C is deprecated: use C2 instead
x3: Union[D, Optional[C], E] # N: class __main__.C is deprecated: use C2 instead
x4: Tuple[D, C, E] # N: class __main__.C is deprecated: use C2 instead
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.

x9: Callable[[int], C] # N: class __main__.C is deprecated: use C2 instead
x10: Callable[[int, C, int], int] # N: class __main__.C is deprecated: use C2 instead

T = TypeVar("T")
A1: TypeAlias = Optional[C] # ToDo
x11: A1
A2: TypeAlias = List[Union[A2, C]] # ToDo
x12: A2
A3: TypeAlias = List[Optional[T]]
x13: A3[C] # N: class __main__.C is deprecated: use C2 instead

[builtins fixtures/tuple.pyi]


Expand Down
Loading