Skip to content

Commit 8cee6dc

Browse files
sobolevnAlexWaygood
authored andcommitted
Now we can override attributes with methods, refs python#10134 (python#11561)
Now we can override attributes with methods. Closes python#10134 Closes python#11556 Co-authored-by: Alex Waygood <[email protected]>
1 parent 7841662 commit 8cee6dc

File tree

2 files changed

+47
-0
lines changed

2 files changed

+47
-0
lines changed

mypy/checker.py

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1536,6 +1536,16 @@ def check_method_override_for_base_with_name(
15361536
original_type = self.function_type(original_node)
15371537
elif isinstance(original_node, Decorator):
15381538
original_type = self.function_type(original_node.func)
1539+
elif isinstance(original_node, Var):
1540+
# Super type can define method as an attribute.
1541+
# See https://github.com/python/mypy/issues/10134
1542+
1543+
# We also check that sometimes `original_node.type` is None.
1544+
# This is the case when we use something like `__hash__ = None`.
1545+
if original_node.type is not None:
1546+
original_type = get_proper_type(original_node.type)
1547+
else:
1548+
original_type = NoneType()
15391549
else:
15401550
assert False, str(base_attr.node)
15411551
if isinstance(original_node, (FuncDef, OverloadedFuncDef)):

test-data/unit/check-classes.test

Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -114,6 +114,43 @@ class A:
114114
A().f = None # E: Cannot assign to a method
115115

116116

117+
[case testOverrideAttributeWithMethod]
118+
# This was crashing:
119+
# https://github.com/python/mypy/issues/10134
120+
from typing import Protocol
121+
122+
class Base:
123+
__hash__ = None
124+
125+
class Derived(Base):
126+
def __hash__(self) -> int: # E: Signature of "__hash__" incompatible with supertype "Base"
127+
pass
128+
129+
# Correct:
130+
131+
class CallableProtocol(Protocol):
132+
def __call__(self, arg: int) -> int:
133+
pass
134+
135+
class CorrectBase:
136+
attr: CallableProtocol
137+
138+
class CorrectDerived(CorrectBase):
139+
def attr(self, arg: int) -> int:
140+
pass
141+
142+
[case testOverrideMethodWithAttribute]
143+
# The reverse should not crash as well:
144+
from typing import Callable
145+
146+
class Base:
147+
def __hash__(self) -> int:
148+
pass
149+
150+
class Derived(Base):
151+
__hash__ = 1 # E: Incompatible types in assignment (expression has type "int", base class "Base" defined the type as "Callable[[Base], int]")
152+
153+
117154
-- Attributes
118155
-- ----------
119156

0 commit comments

Comments
 (0)