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
{{ message }}
Repository navigation
Cannot parameterise typing_extensions.Protocol with a ParamSpec or TypeVarTuple on py310+ #181
This change seems to have broken the latest version of pydash when used with typing-extensions 4.6.0. There's a bug report about this here: dgilland/pydash#197.
I did a bisect of every change between typing-extensions 4.5.0 and 4.6.0, and this was pointed out as the culprit. I've had a look at the code changes here but don't have a good enough grasp of what's going wrong that is causing this to fail.
>>> from typing_extensions import Protocol, ParamSpec
>>> P = ParamSpec("P")
>>> classFoo(Protocol[P]): ...
...
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
File "C:\Users\alexw\AppData\Local\Programs\Python\Python311\Lib\typing.py", line 344, in inner
return func(*args, **kwds)
^^^^^^^^^^^^^^^^^^^
File "C:\Users\alexw\coding\typing_extensions\src\typing_extensions.py", line 672, in __class_getitem__
raise TypeError(
TypeError: Parameters to Protocol[...] must all be type variables. Parameter 1 is ~P
Works fine on typing-extensions==4.5.0 (with Python 3.7 and Python 3.10), and also works fine if you use typing.{Protocol,ParamSpec}. So, definitely looks like a typing_extensions bug.
Interestingly, the bug only reproduces if you use Python >=3.10 (i.e., it has to be a version of Python where typing.ParamSpec is a thing for the bug to be reproducible).
We reimplement the logic from typing.Generic.__class_getitem__ in typing_extensions.Protocol.__class_getitem__. (Ideally we wouldn't have to do this, but the typing module on Python 3.7 doesn't let us have typing_extensions.Protocol subclass typing.Generic.)
The implementation of typing.Generic.__class_getitem__ changed on Python 3.10 and Python 3.11, but we haven't reflected those changes in typing_extensions.
Prior to typing_extensions==4.6.0, we only re-implemented Protocol on Python <=3.7, but now we re-implement Protocol on <=3.11. This means that the latent bug has been exposed on Python 3.10 and 3.11, hence the breakage.
changed the title [-]Protocol changes in 4.6.0 seem to have broken the latest version of pydash[/-][+]Cannot parameterise `typing_extensions.Protocol` with a `ParamSpec`[/+]on May 23, 2023
changed the title [-]Cannot parameterise `typing_extensions.Protocol` with a `ParamSpec`[/-][+]Cannot parameterise `typing_extensions.Protocol` with a `ParamSpec` on py310+[/+]on May 23, 2023
Not that anybody asked, but the bug also means that you can't parameterise a typing_extensions.Protocol with a TypeVarTuple on 3.10/3.11:
>>> from typing_extensions import*
>>> Ts = TypeVarTuple("Ts")
>>> classFoo(Protocol[*Ts]): ...
...
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
File "C:\Users\alexw\AppData\Local\Programs\Python\Python311\Lib\typing.py", line 344, in inner
return func(*args, **kwds)
^^^^^^^^^^^^^^^^^^^
File "C:\Users\alexw\coding\typing_extensions\src\typing_extensions.py", line 672, in __class_getitem__
raise TypeError(
TypeError: Parameters to Protocol[...] must all be type variables. Parameter 1 is *Ts
changed the title [-]Cannot parameterise `typing_extensions.Protocol` with a `ParamSpec` on py310+[/-][+]Cannot parameterise `typing_extensions.Protocol` with a `ParamSpec` or `TypeVarTuple` on py310+[/+]on May 23, 2023
One possible fix involves copying over the logic for Generic.__class_getitem__ from 3.12a7 to typing_extensions.Protocol.__class_getitem__. In order to do that cleanly, though, we might have to first backport some unrelated fixes that were made to Unpack in 3.11, which comes with its own risks.
I looked into whether we could instead inherit from typing.Generic on 3.8+, which would mean we wouldn't have to have a Protocol.__class_getitem__ on 3.8+. I'm still investigating that, but suffice it to say that there are complications to that approach as well.
Activity
AlexWaygood commentedon May 23, 2023
My guess is that this change might be the culprit, but haven't checked that at all: https://github.com/python/typing_extensions/pull/137/files#r1164017024
AlexWaygood commentedon May 23, 2023
Minimal repro:
Works fine on
typing-extensions==4.5.0(with Python 3.7 and Python 3.10), and also works fine if you usetyping.{Protocol,ParamSpec}. So, definitely looks like a typing_extensions bug.AlexWaygood commentedon May 23, 2023
Interestingly, the bug only reproduces if you use Python >=3.10 (i.e., it has to be a version of Python where
typing.ParamSpecis a thing for the bug to be reproducible).AlexWaygood commentedon May 23, 2023
Seems like the fundamental issue is that:
typing.Generic.__class_getitem__intyping_extensions.Protocol.__class_getitem__. (Ideally we wouldn't have to do this, but thetypingmodule on Python 3.7 doesn't let us havetyping_extensions.Protocolsubclasstyping.Generic.)typing.Generic.__class_getitem__changed on Python 3.10 and Python 3.11, but we haven't reflected those changes intyping_extensions.typing_extensions==4.6.0, we only re-implementedProtocolon Python <=3.7, but now we re-implementProtocolon <=3.11. This means that the latent bug has been exposed on Python 3.10 and 3.11, hence the breakage.[-]Protocol changes in 4.6.0 seem to have broken the latest version of pydash[/-][+]Cannot parameterise `typing_extensions.Protocol` with a `ParamSpec`[/+][-]Cannot parameterise `typing_extensions.Protocol` with a `ParamSpec`[/-][+]Cannot parameterise `typing_extensions.Protocol` with a `ParamSpec` on py310+[/+]AlexWaygood commentedon May 23, 2023
Not that anybody asked, but the bug also means that you can't parameterise a
typing_extensions.Protocolwith aTypeVarTupleon 3.10/3.11:[-]Cannot parameterise `typing_extensions.Protocol` with a `ParamSpec` on py310+[/-][+]Cannot parameterise `typing_extensions.Protocol` with a `ParamSpec` or `TypeVarTuple` on py310+[/+]JelleZijlstra commentedon May 23, 2023
Thanks @AlexWaygood for investigating! Are you working on a fix?
AlexWaygood commentedon May 23, 2023
I am looking into several potential fixes...
As usual with
typing_extensions, there are several complications to grapple with :)I also have a busy day at work, so might not be able to look at this properly until this evening!
JelleZijlstra commentedon May 23, 2023
No hurry, I can give it a try later today too.
We'll probably want to release a bugfix 4.6.1 with this fix.
AlexWaygood commentedon May 23, 2023
One possible fix involves copying over the logic for
Generic.__class_getitem__from 3.12a7 totyping_extensions.Protocol.__class_getitem__. In order to do that cleanly, though, we might have to first backport some unrelated fixes that were made toUnpackin 3.11, which comes with its own risks.I looked into whether we could instead inherit from
typing.Genericon 3.8+, which would mean we wouldn't have to have aProtocol.__class_getitem__on 3.8+. I'm still investigating that, but suffice it to say that there are complications to that approach as well.srittau commentedon May 23, 2023
Just leaving this here for posterity:

JelleZijlstra commentedon May 23, 2023
They're probably mostly referring to #179, not this issue.
srittau commentedon May 23, 2023
Possible, #158 would probably have been a more fitting issue for the screenshot. But I claim innocence in any case. :)
AlexWaygood commentedon May 23, 2023
Oh, I'm definitely guilty for this bug, if we're pointing fingers 😅
I agree with @JelleZijlstra though, there seems to be far more breakage from pydantic/pydantic#5821 than from this issue!
AlexWaygood commentedon May 23, 2023
I have a fix in the works now.