From a9c8060f706e0328925a99f15f2dd78da6a727a4 Mon Sep 17 00:00:00 2001 From: hauntsaninja Date: Tue, 3 Jan 2023 13:55:41 -0800 Subject: [PATCH 1/3] More helpful error for missing self Fixes #14385 --- mypy/semanal.py | 2 +- test-data/unit/check-classes.test | 4 ++-- test-data/unit/check-functions.test | 2 +- test-data/unit/check-super.test | 2 +- test-data/unit/fine-grained.test | 12 ++++++------ test-data/unit/semanal-errors.test | 6 +++--- 6 files changed, 14 insertions(+), 14 deletions(-) diff --git a/mypy/semanal.py b/mypy/semanal.py index 51310e4f3e4d0..10431eea58376 100644 --- a/mypy/semanal.py +++ b/mypy/semanal.py @@ -947,7 +947,7 @@ def prepare_method_signature(self, func: FuncDef, info: TypeInfo, has_self_type: if func.name in ["__init_subclass__", "__class_getitem__"]: func.is_class = True if not func.arguments: - self.fail("Method must have at least one argument", func) + self.fail("Method must have at least one argument. Did you forget the self argument?", func) elif isinstance(functype, CallableType): self_type = get_proper_type(functype.arg_types[0]) if isinstance(self_type, AnyType): diff --git a/test-data/unit/check-classes.test b/test-data/unit/check-classes.test index 8784c73c5b175..06896e5358deb 100644 --- a/test-data/unit/check-classes.test +++ b/test-data/unit/check-classes.test @@ -2901,7 +2901,7 @@ b.bad = 'a' # E: Incompatible types in assignment (expression has type "str", v from typing import Any class Test: - def __setattr__() -> None: ... # E: Method must have at least one argument # E: Invalid signature "Callable[[], None]" for "__setattr__" + def __setattr__() -> None: ... # E: Method must have at least one argument. Did you forget the self argument? # E: Invalid signature "Callable[[], None]" for "__setattr__" t = Test() t.crash = 'test' # E: "Test" has no attribute "crash" @@ -7120,7 +7120,7 @@ reveal_type(Foo().y) # N: Revealed type is "builtins.list[Any]" # flags: --check-untyped-defs class Foo: - def bad(): # E: Method must have at least one argument + def bad(): # E: Method must have at least one argument. Did you forget the self argument? self.x = 0 # E: Name "self" is not defined [case testTypeAfterAttributeAccessWithDisallowAnyExpr] diff --git a/test-data/unit/check-functions.test b/test-data/unit/check-functions.test index ae6424f743be4..38e3e584065ea 100644 --- a/test-data/unit/check-functions.test +++ b/test-data/unit/check-functions.test @@ -2708,7 +2708,7 @@ class A: @dec def e(self) -> int: pass @property - def g() -> int: pass # E: Method must have at least one argument + def g() -> int: pass # E: Method must have at least one argument. Did you forget the self argument? @property def h(self, *args, **kwargs) -> int: pass # OK [builtins fixtures/property.pyi] diff --git a/test-data/unit/check-super.test b/test-data/unit/check-super.test index 6537f563a99c1..d72bf8638f115 100644 --- a/test-data/unit/check-super.test +++ b/test-data/unit/check-super.test @@ -365,7 +365,7 @@ class A: def f(self) -> None: pass class B(A): - def g() -> None: # E: Method must have at least one argument + def g() -> None: # E: Method must have at least one argument. Did you forget the self argument? super().f() # E: super() requires one or more positional arguments in enclosing function def h(self) -> None: def a() -> None: diff --git a/test-data/unit/fine-grained.test b/test-data/unit/fine-grained.test index 1a318b52a0823..779697930b693 100644 --- a/test-data/unit/fine-grained.test +++ b/test-data/unit/fine-grained.test @@ -1586,11 +1586,11 @@ class A: [file b.py.3] 2 [out] -a.py:3: error: Method must have at least one argument +a.py:3: error: Method must have at least one argument. Did you forget the self argument? == -a.py:3: error: Method must have at least one argument +a.py:3: error: Method must have at least one argument. Did you forget the self argument? == -a.py:3: error: Method must have at least one argument +a.py:3: error: Method must have at least one argument. Did you forget the self argument? [case testBaseClassDeleted] import m @@ -2007,11 +2007,11 @@ class A: class A: def foo(self) -> int: pass [out] -a.py:2: error: Method must have at least one argument +a.py:2: error: Method must have at least one argument. Did you forget the self argument? == -a.py:2: error: Method must have at least one argument +a.py:2: error: Method must have at least one argument. Did you forget the self argument? == -a.py:2: error: Method must have at least one argument +a.py:2: error: Method must have at least one argument. Did you forget the self argument? == [case testPreviousErrorInMethodSemanal2] diff --git a/test-data/unit/semanal-errors.test b/test-data/unit/semanal-errors.test index 5697d473414ec..3f34f0748a7a4 100644 --- a/test-data/unit/semanal-errors.test +++ b/test-data/unit/semanal-errors.test @@ -542,7 +542,7 @@ import typing class A: def f(): pass [out] -main:3: error: Method must have at least one argument +main:3: error: Method must have at least one argument. Did you forget the self argument? [case testInvalidBaseClass] import typing @@ -564,8 +564,8 @@ class A: def f() -> None: pass def g(): pass [out] -main:3: error: Method must have at least one argument -main:4: error: Method must have at least one argument +main:3: error: Method must have at least one argument. Did you forget the self argument? +main:4: error: Method must have at least one argument. Did you forget the self argument? [case testMultipleMethodDefinition] import typing From e8031a9b0bceccb03ef36d9dcf025f69fbeeeca6 Mon Sep 17 00:00:00 2001 From: hauntsaninja Date: Tue, 3 Jan 2023 14:04:30 -0800 Subject: [PATCH 2/3] lint --- mypy/semanal.py | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/mypy/semanal.py b/mypy/semanal.py index 10431eea58376..f4068ac6c26ec 100644 --- a/mypy/semanal.py +++ b/mypy/semanal.py @@ -947,7 +947,10 @@ def prepare_method_signature(self, func: FuncDef, info: TypeInfo, has_self_type: if func.name in ["__init_subclass__", "__class_getitem__"]: func.is_class = True if not func.arguments: - self.fail("Method must have at least one argument. Did you forget the self argument?", func) + self.fail( + "Method must have at least one argument. Did you forget the self argument?", + func, + ) elif isinstance(functype, CallableType): self_type = get_proper_type(functype.arg_types[0]) if isinstance(self_type, AnyType): From de1a6911e3c7629035b46cf11f2da66e305a4d02 Mon Sep 17 00:00:00 2001 From: hauntsaninja Date: Tue, 3 Jan 2023 14:20:11 -0800 Subject: [PATCH 3/3] quotes --- mypy/semanal.py | 2 +- test-data/unit/check-classes.test | 4 ++-- test-data/unit/check-functions.test | 2 +- test-data/unit/check-super.test | 2 +- test-data/unit/fine-grained.test | 12 ++++++------ test-data/unit/semanal-errors.test | 6 +++--- 6 files changed, 14 insertions(+), 14 deletions(-) diff --git a/mypy/semanal.py b/mypy/semanal.py index f4068ac6c26ec..fb01fad51bb09 100644 --- a/mypy/semanal.py +++ b/mypy/semanal.py @@ -948,7 +948,7 @@ def prepare_method_signature(self, func: FuncDef, info: TypeInfo, has_self_type: func.is_class = True if not func.arguments: self.fail( - "Method must have at least one argument. Did you forget the self argument?", + 'Method must have at least one argument. Did you forget the "self" argument?', func, ) elif isinstance(functype, CallableType): diff --git a/test-data/unit/check-classes.test b/test-data/unit/check-classes.test index 06896e5358deb..b35b2f9e4e94b 100644 --- a/test-data/unit/check-classes.test +++ b/test-data/unit/check-classes.test @@ -2901,7 +2901,7 @@ b.bad = 'a' # E: Incompatible types in assignment (expression has type "str", v from typing import Any class Test: - def __setattr__() -> None: ... # E: Method must have at least one argument. Did you forget the self argument? # E: Invalid signature "Callable[[], None]" for "__setattr__" + def __setattr__() -> None: ... # E: Method must have at least one argument. Did you forget the "self" argument? # E: Invalid signature "Callable[[], None]" for "__setattr__" t = Test() t.crash = 'test' # E: "Test" has no attribute "crash" @@ -7120,7 +7120,7 @@ reveal_type(Foo().y) # N: Revealed type is "builtins.list[Any]" # flags: --check-untyped-defs class Foo: - def bad(): # E: Method must have at least one argument. Did you forget the self argument? + def bad(): # E: Method must have at least one argument. Did you forget the "self" argument? self.x = 0 # E: Name "self" is not defined [case testTypeAfterAttributeAccessWithDisallowAnyExpr] diff --git a/test-data/unit/check-functions.test b/test-data/unit/check-functions.test index 38e3e584065ea..9afe9189caaaa 100644 --- a/test-data/unit/check-functions.test +++ b/test-data/unit/check-functions.test @@ -2708,7 +2708,7 @@ class A: @dec def e(self) -> int: pass @property - def g() -> int: pass # E: Method must have at least one argument. Did you forget the self argument? + def g() -> int: pass # E: Method must have at least one argument. Did you forget the "self" argument? @property def h(self, *args, **kwargs) -> int: pass # OK [builtins fixtures/property.pyi] diff --git a/test-data/unit/check-super.test b/test-data/unit/check-super.test index d72bf8638f115..b3379e505be72 100644 --- a/test-data/unit/check-super.test +++ b/test-data/unit/check-super.test @@ -365,7 +365,7 @@ class A: def f(self) -> None: pass class B(A): - def g() -> None: # E: Method must have at least one argument. Did you forget the self argument? + def g() -> None: # E: Method must have at least one argument. Did you forget the "self" argument? super().f() # E: super() requires one or more positional arguments in enclosing function def h(self) -> None: def a() -> None: diff --git a/test-data/unit/fine-grained.test b/test-data/unit/fine-grained.test index 779697930b693..5a7f21d48c20a 100644 --- a/test-data/unit/fine-grained.test +++ b/test-data/unit/fine-grained.test @@ -1586,11 +1586,11 @@ class A: [file b.py.3] 2 [out] -a.py:3: error: Method must have at least one argument. Did you forget the self argument? +a.py:3: error: Method must have at least one argument. Did you forget the "self" argument? == -a.py:3: error: Method must have at least one argument. Did you forget the self argument? +a.py:3: error: Method must have at least one argument. Did you forget the "self" argument? == -a.py:3: error: Method must have at least one argument. Did you forget the self argument? +a.py:3: error: Method must have at least one argument. Did you forget the "self" argument? [case testBaseClassDeleted] import m @@ -2007,11 +2007,11 @@ class A: class A: def foo(self) -> int: pass [out] -a.py:2: error: Method must have at least one argument. Did you forget the self argument? +a.py:2: error: Method must have at least one argument. Did you forget the "self" argument? == -a.py:2: error: Method must have at least one argument. Did you forget the self argument? +a.py:2: error: Method must have at least one argument. Did you forget the "self" argument? == -a.py:2: error: Method must have at least one argument. Did you forget the self argument? +a.py:2: error: Method must have at least one argument. Did you forget the "self" argument? == [case testPreviousErrorInMethodSemanal2] diff --git a/test-data/unit/semanal-errors.test b/test-data/unit/semanal-errors.test index 3f34f0748a7a4..fffd02c9c3375 100644 --- a/test-data/unit/semanal-errors.test +++ b/test-data/unit/semanal-errors.test @@ -542,7 +542,7 @@ import typing class A: def f(): pass [out] -main:3: error: Method must have at least one argument. Did you forget the self argument? +main:3: error: Method must have at least one argument. Did you forget the "self" argument? [case testInvalidBaseClass] import typing @@ -564,8 +564,8 @@ class A: def f() -> None: pass def g(): pass [out] -main:3: error: Method must have at least one argument. Did you forget the self argument? -main:4: error: Method must have at least one argument. Did you forget the self argument? +main:3: error: Method must have at least one argument. Did you forget the "self" argument? +main:4: error: Method must have at least one argument. Did you forget the "self" argument? [case testMultipleMethodDefinition] import typing