diff options
-rw-r--r-- | Lib/test/test_typing.py | 30 | ||||
-rw-r--r-- | Lib/typing.py | 5 | ||||
-rw-r--r-- | Misc/NEWS.d/next/Library/2023-01-14-12-58-21.gh-issue-101015.stWFid.rst | 2 |
3 files changed, 36 insertions, 1 deletions
diff --git a/Lib/test/test_typing.py b/Lib/test/test_typing.py index 1cae1b0..5aa49bb 100644 --- a/Lib/test/test_typing.py +++ b/Lib/test/test_typing.py @@ -1224,6 +1224,36 @@ class TypeVarTupleTests(BaseTestCase): self.assertIs(D[T].__origin__, D) self.assertIs(D[Unpack[Ts]].__origin__, D) + def test_get_type_hints_on_unpack_args(self): + Ts = TypeVarTuple('Ts') + + def func1(*args: *Ts): pass + self.assertEqual(gth(func1), {'args': Unpack[Ts]}) + + def func2(*args: *tuple[int, str]): pass + self.assertEqual(gth(func2), {'args': Unpack[tuple[int, str]]}) + + class CustomVariadic(Generic[*Ts]): pass + + def func3(*args: *CustomVariadic[int, str]): pass + self.assertEqual(gth(func3), {'args': Unpack[CustomVariadic[int, str]]}) + + def test_get_type_hints_on_unpack_args_string(self): + Ts = TypeVarTuple('Ts') + + def func1(*args: '*Ts'): pass + self.assertEqual(gth(func1, localns={'Ts': Ts}), + {'args': Unpack[Ts]}) + + def func2(*args: '*tuple[int, str]'): pass + self.assertEqual(gth(func2), {'args': Unpack[tuple[int, str]]}) + + class CustomVariadic(Generic[*Ts]): pass + + def func3(*args: '*CustomVariadic[int, str]'): pass + self.assertEqual(gth(func3, localns={'CustomVariadic': CustomVariadic}), + {'args': Unpack[CustomVariadic[int, str]]}) + def test_tuple_args_are_correct(self): Ts = TypeVarTuple('Ts') diff --git a/Lib/typing.py b/Lib/typing.py index 4675af1..bdf51bb 100644 --- a/Lib/typing.py +++ b/Lib/typing.py @@ -371,10 +371,13 @@ def _eval_type(t, globalns, localns, recursive_guard=frozenset()): ForwardRef(arg) if isinstance(arg, str) else arg for arg in t.__args__ ) + is_unpacked = t.__unpacked__ if _should_unflatten_callable_args(t, args): t = t.__origin__[(args[:-1], args[-1])] else: t = t.__origin__[args] + if is_unpacked: + t = Unpack[t] ev_args = tuple(_eval_type(a, globalns, localns, recursive_guard) for a in t.__args__) if ev_args == t.__args__: return t @@ -828,7 +831,7 @@ class ForwardRef(_Final, _root=True): # Unfortunately, this isn't a valid expression on its own, so we # do the unpacking manually. if arg[0] == '*': - arg_to_compile = f'({arg},)[0]' # E.g. (*Ts,)[0] + arg_to_compile = f'({arg},)[0]' # E.g. (*Ts,)[0] or (*tuple[int, int],)[0] else: arg_to_compile = arg try: diff --git a/Misc/NEWS.d/next/Library/2023-01-14-12-58-21.gh-issue-101015.stWFid.rst b/Misc/NEWS.d/next/Library/2023-01-14-12-58-21.gh-issue-101015.stWFid.rst new file mode 100644 index 0000000..b9d73ff --- /dev/null +++ b/Misc/NEWS.d/next/Library/2023-01-14-12-58-21.gh-issue-101015.stWFid.rst @@ -0,0 +1,2 @@ +Fix :func:`typing.get_type_hints` on ``'*tuple[...]'`` and ``*tuple[...]``. +It must not drop the ``Unpack`` part. |