Skip to content

Commit 620e281

Browse files
Do not report plugin-generated methods with explicit-override (#17433)
Closes typeddjango/django-stubs#2226 Closes #17417 Closes #17370 Closes #17224 This is an alternative to #17418 Thanks a lot to @sterliakov, I took a dataclasses test case from #17370 --------- Co-authored-by: pre-commit-ci[bot] <66853113+pre-commit-ci[bot]@users.noreply.github.com>
1 parent 18945af commit 620e281

File tree

4 files changed

+78
-1
lines changed

4 files changed

+78
-1
lines changed

mypy/checker.py

+8-1
Original file line numberDiff line numberDiff line change
@@ -1938,8 +1938,15 @@ def check_explicit_override_decorator(
19381938
found_method_base_classes: list[TypeInfo] | None,
19391939
context: Context | None = None,
19401940
) -> None:
1941+
plugin_generated = False
1942+
if defn.info and (node := defn.info.get(defn.name)) and node.plugin_generated:
1943+
# Do not report issues for plugin generated nodes,
1944+
# they can't realistically use `@override` for their methods.
1945+
plugin_generated = True
1946+
19411947
if (
1942-
found_method_base_classes
1948+
not plugin_generated
1949+
and found_method_base_classes
19431950
and not defn.is_explicit_override
19441951
and defn.name not in ("__init__", "__new__")
19451952
and not is_private(defn.name)

test-data/unit/check-custom-plugin.test

+33
Original file line numberDiff line numberDiff line change
@@ -1050,6 +1050,39 @@ reveal_type(my_class.stmethod) # N: Revealed type is "Overload(def (arg: builti
10501050
\[mypy]
10511051
plugins=<ROOT>/test-data/unit/plugins/add_overloaded_method.py
10521052

1053+
[case testAddMethodPluginExplicitOverride]
1054+
# flags: --python-version 3.12 --config-file tmp/mypy.ini
1055+
from typing import override, TypeVar
1056+
1057+
T = TypeVar('T', bound=type)
1058+
1059+
def inject_foo(t: T) -> T:
1060+
# Imitates:
1061+
# t.foo_implicit = some_method
1062+
return t
1063+
1064+
class BaseWithoutFoo: pass
1065+
1066+
@inject_foo
1067+
class ChildWithFoo(BaseWithoutFoo): pass
1068+
reveal_type(ChildWithFoo.foo_implicit) # N: Revealed type is "def (self: __main__.ChildWithFoo)"
1069+
1070+
@inject_foo
1071+
class SomeWithFoo(ChildWithFoo): pass
1072+
reveal_type(SomeWithFoo.foo_implicit) # N: Revealed type is "def (self: __main__.SomeWithFoo)"
1073+
1074+
class ExplicitOverride(SomeWithFoo):
1075+
@override
1076+
def foo_implicit(self) -> None: pass
1077+
1078+
class ImplicitOverride(SomeWithFoo):
1079+
def foo_implicit(self) -> None: pass # E: Method "foo_implicit" is not using @override but is overriding a method in class "__main__.SomeWithFoo"
1080+
[file mypy.ini]
1081+
\[mypy]
1082+
plugins=<ROOT>/test-data/unit/plugins/add_method.py
1083+
enable_error_code = explicit-override
1084+
[typing fixtures/typing-override.pyi]
1085+
10531086
[case testCustomErrorCodePlugin]
10541087
# flags: --config-file tmp/mypy.ini --show-error-codes
10551088
def main() -> int:

test-data/unit/check-dataclasses.test

+14
Original file line numberDiff line numberDiff line change
@@ -2475,3 +2475,17 @@ class Base:
24752475
class Child(Base):
24762476
y: int
24772477
[builtins fixtures/dataclasses.pyi]
2478+
2479+
2480+
[case testDataclassInheritanceWorksWithExplicitOverridesAndOrdering]
2481+
# flags: --enable-error-code explicit-override
2482+
from dataclasses import dataclass
2483+
2484+
@dataclass(order=True)
2485+
class Base:
2486+
x: int
2487+
2488+
@dataclass(order=True)
2489+
class Child(Base):
2490+
y: int
2491+
[builtins fixtures/dataclasses.pyi]

test-data/unit/plugins/add_method.py

+23
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
from __future__ import annotations
2+
3+
from typing import Callable
4+
5+
from mypy.plugin import ClassDefContext, Plugin
6+
from mypy.plugins.common import add_method
7+
from mypy.types import NoneType
8+
9+
10+
class AddOverrideMethodPlugin(Plugin):
11+
def get_class_decorator_hook_2(self, fullname: str) -> Callable[[ClassDefContext], bool] | None:
12+
if fullname == "__main__.inject_foo":
13+
return add_extra_methods_hook
14+
return None
15+
16+
17+
def add_extra_methods_hook(ctx: ClassDefContext) -> bool:
18+
add_method(ctx, "foo_implicit", [], NoneType())
19+
return True
20+
21+
22+
def plugin(version: str) -> type[AddOverrideMethodPlugin]:
23+
return AddOverrideMethodPlugin

0 commit comments

Comments
 (0)