Search code examples
pythoninheritanceprotocolspython-typing

How can you test that a python typing Protocol is a subclass of another Protocol?


The obvious solution to the problem is to use issubclass, but this raises TypeError (using Python 3.6.7), e.g.

>>> from typing_extensions import Protocol
>>> class ProtoSubclass(Protocol):
...     pass
... 
>>> issubclass(ProtoSubclass, Protocol)
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "/opt/conda/envs/airflow/lib/python3.6/site-packages/typing_extensions.py", line 1265, in __subclasscheck__
    raise TypeError("Instance and class checks can only be used with"
TypeError: Instance and class checks can only be used with @runtime protocols
>>> from typing_extensions import runtime
>>> @runtime
... class ProtoSubclass(Protocol):
...     pass
... 
>>> issubclass(ProtoSubclass, Protocol)
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "/opt/conda/envs/airflow/lib/python3.6/site-packages/typing_extensions.py", line 1265, in __subclasscheck__
    raise TypeError("Instance and class checks can only be used with"
TypeError: Instance and class checks can only be used with @runtime protocols

Solution

  • For more on the topic of python Protocols, see

    In Python 3.6.7, one way to solve this is to use the @runtime_checkable decorator:

    >>> from typing_extensions import Protocol
    >>> from typing_extensions import runtime_checkable
    
    >>> @runtime_checkable
    ... class CustomProtocol(Protocol):
    ...     def custom(self):
    ...         ...
    ... 
    
    >>> @runtime_checkable
    ... class ExtendedCustomProtocol(CustomProtocol, Protocol):
    ...     def extended(self):
    ...         ...
    ... 
    
    >>> issubclass(ExtendedCustomProtocol, CustomProtocol)
    True