python / python/typing_extensions

`IntFloatTuple` from PEP 646 doesn't work as expected on Python<3.11

Open
#103 2 comments 1 reaction 0 assignees View on GitHub

Nobody has claimed this yet.

pep-646
Dominant language
Python
Stars
583
Forks
146
Avg merge
10h 11m
Merged PRs (30d)
5

Description

I was working on serialization / deserialization logic for the new PEP 646 in mashumaro, but unfortunately the following example from https://peps.python.org/pep-0646/#type-arguments-can-be-variadic doesn't work as expected on older python versions with typing-extensions 4.4.0:

from typing import Tuple, TypeVar
from typing_extensions import TypeVarTuple, Unpack, get_args


K = TypeVar("K")
T = TypeVar("T")
Ts = TypeVarTuple("Ts")

Ts1 = TypeVarTuple("Ts1")
Ts2 = TypeVarTuple("Ts2")
IntTuple = Tuple[int, Unpack[Ts1]]
IntFloatTuple = IntTuple[float, Unpack[Ts2]]

print(IntFloatTuple.__args__)
print(get_args(IntFloatTuple))

The PEP said:

Here, *Ts1 in the IntTuple alias is bound to Tuple[float, *Ts2], resulting in an alias IntFloatTuple equivalent to Tuple[int, float, *Ts2].

On python 3.11.0 it works seamlessly as expected:

print(IntFloatTuple.__args__)
# (<class 'int'>, <class 'float'>, *Ts2)

On python 3.10.9 it produces error on IntFloatTuple = IntTuple[float, Unpack[Ts2]]:

Traceback (most recent call last):
  File "/Users/alexander.tikhonov/projects/mashumaro/pep_646.py", line 12, in <module>
    IntFloatTuple = IntTuple[float, Unpack[Ts2]]
  File "/Users/alexander.tikhonov/.pyenv/versions/3.10.9/lib/python3.10/typing.py", line 309, in inner
    return cached(*args, **kwds)
  File "/Users/alexander.tikhonov/.pyenv/versions/3.10.9/lib/python3.10/typing.py", line 1070, in __getitem__
    arg = subst[arg]
KeyError: typing_extensions.Unpack[Ts1]

On python 3.9.16 it produces the same error on IntFloatTuple = IntTuple[float, Unpack[Ts2]]:

Traceback (most recent call last):
  File "/Users/alexander.tikhonov/projects/mashumaro/pep_646.py", line 12, in <module>
    IntFloatTuple = IntTuple[float, Unpack[Ts2]]
  File "/Users/alexander.tikhonov/.pyenv/versions/3.9.16/lib/python3.9/typing.py", line 274, in inner
    return cached(*args, **kwds)
  File "/Users/alexander.tikhonov/.pyenv/versions/3.9.16/lib/python3.9/typing.py", line 774, in __getitem__
    arg = subst[arg]
KeyError: typing_extensions.Unpack[Ts1]

On python 3.8.16 it produces wrong result:

print(IntFloatTuple.__args__)
(<class 'int'>, typing_extensions.Unpack[Ts1])
print(get_args(IntFloatTuple))
# (<class 'int'>, typing_extensions.Unpack[Ts1])

On python 3.7.16 it produces the same wrong result:

print(IntFloatTuple.__args__)
# (<class 'int'>, typing_extensions.Unpack[Ts1])
print(get_args(IntFloatTuple))
# (<class 'int'>, typing_extensions.Unpack[Ts1])

I couldn't figure out how to get type arguments the same on all python versions, and so it stops me from full support for variadic generics. At the moment I have to skip some tests like this one on python<3.11.

P.S. This problem also affects IntFloatsTuple = IntTuple[Unpack[Tuple[float, ...]]].

Contributor guide

Open the contributing guide

First steps

  1. Read the whole issue, then the project's contributing guide.
  2. Comment on the issue to say you are picking it up — it saves two people doing the same work.
  3. Fork the repository and make your change on a branch.
  4. Open a pull request that references the issue number.

Research direction

Start with the PEP 646 example in the issue and compare its behavior across the reported Python versions with typing-extensions 4.4.0. Then inspect the skipped cases in tests/test_pep_646.py around lines 392-408; done means nested variadic aliases produce consistent type arguments on supported older versions.

Written by the indexing model from the issue text.

Assessment

Tech stack
python
Domain
tooling
Issue type
Bug
Difficulty
4/5
Estimated time
3-5 days
Activity status
Stale
Clarity
Mostly clear
Newbie friendliness
35/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.