-
-
Notifications
You must be signed in to change notification settings - Fork 2.8k
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
MyPy does not enforce Hashability #2455
Comments
Other than python/typing#11, not that I know. |
Another example appeared in #8150. Also I think it makes to raise priority to normal as this is relatively common cause of confusion. |
In case it's useful to have gists/tests for this: With regular objects: from __future__ import annotations
from typing import *
from typing_extensions import (
reveal_type,
)
class SomeClass:
def __eq__(self, other: object) -> bool:
# defining '__eq__()' without defining '__hash__()' implicitly
# makes instances of this class unhashable, and sets '__hash__'
# to 'None'
return super().__eq__(other)
instance = SomeClass()
hash(instance)
# mypy actual behavior: no error issued
# mypy expected behavior: issue an error, since this fails at runtime
# runtime behavior: TypeError: unhashable type: 'SomeClass'
reveal_type(type(instance).__hash__)
# mypy actual behavior: Revealed type is "def (self: builtins.object) -> builtins.int"
# mypy expected behavior: Revealed type is "None"
# at runtime: Runtime type is 'NoneType' I had been under the impression that types were always hashable, but it seems that's not always the case if a metaclass is in play – there's nothing different or special about this case: from __future__ import annotations
from typing import *
from typing_extensions import (
reveal_type,
)
class SomeMeta(type):
def __eq__(self, other: object) -> bool:
# defining '__eq__()' without defining '__hash__()' implicitly
# makes instances of this metaclass unhashable, and sets
# '__hash__' to 'None'
return super().__eq__(other)
class SomeClass(metaclass=SomeMeta):
pass
hash(SomeClass)
# mypy actual behavior: no error issued
# mypy expected behavior: issue an error, since this fails at runtime
# runtime behavior: TypeError: unhashable type: 'SomeMeta'
reveal_type(type(SomeClass).__hash__)
# mypy actual behavior: Revealed type is "def (self: object) -> int"
# mypy expected behavior: Revealed type is "None"
# at runtime: Runtime type is 'NoneType' |
For example, the following code is illegal in Python 3 (implementing
__eq__
shadows your__hash__
implementation withNone
in Python 3)Poking around the code, AFAICT
mypy
doesn't do anyHashable
checks. I don't see any other Protocols being checked inchecker.py
. Is there any existing tickets around supporting Protocols in mypy?The text was updated successfully, but these errors were encountered: