Skip to content

Commit

Permalink
Check typeguard validity for staticmethods (#14953)
Browse files Browse the repository at this point in the history
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
  • Loading branch information
A5rocks authored Mar 26, 2023
1 parent 3f35ebb commit c170056
Show file tree
Hide file tree
Showing 2 changed files with 23 additions and 9 deletions.
7 changes: 2 additions & 5 deletions mypy/semanal.py
Original file line number Diff line number Diff line change
Expand Up @@ -867,11 +867,8 @@ def analyze_func_def(self, defn: FuncDef) -> None:
assert isinstance(result, ProperType)
if isinstance(result, CallableType):
# type guards need to have a positional argument, to spec
if (
result.type_guard
and ARG_POS not in result.arg_kinds[self.is_class_scope() :]
and not defn.is_static
):
skip_self = self.is_class_scope() and not defn.is_static
if result.type_guard and ARG_POS not in result.arg_kinds[skip_self:]:
self.fail(
"TypeGuard functions must have a positional argument",
result,
Expand Down
25 changes: 21 additions & 4 deletions test-data/unit/check-typeguard.test
Original file line number Diff line number Diff line change
Expand Up @@ -602,12 +602,30 @@ def func(names: Tuple[str, ...]):
from typing_extensions import TypeGuard

class Z:
def typeguard(self, *, x: object) -> TypeGuard[int]: # E: TypeGuard functions must have a positional argument
def typeguard1(self, *, x: object) -> TypeGuard[int]: # line 4
...

@staticmethod
def typeguard2(x: object) -> TypeGuard[int]:
...

@staticmethod # line 11
def typeguard3(*, x: object) -> TypeGuard[int]:
...

def bad_typeguard(*, x: object) -> TypeGuard[int]: # E: TypeGuard functions must have a positional argument
def bad_typeguard(*, x: object) -> TypeGuard[int]: # line 15
...
[builtins fixtures/tuple.pyi]

# In Python 3.8 the line number associated with FunctionDef nodes changed
[builtins fixtures/classmethod.pyi]
[out]
main:4: error: TypeGuard functions must have a positional argument
main:11: error: TypeGuard functions must have a positional argument
main:15: error: TypeGuard functions must have a positional argument
[out version>=3.8]
main:4: error: TypeGuard functions must have a positional argument
main:12: error: TypeGuard functions must have a positional argument
main:15: error: TypeGuard functions must have a positional argument

[case testTypeGuardWithKeywordArg]
from typing_extensions import TypeGuard
Expand Down Expand Up @@ -640,7 +658,6 @@ if Y().typeguard(x):
reveal_type(x) # N: Revealed type is "builtins.int"
if Y.typeguard(x):
reveal_type(x) # N: Revealed type is "builtins.int"
[builtins fixtures/tuple.pyi]
[builtins fixtures/classmethod.pyi]

[case testTypeGuardKwargFollowingThroughOverloaded]
Expand Down

0 comments on commit c170056

Please sign in to comment.