Skip to content

Commit c170056

Browse files
authored
Check typeguard validity for staticmethods (#14953)
I was checking through my previous contributions and noticed I messed up the logic here. I added a test case that currently is wrong. Followup to #14238
1 parent 3f35ebb commit c170056

File tree

2 files changed

+23
-9
lines changed

2 files changed

+23
-9
lines changed

mypy/semanal.py

+2-5
Original file line numberDiff line numberDiff line change
@@ -867,11 +867,8 @@ def analyze_func_def(self, defn: FuncDef) -> None:
867867
assert isinstance(result, ProperType)
868868
if isinstance(result, CallableType):
869869
# type guards need to have a positional argument, to spec
870-
if (
871-
result.type_guard
872-
and ARG_POS not in result.arg_kinds[self.is_class_scope() :]
873-
and not defn.is_static
874-
):
870+
skip_self = self.is_class_scope() and not defn.is_static
871+
if result.type_guard and ARG_POS not in result.arg_kinds[skip_self:]:
875872
self.fail(
876873
"TypeGuard functions must have a positional argument",
877874
result,

test-data/unit/check-typeguard.test

+21-4
Original file line numberDiff line numberDiff line change
@@ -602,12 +602,30 @@ def func(names: Tuple[str, ...]):
602602
from typing_extensions import TypeGuard
603603

604604
class Z:
605-
def typeguard(self, *, x: object) -> TypeGuard[int]: # E: TypeGuard functions must have a positional argument
605+
def typeguard1(self, *, x: object) -> TypeGuard[int]: # line 4
606+
...
607+
608+
@staticmethod
609+
def typeguard2(x: object) -> TypeGuard[int]:
610+
...
611+
612+
@staticmethod # line 11
613+
def typeguard3(*, x: object) -> TypeGuard[int]:
606614
...
607615

608-
def bad_typeguard(*, x: object) -> TypeGuard[int]: # E: TypeGuard functions must have a positional argument
616+
def bad_typeguard(*, x: object) -> TypeGuard[int]: # line 15
609617
...
610-
[builtins fixtures/tuple.pyi]
618+
619+
# In Python 3.8 the line number associated with FunctionDef nodes changed
620+
[builtins fixtures/classmethod.pyi]
621+
[out]
622+
main:4: error: TypeGuard functions must have a positional argument
623+
main:11: error: TypeGuard functions must have a positional argument
624+
main:15: error: TypeGuard functions must have a positional argument
625+
[out version>=3.8]
626+
main:4: error: TypeGuard functions must have a positional argument
627+
main:12: error: TypeGuard functions must have a positional argument
628+
main:15: error: TypeGuard functions must have a positional argument
611629

612630
[case testTypeGuardWithKeywordArg]
613631
from typing_extensions import TypeGuard
@@ -640,7 +658,6 @@ if Y().typeguard(x):
640658
reveal_type(x) # N: Revealed type is "builtins.int"
641659
if Y.typeguard(x):
642660
reveal_type(x) # N: Revealed type is "builtins.int"
643-
[builtins fixtures/tuple.pyi]
644661
[builtins fixtures/classmethod.pyi]
645662

646663
[case testTypeGuardKwargFollowingThroughOverloaded]

0 commit comments

Comments
 (0)