Skip to content

Commit 8f202cf

Browse files
committed
gh-158981: Fix subscripting generic aliases that omit a parameter with a default
Make typing._unpack_args() return a tuple, like its C counterpart in Objects/genericaliasobject.c, so that TypeVar and TypeVarTuple defaults are applied correctly.
1 parent 9d22a53 commit 8f202cf

3 files changed

Lines changed: 28 additions & 1 deletion

File tree

‎Lib/test/test_typing.py‎

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -737,6 +737,28 @@ def test_allow_default_after_non_default_in_alias(self):
737737
a4 = Callable[*Ts, T]
738738
self.assertEqual(a4.__args__, (*Ts, T))
739739

740+
def test_typevar_default_in_alias_specialization(self):
741+
T = TypeVar('T')
742+
D = TypeVar('D', default=int)
743+
class A(Generic[T, D]): ...
744+
745+
self.assertEqual(Dict[T, D][str], Dict[str, int])
746+
self.assertEqual(Tuple[T, D][str], Tuple[str, int])
747+
self.assertEqual(Callable[[T], D][str], Callable[[str], int])
748+
self.assertEqual(A[T, D][str].__args__, (str, int))
749+
self.assertEqual(dict[T, D][str], dict[str, int])
750+
self.assertEqual(Dict[T, D][str, bytes], Dict[str, bytes])
751+
752+
def test_typevartuple_default_in_alias_specialization(self):
753+
T = TypeVar('T')
754+
Ts = TypeVarTuple('Ts', default=Unpack[Tuple[int, str]])
755+
756+
self.assertEqual(Tuple[bool, *Ts][()].__args__, (bool, int, str))
757+
self.assertEqual(tuple[bool, *Ts][()].__args__, (bool, int, str))
758+
self.assertEqual(tuple[*Ts][()].__args__, (int, str))
759+
self.assertEqual(tuple[T, *Ts][bool].__args__, (bool, int, str))
760+
self.assertEqual(tuple[T, *Ts][bool, bytes].__args__, (bool, bytes))
761+
740762
def test_paramspec_specialization(self):
741763
T = TypeVar("T")
742764
P = ParamSpec('P', default=[str, int])

‎Lib/typing.py‎

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -363,7 +363,7 @@ def _unpack_args(*args):
363363
newargs.extend(subargs)
364364
else:
365365
newargs.append(arg)
366-
return newargs
366+
return tuple(newargs)
367367

368368
def _deduplicate(params, *, unhashable_fallback=False):
369369
# Weed out strict duplicates, preserving the first of each occurrence.
Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
Fix :exc:`TypeError` when subscripting a generic alias such as
2+
``typing.Dict[T, D]`` and omitting a :class:`~typing.TypeVar` that has a
3+
default. Also fix the default of a :class:`~typing.TypeVarTuple` being
4+
inserted as a nested list when subscripting a :class:`types.GenericAlias`
5+
such as ``tuple[bool, *Ts][()]``.

0 commit comments

Comments
 (0)