-
-
Notifications
You must be signed in to change notification settings - Fork 3k
Add strict_override_decorator
option (PEP 698)
#15512
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from 6 commits
7fef24f
537e794
6e40627
b33386c
e4d7096
d2ae2ab
2a55f90
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change | ||||||||||||||||||||||
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
|
@@ -2759,8 +2759,7 @@ class E(D): pass | |||||||||||||||||||||||
class F(E): | ||||||||||||||||||||||||
@override | ||||||||||||||||||||||||
def f(self, x: int) -> str: pass | ||||||||||||||||||||||||
[typing fixtures/typing-full.pyi] | ||||||||||||||||||||||||
[builtins fixtures/tuple.pyi] | ||||||||||||||||||||||||
[typing fixtures/typing-override.pyi] | ||||||||||||||||||||||||
|
||||||||||||||||||||||||
[case explicitOverrideStaticmethod] | ||||||||||||||||||||||||
# flags: --python-version 3.12 | ||||||||||||||||||||||||
|
@@ -2792,8 +2791,8 @@ class D(A): | |||||||||||||||||||||||
def f(x: str) -> str: pass # E: Argument 1 of "f" is incompatible with supertype "A"; supertype defines the argument type as "int" \ | ||||||||||||||||||||||||
# N: This violates the Liskov substitution principle \ | ||||||||||||||||||||||||
# N: See https://mypy.readthedocs.io/en/stable/common_issues.html#incompatible-overrides | ||||||||||||||||||||||||
[typing fixtures/typing-full.pyi] | ||||||||||||||||||||||||
[builtins fixtures/callable.pyi] | ||||||||||||||||||||||||
[typing fixtures/typing-override.pyi] | ||||||||||||||||||||||||
[builtins fixtures/staticmethod.pyi] | ||||||||||||||||||||||||
|
||||||||||||||||||||||||
[case explicitOverrideClassmethod] | ||||||||||||||||||||||||
# flags: --python-version 3.12 | ||||||||||||||||||||||||
|
@@ -2825,8 +2824,8 @@ class D(A): | |||||||||||||||||||||||
def f(cls, x: str) -> str: pass # E: Argument 1 of "f" is incompatible with supertype "A"; supertype defines the argument type as "int" \ | ||||||||||||||||||||||||
# N: This violates the Liskov substitution principle \ | ||||||||||||||||||||||||
# N: See https://mypy.readthedocs.io/en/stable/common_issues.html#incompatible-overrides | ||||||||||||||||||||||||
[typing fixtures/typing-full.pyi] | ||||||||||||||||||||||||
[builtins fixtures/callable.pyi] | ||||||||||||||||||||||||
[typing fixtures/typing-override.pyi] | ||||||||||||||||||||||||
[builtins fixtures/classmethod.pyi] | ||||||||||||||||||||||||
|
||||||||||||||||||||||||
[case explicitOverrideProperty] | ||||||||||||||||||||||||
# flags: --python-version 3.12 | ||||||||||||||||||||||||
|
@@ -2860,8 +2859,8 @@ class D(A): | |||||||||||||||||||||||
# N: str \ | ||||||||||||||||||||||||
# N: Subclass: \ | ||||||||||||||||||||||||
# N: int | ||||||||||||||||||||||||
[typing fixtures/typing-override.pyi] | ||||||||||||||||||||||||
[builtins fixtures/property.pyi] | ||||||||||||||||||||||||
[typing fixtures/typing-full.pyi] | ||||||||||||||||||||||||
|
||||||||||||||||||||||||
[case explicitOverrideSettableProperty] | ||||||||||||||||||||||||
# flags: --python-version 3.12 | ||||||||||||||||||||||||
|
@@ -2898,8 +2897,8 @@ class D(A): | |||||||||||||||||||||||
|
||||||||||||||||||||||||
@f.setter | ||||||||||||||||||||||||
def f(self, value: int) -> None: pass | ||||||||||||||||||||||||
[typing fixtures/typing-override.pyi] | ||||||||||||||||||||||||
[builtins fixtures/property.pyi] | ||||||||||||||||||||||||
[typing fixtures/typing-full.pyi] | ||||||||||||||||||||||||
|
||||||||||||||||||||||||
[case invalidExplicitOverride] | ||||||||||||||||||||||||
# flags: --python-version 3.12 | ||||||||||||||||||||||||
|
@@ -2914,8 +2913,7 @@ class A: pass | |||||||||||||||||||||||
def g() -> None: | ||||||||||||||||||||||||
@override # E: "override" used with a non-method | ||||||||||||||||||||||||
def h(b: bool) -> int: pass | ||||||||||||||||||||||||
[typing fixtures/typing-full.pyi] | ||||||||||||||||||||||||
[builtins fixtures/tuple.pyi] | ||||||||||||||||||||||||
[typing fixtures/typing-override.pyi] | ||||||||||||||||||||||||
|
||||||||||||||||||||||||
[case explicitOverrideSpecialMethods] | ||||||||||||||||||||||||
# flags: --python-version 3.12 | ||||||||||||||||||||||||
|
@@ -2931,8 +2929,7 @@ class B(A): | |||||||||||||||||||||||
class C: | ||||||||||||||||||||||||
@override | ||||||||||||||||||||||||
def __init__(self, a: int) -> None: pass | ||||||||||||||||||||||||
[typing fixtures/typing-full.pyi] | ||||||||||||||||||||||||
[builtins fixtures/tuple.pyi] | ||||||||||||||||||||||||
[typing fixtures/typing-override.pyi] | ||||||||||||||||||||||||
|
||||||||||||||||||||||||
[case explicitOverrideFromExtensions] | ||||||||||||||||||||||||
from typing_extensions import override | ||||||||||||||||||||||||
|
@@ -2943,7 +2940,6 @@ class A: | |||||||||||||||||||||||
class B(A): | ||||||||||||||||||||||||
@override | ||||||||||||||||||||||||
def f2(self, x: int) -> str: pass # E: Method "f2" is marked as an override, but no base method was found with this name | ||||||||||||||||||||||||
[typing fixtures/typing-full.pyi] | ||||||||||||||||||||||||
[builtins fixtures/tuple.pyi] | ||||||||||||||||||||||||
|
||||||||||||||||||||||||
[case explicitOverrideOverloads] | ||||||||||||||||||||||||
|
@@ -2960,8 +2956,7 @@ class B(A): | |||||||||||||||||||||||
def f2(self, x: str) -> str: pass | ||||||||||||||||||||||||
@override | ||||||||||||||||||||||||
def f2(self, x: int | str) -> str: pass | ||||||||||||||||||||||||
[typing fixtures/typing-full.pyi] | ||||||||||||||||||||||||
[builtins fixtures/tuple.pyi] | ||||||||||||||||||||||||
[typing fixtures/typing-override.pyi] | ||||||||||||||||||||||||
|
||||||||||||||||||||||||
[case explicitOverrideNotOnOverloadsImplementation] | ||||||||||||||||||||||||
# flags: --python-version 3.12 | ||||||||||||||||||||||||
|
@@ -2985,8 +2980,7 @@ class C(A): | |||||||||||||||||||||||
@overload | ||||||||||||||||||||||||
def f(self, y: str) -> str: pass | ||||||||||||||||||||||||
def f(self, y: int | str) -> str: pass | ||||||||||||||||||||||||
[typing fixtures/typing-full.pyi] | ||||||||||||||||||||||||
[builtins fixtures/tuple.pyi] | ||||||||||||||||||||||||
[typing fixtures/typing-override.pyi] | ||||||||||||||||||||||||
|
||||||||||||||||||||||||
[case explicitOverrideOnMultipleOverloads] | ||||||||||||||||||||||||
# flags: --python-version 3.12 | ||||||||||||||||||||||||
|
@@ -3012,5 +3006,122 @@ class C(A): | |||||||||||||||||||||||
def f(self, y: str) -> str: pass | ||||||||||||||||||||||||
@override | ||||||||||||||||||||||||
def f(self, y: int | str) -> str: pass | ||||||||||||||||||||||||
[typing fixtures/typing-full.pyi] | ||||||||||||||||||||||||
[typing fixtures/typing-override.pyi] | ||||||||||||||||||||||||
|
||||||||||||||||||||||||
[case explicitOverrideCyclicDependency] | ||||||||||||||||||||||||
# flags: --python-version 3.12 | ||||||||||||||||||||||||
import b | ||||||||||||||||||||||||
[file a.py] | ||||||||||||||||||||||||
from typing import override | ||||||||||||||||||||||||
import b | ||||||||||||||||||||||||
import c | ||||||||||||||||||||||||
|
||||||||||||||||||||||||
class A(b.B): | ||||||||||||||||||||||||
@override # This is fine | ||||||||||||||||||||||||
@c.deco | ||||||||||||||||||||||||
def meth(self) -> int: ... | ||||||||||||||||||||||||
[file b.py] | ||||||||||||||||||||||||
import a | ||||||||||||||||||||||||
import c | ||||||||||||||||||||||||
|
||||||||||||||||||||||||
class B: | ||||||||||||||||||||||||
@c.deco | ||||||||||||||||||||||||
def meth(self) -> int: ... | ||||||||||||||||||||||||
[file c.py] | ||||||||||||||||||||||||
from typing import TypeVar, Tuple, Callable | ||||||||||||||||||||||||
T = TypeVar('T') | ||||||||||||||||||||||||
def deco(f: Callable[..., T]) -> Callable[..., Tuple[T, int]]: ... | ||||||||||||||||||||||||
[builtins fixtures/tuple.pyi] | ||||||||||||||||||||||||
[typing fixtures/typing-override.pyi] | ||||||||||||||||||||||||
|
||||||||||||||||||||||||
[case requireExplicitOverrideMethod] | ||||||||||||||||||||||||
# flags: --strict-override-decorator --python-version 3.12 | ||||||||||||||||||||||||
from typing import override | ||||||||||||||||||||||||
|
||||||||||||||||||||||||
class A: | ||||||||||||||||||||||||
def f(self, x: int) -> str: pass | ||||||||||||||||||||||||
|
||||||||||||||||||||||||
class B(A): | ||||||||||||||||||||||||
@override | ||||||||||||||||||||||||
def f(self, y: int) -> str: pass | ||||||||||||||||||||||||
|
||||||||||||||||||||||||
class C(A): | ||||||||||||||||||||||||
def f(self, y: int) -> str: pass # E: Method "f" is not marked as override but is overriding a method in class "__main__.A" | ||||||||||||||||||||||||
|
||||||||||||||||||||||||
class D(B): | ||||||||||||||||||||||||
def f(self, y: int) -> str: pass # E: Method "f" is not marked as override but is overriding a method in class "__main__.B" | ||||||||||||||||||||||||
[typing fixtures/typing-override.pyi] | ||||||||||||||||||||||||
cdce8p marked this conversation as resolved.
Show resolved
Hide resolved
|
||||||||||||||||||||||||
|
||||||||||||||||||||||||
[case requireExplicitOverrideSpecialMethod] | ||||||||||||||||||||||||
# flags: --strict-override-decorator --python-version 3.12 | ||||||||||||||||||||||||
from typing import Self, override | ||||||||||||||||||||||||
|
||||||||||||||||||||||||
# Don't require override decorator for __init__ and __new__ | ||||||||||||||||||||||||
# See: https://github.com/python/typing/issues/1376 | ||||||||||||||||||||||||
class A: | ||||||||||||||||||||||||
def __init__(self) -> None: pass | ||||||||||||||||||||||||
def __new__(cls) -> Self: pass | ||||||||||||||||||||||||
[typing fixtures/typing-override.pyi] | ||||||||||||||||||||||||
|
||||||||||||||||||||||||
[case requireExplicitOverrideProperty] | ||||||||||||||||||||||||
# flags: --strict-override-decorator --python-version 3.12 | ||||||||||||||||||||||||
from typing import override | ||||||||||||||||||||||||
|
||||||||||||||||||||||||
class A: | ||||||||||||||||||||||||
@property | ||||||||||||||||||||||||
def prop(self) -> int: pass | ||||||||||||||||||||||||
|
||||||||||||||||||||||||
class B(A): | ||||||||||||||||||||||||
@override | ||||||||||||||||||||||||
@property | ||||||||||||||||||||||||
def prop(self) -> int: pass | ||||||||||||||||||||||||
|
||||||||||||||||||||||||
class C(A): | ||||||||||||||||||||||||
@property | ||||||||||||||||||||||||
def prop(self) -> int: pass # E: Method "prop" is not marked as override but is overriding a method in class "__main__.A" | ||||||||||||||||||||||||
[typing fixtures/typing-override.pyi] | ||||||||||||||||||||||||
[builtins fixtures/property.pyi] | ||||||||||||||||||||||||
|
||||||||||||||||||||||||
[case requireExplicitOverrideOverload] | ||||||||||||||||||||||||
# flags: --strict-override-decorator --python-version 3.12 | ||||||||||||||||||||||||
from typing import overload, override | ||||||||||||||||||||||||
|
||||||||||||||||||||||||
class A: | ||||||||||||||||||||||||
@overload | ||||||||||||||||||||||||
def f(self, x: int) -> str: ... | ||||||||||||||||||||||||
@overload | ||||||||||||||||||||||||
def f(self, x: str) -> str: ... | ||||||||||||||||||||||||
def f(self, x): pass | ||||||||||||||||||||||||
|
||||||||||||||||||||||||
class B(A): | ||||||||||||||||||||||||
@overload | ||||||||||||||||||||||||
def f(self, y: int) -> str: ... | ||||||||||||||||||||||||
@overload | ||||||||||||||||||||||||
def f(self, y: str) -> str: ... | ||||||||||||||||||||||||
@override | ||||||||||||||||||||||||
cdce8p marked this conversation as resolved.
Show resolved
Hide resolved
|
||||||||||||||||||||||||
def f(self, y): pass | ||||||||||||||||||||||||
|
||||||||||||||||||||||||
class C(A): | ||||||||||||||||||||||||
@overload | ||||||||||||||||||||||||
def f(self, y: int) -> str: ... | ||||||||||||||||||||||||
@overload | ||||||||||||||||||||||||
def f(self, y: str) -> str: ... | ||||||||||||||||||||||||
def f(self, y): pass # E: Method "f" is not marked as override but is overriding a method in class "__main__.A" | ||||||||||||||||||||||||
[typing fixtures/typing-override.pyi] | ||||||||||||||||||||||||
|
||||||||||||||||||||||||
[case requireExplicitOverrideMultipleInheritance] | ||||||||||||||||||||||||
# flags: --strict-override-decorator --python-version 3.12 | ||||||||||||||||||||||||
from typing import override | ||||||||||||||||||||||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Test using There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I rather not do that. Since none of our test fixtures use There is also a test case for an unused mypy/test-data/unit/check-functions.test Lines 2937 to 2947 in 67cc059
|
||||||||||||||||||||||||
|
||||||||||||||||||||||||
class A: | ||||||||||||||||||||||||
def f(self, x: int) -> str: pass | ||||||||||||||||||||||||
class B: | ||||||||||||||||||||||||
def f(self, y: int) -> str: pass | ||||||||||||||||||||||||
|
||||||||||||||||||||||||
class C(A, B): | ||||||||||||||||||||||||
@override | ||||||||||||||||||||||||
def f(self, z: int) -> str: pass | ||||||||||||||||||||||||
|
||||||||||||||||||||||||
class D(A, B): | ||||||||||||||||||||||||
def f(self, z: int) -> str: pass # E: Method "f" is not marked as override but is overriding a method in class "__main__.A" | ||||||||||||||||||||||||
[typing fixtures/typing-override.pyi] |
Uh oh!
There was an error while loading. Please reload this page.