Closed
Description
On main
, an isinstance()
check against Sized
works just the same as it does on Python 3.11:
>>> from typing import Sized
>>> isinstance(1, Sized)
False
However! If you first subclass Sized
like this, TypeError
is raised on that isinstance()
check!
>>> from typing import Sized, Protocol
>>> class Foo(Sized, Protocol): pass
...
>>> isinstance(1, Sized)
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
File "C:\Users\alexw\coding\cpython\Lib\typing.py", line 1153, in __instancecheck__
return self.__subclasscheck__(type(obj))
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "C:\Users\alexw\coding\cpython\Lib\typing.py", line 1428, in __subclasscheck__
return issubclass(cls, self.__origin__)
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "<frozen abc>", line 123, in __subclasscheck__
File "C:\Users\alexw\coding\cpython\Lib\typing.py", line 1793, in __subclasscheck__
return super().__subclasscheck__(other)
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "<frozen abc>", line 123, in __subclasscheck__
File "C:\Users\alexw\coding\cpython\Lib\typing.py", line 1876, in _proto_hook
raise TypeError("Instance and class checks can only be used with"
TypeError: Instance and class checks can only be used with @runtime_checkable protocols
This was originally reported by @vnmabus in python/typing_extensions#207.
Note that (because of the abc
-module cache), this doesn't reproduce if you do an isinstance()
check before subclassing typing.Sized
:
>>> import typing
>>> isinstance(1, typing.Sized)
False
>>> class Foo(typing.Sized, typing.Protocol): pass
...
>>> isinstance(1, typing.Sized)
False
Linked PRs
- gh-105144: Runtime-checkable protocols: move all 'sanity checks' to
_ProtocolMeta.__subclasscheck__
#105152 - gh-105144: abc: Suppress errors raised by unrelated other subclasses #105159
- [3.12] gh-105144: Runtime-checkable protocols: move all 'sanity checks' to
_ProtocolMeta.__subclasscheck__
(GH-105152) #105160