Skip to content

Commit

Permalink
PEP 702 (@deprecated): improve the handling of explicit type annotati…
Browse files Browse the repository at this point in the history
…ons of assignment statements (#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>
  • Loading branch information
tyralla and pre-commit-ci[bot] authored Oct 11, 2024
1 parent b1701e5 commit 0c10dc3
Show file tree
Hide file tree
Showing 2 changed files with 47 additions and 4 deletions.
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
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

0 comments on commit 0c10dc3

Please sign in to comment.