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
In typing.py, a number of built-in protocols extend from Generic, not Protocol (eg Iterable, Container, Sized, etc). However, at runtime the Procotol class enforces that all bases for a class also inherit from Protocol. Thus the following code
TypeError: Protocols can only inherit from other protocols, got typing.Iterable
This is further confused by the fact that, in recent versions of typeshed, typing.pyi has these types like Iterable extending Protocol and notGeneric (opposite of runtime, but also seemingly the more "correct" version).
Hitting the same issue -- is there a known workaround, or do I just rip out type hints from anything that requires structural subtyping until this is fixed?
$ pipenv graph
typing-extensions==3.6.5
$ pipenv run python
Python 3.6.5 (default, Apr 4 2018, 15:01:18)
[GCC 7.3.1 20180303 (Red Hat 7.3.1-5)] on linux
Type "help", "copyright", "credits" or "license" for more information.
>>> from typing import Iterable, TypeVar
>>> from typing_extensions import Protocol
>>>
>>> T = TypeVar('T')
>>>
>>> class Foo(Iterable[T], Protocol[T]):
... pass
...
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
File "/home/lihu/.local/share/virtualenvs/Documents-8_-tGN99/lib/python3.6/site-packages/typing_extensions.py", line 852, in __init__
' protocols, got %r' % base)
TypeError: Protocols can only inherit from other protocols, got typing.Iterable
>>>
Thanks for your responses, and all the work you do here!
I wanted to work on this last weekend, but didn't have time. I think the real fix would be to just allow subclassing collections.Iterable etc. I could imagine it will be a common use case to extend a "built-in" protocol. I will tae care of this as soon as I will have some free time.
I wanted to write that this is now solved in newly released typing/typing_extensions 3.7.4, but there is a little problem. I discovered that my fix for extending builtin protocols doesn't always work. Namely, subclassing Protocol together with collections[.abc].Iterable seems to work on all Python versions, but subclassing Protocol together with typing.Iterable only works on Python 3.7+ (because of PEP 560).
Necrobump. Although this issue remains unresolved, a real-world solution finally arises. Courtesy beartype's typing compatibility API, PEP 544-compliant protocols subclassing beartype.typing.Protocol (rather than either typing.Protocol or typing_extensions.Protocol) transparently support subclassing from non-protocol superclasses:
# This is fine.>>>frombeartype.typingimportIterable, Protocol, TypeVar>>>T=TypeVar('T')
>>>classFoo(Iterable[T], Protocol[T]): pass# This is fine, too.>>>importcollections>>>issubclass(Foo, collections.abc.Iterable)
True>>>isinstance(('bar',), Foo)
True# Actual structural subtyping or it didn't happen.>>>classZed(Iterable[T], Protocol[T]):
... defzeds_dead_baby(self): pass>>>classWhosZed(tuple):
... defzeds_dead_baby(self): pass>>>issubclass(WhosZed, Zed)
True>>>isinstance(WhosZed("Whose motorcycle is this?"), Zed)
True>>>isinstance(("It's a chopper, baby."), Zed)
False
As the principal maintainer of @beartype,...hi! I'm as surprised as you are. 😮
Activity
lihu-zhong commentedon Jun 20, 2018
Hitting the same issue -- is there a known workaround, or do I just rip out type hints from anything that requires structural subtyping until this is fixed?
gvanrossum commentedon Jun 20, 2018
To both reporters: Exactly which versions of Python, typing (unless in the stdib), and typing_extensions did you use?
JelleZijlstra commentedon Jun 20, 2018
Also, a workaround (haven't tested) is to do something like this:
(The second branch can probably also still inherit from Iterable.)
lihu-zhong commentedon Jun 20, 2018
Thanks for your responses, and all the work you do here!
gvanrossum commentedon Jun 20, 2018
ilevkivskyi commentedon Jun 20, 2018
I wanted to work on this last weekend, but didn't have time. I think the real fix would be to just allow subclassing
collections.Iterableetc. I could imagine it will be a common use case to extend a "built-in" protocol. I will tae care of this as soon as I will have some free time.gvanrossum commentedon Jun 20, 2018
ilevkivskyi commentedon Jun 20, 2019
I wanted to write that this is now solved in newly released
typing/typing_extensions3.7.4, but there is a little problem. I discovered that my fix for extending builtin protocols doesn't always work. Namely, subclassingProtocoltogether withcollections[.abc].Iterableseems to work on all Python versions, but subclassingProtocoltogether withtyping.Iterableonly works on Python 3.7+ (because of PEP 560).srittau commentedon Nov 4, 2021
If this is still a problem, it should be reported to bugs.python.org.
leycec commentedon Jun 2, 2022
Necrobump. Although this issue remains unresolved, a real-world solution finally arises. Courtesy
beartype'stypingcompatibility API, PEP 544-compliant protocols subclassingbeartype.typing.Protocol(rather than eithertyping.Protocolortyping_extensions.Protocol) transparently support subclassing from non-protocol superclasses:As the principal maintainer of @beartype,...hi! I'm as surprised as you are. 😮