Skip to content

Commit 0c10dc3

Browse files
PEP 702 (@deprecated): improve the handling of explicit type annotations of assignment statements (python#17899)
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.) --------- Co-authored-by: pre-commit-ci[bot] <66853113+pre-commit-ci[bot]@users.noreply.github.com>
1 parent b1701e5 commit 0c10dc3

File tree

2 files changed

+47
-4
lines changed

2 files changed

+47
-4
lines changed

mypy/checker.py

+15-3
Original file line numberDiff line numberDiff line change
@@ -287,6 +287,18 @@ class PartialTypeScope(NamedTuple):
287287
is_local: bool
288288

289289

290+
class InstanceDeprecatedVisitor(TypeTraverserVisitor):
291+
"""Visitor that recursively checks for deprecations in nested instances."""
292+
293+
def __init__(self, typechecker: TypeChecker, context: Context) -> None:
294+
self.typechecker = typechecker
295+
self.context = context
296+
297+
def visit_instance(self, t: Instance) -> None:
298+
super().visit_instance(t)
299+
self.typechecker.check_deprecated(t.type, self.context)
300+
301+
290302
class TypeChecker(NodeVisitor[None], CheckerPluginInterface):
291303
"""Mypy type checker.
292304
@@ -2930,14 +2942,14 @@ def visit_assignment_stmt(self, s: AssignmentStmt) -> None:
29302942
Handle all kinds of assignment statements (simple, indexed, multiple).
29312943
"""
29322944

2933-
if isinstance(s.rvalue, TempNode) and s.rvalue.no_rhs:
2945+
if s.unanalyzed_type is not None:
29342946
for lvalue in s.lvalues:
29352947
if (
29362948
isinstance(lvalue, NameExpr)
29372949
and isinstance(var := lvalue.node, Var)
2938-
and isinstance(instance := get_proper_type(var.type), Instance)
2950+
and (var.type is not None)
29392951
):
2940-
self.check_deprecated(instance.type, s)
2952+
var.type.accept(InstanceDeprecatedVisitor(typechecker=self, context=s))
29412953

29422954
# Avoid type checking type aliases in stubs to avoid false
29432955
# positives about modern type syntax available in stubs such

test-data/unit/check-deprecated.test

+32-1
Original file line numberDiff line numberDiff line change
@@ -102,7 +102,8 @@ def h() -> None: ...
102102

103103
[case testDeprecatedClass]
104104

105-
from typing_extensions import deprecated
105+
from typing import Callable, List, Optional, Tuple, Union
106+
from typing_extensions import deprecated, TypeAlias, TypeVar
106107

107108
@deprecated("use C2 instead")
108109
class C: ...
@@ -114,10 +115,40 @@ C.missing() # N: class __main__.C is deprecated: use C2 instead \
114115
C.__init__(c) # N: class __main__.C is deprecated: use C2 instead
115116
C(1) # N: class __main__.C is deprecated: use C2 instead \
116117
# E: Too many arguments for "C"
118+
117119
D = C # N: class __main__.C is deprecated: use C2 instead
118120
D()
119121
t = (C, C, D) # N: class __main__.C is deprecated: use C2 instead
120122

123+
u1: Union[C, int] = 1 # N: class __main__.C is deprecated: use C2 instead
124+
u1 = 1
125+
u2 = 1 # type: Union[C, int] # N: class __main__.C is deprecated: use C2 instead
126+
u2 = 1
127+
128+
c1 = c2 = C() # N: class __main__.C is deprecated: use C2 instead
129+
i, c3 = 1, C() # N: class __main__.C is deprecated: use C2 instead
130+
131+
class E: ...
132+
133+
x1: Optional[C] # N: class __main__.C is deprecated: use C2 instead
134+
x2: Union[D, C, E] # N: class __main__.C is deprecated: use C2 instead
135+
x3: Union[D, Optional[C], E] # N: class __main__.C is deprecated: use C2 instead
136+
x4: Tuple[D, C, E] # N: class __main__.C is deprecated: use C2 instead
137+
x5: Tuple[Tuple[D, C], E] # N: class __main__.C is deprecated: use C2 instead
138+
x6: List[C] # N: class __main__.C is deprecated: use C2 instead
139+
x7: List[List[C]] # N: class __main__.C is deprecated: use C2 instead
140+
x8: List[Optional[Tuple[Union[List[C], int]]]] # N: class __main__.C is deprecated: use C2 instead
141+
x9: Callable[[int], C] # N: class __main__.C is deprecated: use C2 instead
142+
x10: Callable[[int, C, int], int] # N: class __main__.C is deprecated: use C2 instead
143+
144+
T = TypeVar("T")
145+
A1: TypeAlias = Optional[C] # ToDo
146+
x11: A1
147+
A2: TypeAlias = List[Union[A2, C]] # ToDo
148+
x12: A2
149+
A3: TypeAlias = List[Optional[T]]
150+
x13: A3[C] # N: class __main__.C is deprecated: use C2 instead
151+
121152
[builtins fixtures/tuple.pyi]
122153

123154

0 commit comments

Comments
 (0)