Skip to content

Commit

Permalink
bpo-43224: Add tests for TypeVarTuple substitution in Annotated (GH-3…
Browse files Browse the repository at this point in the history
  • Loading branch information
mrahtz authored Apr 16, 2022
1 parent 468314c commit f2bc12f
Show file tree
Hide file tree
Showing 2 changed files with 85 additions and 0 deletions.
71 changes: 71 additions & 0 deletions Lib/test/test_typing.py
Original file line number Diff line number Diff line change
Expand Up @@ -5873,6 +5873,77 @@ def test_subst(self):
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]])
Expand Down
14 changes: 14 additions & 0 deletions Lib/typing.py
Original file line number Diff line number Diff line change
Expand Up @@ -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__ = ()
Expand All @@ -2093,6 +2104,9 @@ def __class_getitem__(cls, params):
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:])
Expand Down

0 comments on commit f2bc12f

Please sign in to comment.