Skip to content

Commit 1761a43

Browse files
committed
Merge remote-tracking branch 'upstream/main' into get_type_hints
2 parents 9e59796 + a2abfe6 commit 1761a43

File tree

3 files changed

+65
-0
lines changed

3 files changed

+65
-0
lines changed

CHANGELOG.md

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,8 @@
2020
`Union[..., NoneType]` to annotations that have a `None` default value anymore.
2121
This fixes wrapping of `Annotated` in an unwanted `Optional` in such cases.
2222
Patch by [Daraan](https://github.com/Daraan).
23+
- Fix error in subscription of `Unpack` aliases causing nested Unpacks
24+
to not be resolved correctly. Patch by [Daraan](https://github.com/Daraan).
2325

2426
# Release 4.12.2 (June 7, 2024)
2527

src/test_typing_extensions.py

Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5868,6 +5868,47 @@ class D(Protocol[T1, T2, Unpack[Ts]]): pass
58685868
with self.assertRaises(TypeError):
58695869
klass[int]
58705870

5871+
def test_substitution(self):
5872+
Ts = TypeVarTuple("Ts")
5873+
unpacked_str = Unpack[Ts][str] # This should not raise an error
5874+
self.assertIs(unpacked_str, str)
5875+
5876+
@skipUnless(TYPING_3_11_0, "Needs Issue #103 for <3.11")
5877+
def test_nested_unpack(self):
5878+
Ts = TypeVarTuple("Ts")
5879+
Variadic = Tuple[int, Unpack[Ts]]
5880+
# Tuple[int, int, Tuple[str, int]]
5881+
direct_subscription = Variadic[int, Tuple[str, int]]
5882+
# Tuple[int, int, Tuple[*Ts, int]]
5883+
TupleAliasTs = Variadic[int, Tuple[Unpack[Ts], int]]
5884+
5885+
# Tuple[int, int, Tuple[str, int]]
5886+
recursive_unpack = TupleAliasTs[str]
5887+
self.assertEqual(direct_subscription, recursive_unpack)
5888+
self.assertEqual(get_args(recursive_unpack), (int, int, Tuple[str, int]))
5889+
5890+
# Test with Callable
5891+
T = TypeVar("T")
5892+
# Tuple[int, (*Ts) -> T]
5893+
CallableAliasTsT = Variadic[Callable[[Unpack[Ts]], T]]
5894+
# Tuple[int, (str, int) -> object]
5895+
callable_fully_subscripted = CallableAliasTsT[Unpack[Tuple[str, int]], object]
5896+
self.assertEqual(get_args(callable_fully_subscripted), (int, Callable[[str, int], object]))
5897+
5898+
@skipUnless(TYPING_3_11_0, "Needs Issue #103 for <3.11")
5899+
def test_equivalent_nested_variadics(self):
5900+
T = TypeVar("T")
5901+
Ts = TypeVarTuple("Ts")
5902+
Variadic = Tuple[int, Unpack[Ts]]
5903+
TupleAliasTsT = Variadic[Tuple[Unpack[Ts], T]]
5904+
nested_tuple_bare = TupleAliasTsT[str, int, object]
5905+
5906+
self.assertEqual(get_args(nested_tuple_bare), (int, Tuple[str, int, object]))
5907+
# Variants
5908+
self.assertEqual(nested_tuple_bare, TupleAliasTsT[Unpack[Tuple[str, int, object]]])
5909+
self.assertEqual(nested_tuple_bare, TupleAliasTsT[Unpack[Tuple[str, int]], object])
5910+
self.assertEqual(nested_tuple_bare, TupleAliasTsT[Unpack[Tuple[str]], Unpack[Tuple[int]], object])
5911+
58715912

58725913
class TypeVarTupleTests(BaseTestCase):
58735914

src/typing_extensions.py

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2503,6 +2503,17 @@ def __typing_unpacked_tuple_args__(self):
25032503
return arg.__args__
25042504
return None
25052505

2506+
@property
2507+
def __typing_is_unpacked_typevartuple__(self):
2508+
assert self.__origin__ is Unpack
2509+
assert len(self.__args__) == 1
2510+
return isinstance(self.__args__[0], TypeVarTuple)
2511+
2512+
def __getitem__(self, args):
2513+
if self.__typing_is_unpacked_typevartuple__:
2514+
return args
2515+
return super().__getitem__(args)
2516+
25062517
@_UnpackSpecialForm
25072518
def Unpack(self, parameters):
25082519
item = typing._type_check(parameters, f'{self._name} accepts only a single type.')
@@ -2515,6 +2526,17 @@ def _is_unpack(obj):
25152526
class _UnpackAlias(typing._GenericAlias, _root=True):
25162527
__class__ = typing.TypeVar
25172528

2529+
@property
2530+
def __typing_is_unpacked_typevartuple__(self):
2531+
assert self.__origin__ is Unpack
2532+
assert len(self.__args__) == 1
2533+
return isinstance(self.__args__[0], TypeVarTuple)
2534+
2535+
def __getitem__(self, args):
2536+
if self.__typing_is_unpacked_typevartuple__:
2537+
return args
2538+
return super().__getitem__(args)
2539+
25182540
class _UnpackForm(_ExtensionsSpecialForm, _root=True):
25192541
def __getitem__(self, parameters):
25202542
item = typing._type_check(parameters,

0 commit comments

Comments
 (0)