Skip to content

Commit

Permalink
Now we can override attributes with methods, refs python#10134 (pytho…
Browse files Browse the repository at this point in the history
…n#11561)

Now we can override attributes with methods.

Closes python#10134
Closes python#11556

Co-authored-by: Alex Waygood <[email protected]>
  • Loading branch information
2 people authored and tushar-deepsource committed Jan 20, 2022
1 parent 7841662 commit 8cee6dc
Show file tree
Hide file tree
Showing 2 changed files with 47 additions and 0 deletions.
10 changes: 10 additions & 0 deletions mypy/checker.py
Original file line number Diff line number Diff line change
Expand Up @@ -1536,6 +1536,16 @@ def check_method_override_for_base_with_name(
original_type = self.function_type(original_node)
elif isinstance(original_node, Decorator):
original_type = self.function_type(original_node.func)
elif isinstance(original_node, Var):
# Super type can define method as an attribute.
# See https://github.com/python/mypy/issues/10134

# We also check that sometimes `original_node.type` is None.
# This is the case when we use something like `__hash__ = None`.
if original_node.type is not None:
original_type = get_proper_type(original_node.type)
else:
original_type = NoneType()
else:
assert False, str(base_attr.node)
if isinstance(original_node, (FuncDef, OverloadedFuncDef)):
Expand Down
37 changes: 37 additions & 0 deletions test-data/unit/check-classes.test
Original file line number Diff line number Diff line change
Expand Up @@ -114,6 +114,43 @@ class A:
A().f = None # E: Cannot assign to a method


[case testOverrideAttributeWithMethod]
# This was crashing:
# https://github.com/python/mypy/issues/10134
from typing import Protocol

class Base:
__hash__ = None

class Derived(Base):
def __hash__(self) -> int: # E: Signature of "__hash__" incompatible with supertype "Base"
pass

# Correct:

class CallableProtocol(Protocol):
def __call__(self, arg: int) -> int:
pass

class CorrectBase:
attr: CallableProtocol

class CorrectDerived(CorrectBase):
def attr(self, arg: int) -> int:
pass

[case testOverrideMethodWithAttribute]
# The reverse should not crash as well:
from typing import Callable

class Base:
def __hash__(self) -> int:
pass

class Derived(Base):
__hash__ = 1 # E: Incompatible types in assignment (expression has type "int", base class "Base" defined the type as "Callable[[Base], int]")


-- Attributes
-- ----------

Expand Down

0 comments on commit 8cee6dc

Please sign in to comment.