Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
12 changes: 6 additions & 6 deletions mypy/stubtest.py
Original file line number Diff line number Diff line change
Expand Up @@ -1574,14 +1574,14 @@ def apply_decorator_to_funcitem(
):
return func
if decorator.fullname == "builtins.classmethod":
if func.arguments[0].variable.name not in ("_cls", "cls", "mcs", "metacls"):
raise StubtestFailure(
f"unexpected class parameter name {func.arguments[0].variable.name!r} "
f"in {dec.fullname}"
)
if not func.arguments or func.arguments[0].kind not in (nodes.ARG_POS, nodes.ARG_OPT):
# Nothing to drop, e.g. `def f(*args)`. inspect.signature of the runtime
# classmethod keeps the star argument too, so the two already line up.
return func
# FuncItem is written so that copy.copy() actually works, even when compiled
ret = copy.copy(func)
# Remove the cls argument, since it's not present in inspect.signature of classmethods
# Remove the cls argument, since it's not present in inspect.signature of classmethods.
# It can be given any name, so don't look at the name to decide.
ret.arguments = ret.arguments[1:]
return ret
# Just give up on any other decorators. After excluding properties, we don't run into
Expand Down
27 changes: 27 additions & 0 deletions mypy/test/teststubtest.py
Original file line number Diff line number Diff line change
Expand Up @@ -682,6 +682,33 @@ def __new__(cls, *args, **kwargs): pass
""",
error=None,
)
# The first parameter of a classmethod can be called anything, see #16583
yield Case(
stub="""
class GoodOddClsName:
@classmethod
def f(GoodOddClsName, number: int) -> None: ...
""",
runtime="""
class GoodOddClsName:
@classmethod
def f(GoodOddClsName, number): pass
""",
error=None,
)
yield Case(
stub="""
class GoodStarArgsCls:
@classmethod
def f(*args: int) -> None: ...
""",
runtime="""
class GoodStarArgsCls:
@classmethod
def f(*args): pass
""",
error=None,
)

@collect_cases
def test_arg_mismatch(self) -> Iterator[Case]:
Expand Down
Loading