Skip to content

Commit 986f752

Browse files
committed
Reuse "has self of cls" logic, add doc warning
1 parent 3083087 commit 986f752

File tree

4 files changed

+21
-5
lines changed

4 files changed

+21
-5
lines changed

mypy/checker.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1342,7 +1342,7 @@ def check_func_def(
13421342
if typ.type_is:
13431343
arg_index = 0
13441344
# For methods and classmethods, we want the second parameter
1345-
if ref_type is not None and (not defn.is_static or defn.name == "__new__"):
1345+
if ref_type is not None and defn.has_self_or_cls_argument:
13461346
arg_index = 1
13471347
if arg_index < len(typ.arg_types) and not is_subtype(
13481348
typ.type_is, typ.arg_types[arg_index]
@@ -1362,7 +1362,7 @@ def check_func_def(
13621362
isinstance(defn, FuncDef)
13631363
and ref_type is not None
13641364
and i == 0
1365-
and (not defn.is_static or defn.name == "__new__")
1365+
and defn.has_self_or_cls_argument
13661366
and typ.arg_kinds[0] not in [nodes.ARG_STAR, nodes.ARG_STAR2]
13671367
):
13681368
if defn.is_class or defn.name == "__new__":

mypy/nodes.py

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -509,6 +509,13 @@ class FuncBase(Node):
509509
"_fullname",
510510
)
511511

512+
is_static: bool
513+
"""Is this a `@staticmethod` (explicit or implicit)?
514+
515+
This shouldn't be used to check that there's `self` or `cls` argument.
516+
Use :py:attr:`has_self_or_cls_argument` instead.
517+
"""
518+
512519
def __init__(self) -> None:
513520
super().__init__()
514521
# Type signature. This is usually CallableType or Overloaded, but it can be
@@ -536,6 +543,15 @@ def name(self) -> str:
536543
def fullname(self) -> str:
537544
return self._fullname
538545

546+
@property
547+
def has_self_or_cls_argument(self) -> bool:
548+
"""If used as a method, does it have an argument for method binding (`self`, `cls`)?
549+
550+
This is true for `__new__` even though `__new__` does not undergo method binding,
551+
because we still usually assume that `cls` corresponds to the enclosing class.
552+
"""
553+
return not self.is_static or self.name == "__new__"
554+
539555

540556
OverloadPart: _TypeAlias = Union["FuncDef", "Decorator"]
541557

mypy/semanal.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1070,7 +1070,7 @@ def prepare_method_signature(self, func: FuncDef, info: TypeInfo, has_self_type:
10701070
functype = func.type
10711071
if func.name == "__new__":
10721072
func.is_static = True
1073-
if not func.is_static or func.name == "__new__":
1073+
if func.has_self_or_cls_argument:
10741074
if func.name in ["__init_subclass__", "__class_getitem__"]:
10751075
func.is_class = True
10761076
if not func.arguments:
@@ -1615,7 +1615,7 @@ def analyze_function_body(self, defn: FuncItem) -> None:
16151615
# The first argument of a non-static, non-class method is like 'self'
16161616
# (though the name could be different), having the enclosing class's
16171617
# instance type.
1618-
if is_method and (not defn.is_static or defn.name == "__new__") and defn.arguments:
1618+
if is_method and defn.has_self_or_cls_argument and defn.arguments:
16191619
if not defn.is_class:
16201620
defn.arguments[0].variable.is_self = True
16211621
else:

mypy/typeops.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -889,7 +889,7 @@ def callable_type(
889889
fdef: FuncItem, fallback: Instance, ret_type: Type | None = None
890890
) -> CallableType:
891891
# TODO: somewhat unfortunate duplication with prepare_method_signature in semanal
892-
if fdef.info and (not fdef.is_static or fdef.name == "__new__") and fdef.arg_names:
892+
if fdef.info and fdef.has_self_or_cls_argument and fdef.arg_names:
893893
self_type: Type = fill_typevars(fdef.info)
894894
if fdef.is_class or fdef.name == "__new__":
895895
self_type = TypeType.make_normalized(self_type)

0 commit comments

Comments
 (0)