]> git.ipfire.org Git - thirdparty/Python/cpython.git/commitdiff
bpo-43224: Add tests for TypeVarTuple substitution in Annotated (GH-31846)
authorMatthew Rahtz <matthew.rahtz@gmail.com>
Sat, 16 Apr 2022 04:24:28 +0000 (05:24 +0100)
committerGitHub <noreply@github.com>
Sat, 16 Apr 2022 04:24:28 +0000 (21:24 -0700)
Lib/test/test_typing.py
Lib/typing.py

index 97fc66a2f748f36f84babc8949b3d7b405d6ff92..ffd0592a3b4149df19926a3b8da1d48ec9569ec2 100644 (file)
@@ -5873,6 +5873,77 @@ class AnnotatedTests(BaseTestCase):
         with self.assertRaises(TypeError):
             LI[None]
 
+    def test_typevar_subst(self):
+        dec = "a decoration"
+        Ts = TypeVarTuple('Ts')
+        T = TypeVar('T')
+        T1 = TypeVar('T1')
+        T2 = TypeVar('T2')
+
+        A = Annotated[Tuple[Unpack[Ts]], dec]
+        self.assertEqual(A[int], Annotated[Tuple[int], dec])
+        self.assertEqual(A[str, int], Annotated[Tuple[str, int], dec])
+        with self.assertRaises(TypeError):
+            Annotated[Unpack[Ts], dec]
+
+        B = Annotated[Tuple[T, Unpack[Ts]], dec]
+        self.assertEqual(B[int], Annotated[Tuple[int], dec])
+        self.assertEqual(B[int, str], Annotated[Tuple[int, str], dec])
+        self.assertEqual(
+            B[int, str, float],
+            Annotated[Tuple[int, str, float], dec]
+        )
+        with self.assertRaises(TypeError):
+            B[()]
+
+        C = Annotated[Tuple[Unpack[Ts], T], dec]
+        self.assertEqual(C[int], Annotated[Tuple[int], dec])
+        self.assertEqual(C[int, str], Annotated[Tuple[int, str], dec])
+        self.assertEqual(
+            C[int, str, float],
+            Annotated[Tuple[int, str, float], dec]
+        )
+        with self.assertRaises(TypeError):
+            C[()]
+
+        D = Annotated[Tuple[T1, Unpack[Ts], T2], dec]
+        self.assertEqual(D[int, str], Annotated[Tuple[int, str], dec])
+        self.assertEqual(
+            D[int, str, float],
+            Annotated[Tuple[int, str, float], dec]
+        )
+        self.assertEqual(
+            D[int, str, bool, float],
+            Annotated[Tuple[int, str, bool, float], dec]
+        )
+        with self.assertRaises(TypeError):
+            D[int]
+
+        # Now let's try creating an alias from an alias.
+
+        Ts2 = TypeVarTuple('Ts2')
+        T3 = TypeVar('T3')
+        T4 = TypeVar('T4')
+
+        E = D[T3, Unpack[Ts2], T4]
+        self.assertEqual(
+            E,
+            Annotated[Tuple[T3, Unpack[Ts2], T4], dec]
+        )
+        self.assertEqual(
+            E[int, str], Annotated[Tuple[int, str], dec]
+        )
+        self.assertEqual(
+            E[int, str, float],
+            Annotated[Tuple[int, str, float], dec]
+        )
+        self.assertEqual(
+            E[int, str, bool, float],
+            Annotated[Tuple[int, str, bool, float], dec]
+        )
+        with self.assertRaises(TypeError):
+            E[int]
+
     def test_annotated_in_other_types(self):
         X = List[Annotated[T, 5]]
         self.assertEqual(X[int], List[Annotated[int, 5]])
index 1b584bea0c3e57df5b27e277304de02aa8d429ba..b26adc63cc136bb5c2ab1cfecf2755a4c4a5c24b 100644 (file)
@@ -2080,6 +2080,17 @@ class Annotated:
 
         OptimizedList = Annotated[List[T], runtime.Optimize()]
         OptimizedList[int] == Annotated[List[int], runtime.Optimize()]
+
+    - Annotated cannot be used with an unpacked TypeVarTuple::
+
+        Annotated[*Ts, Ann1]  # NOT valid
+
+      This would be equivalent to
+
+        Annotated[T1, T2, T3, ..., Ann1]
+
+      where T1, T2 etc. are TypeVars, which would be invalid, because
+      only one type should be passed to Annotated.
     """
 
     __slots__ = ()
@@ -2093,6 +2104,9 @@ class Annotated:
             raise TypeError("Annotated[...] should be used "
                             "with at least two arguments (a type and an "
                             "annotation).")
+        if _is_unpacked_typevartuple(params[0]):
+            raise TypeError("Annotated[...] should not be used with an "
+                            "unpacked TypeVarTuple")
         msg = "Annotated[t, ...]: t must be a type."
         origin = _type_check(params[0], msg, allow_special_forms=True)
         metadata = tuple(params[1:])