]> git.ipfire.org Git - thirdparty/Python/cpython.git/commitdiff
gh-101015: Fix `typing.get_type_hints` with unpacked `*tuple` (PEP 646) (GH-101031)
authorMiss Islington (bot) <31488909+miss-islington@users.noreply.github.com>
Mon, 23 Jan 2023 08:20:15 +0000 (00:20 -0800)
committerGitHub <noreply@github.com>
Mon, 23 Jan 2023 08:20:15 +0000 (00:20 -0800)
(cherry picked from commit 807d6b576fa37f3ab7eb951297cb365c0c198595)

Co-authored-by: Nikita Sobolev <mail@sobolevn.me>
Lib/test/test_typing.py
Lib/typing.py
Misc/NEWS.d/next/Library/2023-01-14-12-58-21.gh-issue-101015.stWFid.rst [new file with mode: 0644]

index efa4cb3d4e2a97d773876c4d3d20fa2c9711f75e..10023af4f788e9db1823fb12733c1c7a1dd05a60 100644 (file)
@@ -1222,6 +1222,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')
 
index b287446169c226ceadec34565473083f79cbcb1d..9f5db1a1faaba9c08942473bc2d01f40f182fcc1 100644 (file)
@@ -363,10 +363,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
@@ -820,7 +823,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 (file)
index 0000000..b9d73ff
--- /dev/null
@@ -0,0 +1,2 @@
+Fix :func:`typing.get_type_hints` on ``'*tuple[...]'`` and ``*tuple[...]``.
+It must not drop the ``Unpack`` part.