Skip to content

Commit 8ae84ed

Browse files
authored
stubtest: special case final and deprecated (#16457)
We should probably lean into the type checker harder here Fixes #14950 Fixes python/typeshed#11009 (comment)
1 parent a7c53d3 commit 8ae84ed

File tree

3 files changed

+29
-0
lines changed

3 files changed

+29
-0
lines changed

mypy/stubtest.py

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1215,6 +1215,12 @@ def _resolve_funcitem_from_decorator(dec: nodes.OverloadPart) -> nodes.FuncItem
12151215
def apply_decorator_to_funcitem(
12161216
decorator: nodes.Expression, func: nodes.FuncItem
12171217
) -> nodes.FuncItem | None:
1218+
if (
1219+
isinstance(decorator, nodes.CallExpr)
1220+
and isinstance(decorator.callee, nodes.RefExpr)
1221+
and decorator.callee.fullname in mypy.types.DEPRECATED_TYPE_NAMES
1222+
):
1223+
return func
12181224
if not isinstance(decorator, nodes.RefExpr):
12191225
return None
12201226
if not decorator.fullname:
@@ -1223,6 +1229,7 @@ def apply_decorator_to_funcitem(
12231229
if (
12241230
decorator.fullname in ("builtins.staticmethod", "abc.abstractmethod")
12251231
or decorator.fullname in mypy.types.OVERLOAD_NAMES
1232+
or decorator.fullname in mypy.types.FINAL_DECORATOR_NAMES
12261233
):
12271234
return func
12281235
if decorator.fullname == "builtins.classmethod":

mypy/test/teststubtest.py

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -71,6 +71,8 @@ class Sequence(Iterable[_T_co]): ...
7171
class Tuple(Sequence[_T_co]): ...
7272
class NamedTuple(tuple[Any, ...]): ...
7373
def overload(func: _T) -> _T: ...
74+
def deprecated(__msg: str) -> Callable[[_T], _T]: ...
75+
def final(func: _T) -> _T: ...
7476
"""
7577

7678
stubtest_builtins_stub = """
@@ -630,6 +632,23 @@ def f5(__b: str) -> str: ...
630632
runtime="def f5(x, /): pass",
631633
error=None,
632634
)
635+
yield Case(
636+
stub="""
637+
from typing import deprecated, final
638+
class Foo:
639+
@overload
640+
@final
641+
def f6(self, __a: int) -> int: ...
642+
@overload
643+
@deprecated("evil")
644+
def f6(self, __b: str) -> str: ...
645+
""",
646+
runtime="""
647+
class Foo:
648+
def f6(self, x, /): pass
649+
""",
650+
error=None,
651+
)
633652

634653
@collect_cases
635654
def test_property(self) -> Iterator[Case]:

mypy/types.py

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -119,6 +119,9 @@
119119
# Supported Annotated type names.
120120
ANNOTATED_TYPE_NAMES: Final = ("typing.Annotated", "typing_extensions.Annotated")
121121

122+
# Supported @deprecated type names
123+
DEPRECATED_TYPE_NAMES: Final = ("typing.deprecated", "typing_extensions.deprecated")
124+
122125
# We use this constant in various places when checking `tuple` subtyping:
123126
TUPLE_LIKE_INSTANCE_NAMES: Final = (
124127
"builtins.tuple",

0 commit comments

Comments
 (0)