You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Poking around the code, AFAICT mypy doesn't do any Hashable checks. I don't see any other Protocols being checked in checker.py. Is there any existing tickets around supporting Protocols in mypy?
Pyright recently added support for this feature. It wouldn't have been possible without some significant modifications to typeshed stubs. See this, this, and this for details. Now that these changes are in typeshed, it should be relatively easy to add this check to mypy.
Reacted by Ilya Priven, Finite State Machine and JR Heard
from __future__ importannotationsfromtypingimport*fromtyping_extensionsimport (
reveal_type,
)
classSomeClass:
def__eq__(self, other: object) ->bool:
# defining '__eq__()' without defining '__hash__()' implicitly# makes instances of this class unhashable, and sets '__hash__'# to 'None'returnsuper().__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__ importannotationsfromtypingimport*fromtyping_extensionsimport (
reveal_type,
)
classSomeMeta(type):
def__eq__(self, other: object) ->bool:
# defining '__eq__()' without defining '__hash__()' implicitly# makes instances of this metaclass unhashable, and sets# '__hash__' to 'None'returnsuper().__eq__(other)
classSomeClass(metaclass=SomeMeta):
passhash(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'
Activity
gvanrossum commentedon Nov 15, 2016
Other than python/typing#11, not that I know.
ilevkivskyi commentedon Dec 18, 2019
Another example appeared in #8150. Also I think it makes to raise priority to normal as this is relatively common cause of confusion.
erictraut commentedon Aug 10, 2023
Pyright recently added support for this feature. It wouldn't have been possible without some significant modifications to typeshed stubs. See this, this, and this for details. Now that these changes are in typeshed, it should be relatively easy to add this check to mypy.
finite-state-machine commentedon Oct 30, 2023
In case it's useful to have gists/tests for this:
With regular objects:
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: