Skip to content

Commit 8255667

Browse files
committed
extended and reworked tests
1 parent c3d98c6 commit 8255667

File tree

1 file changed

+152
-27
lines changed

1 file changed

+152
-27
lines changed

src/test_typing_extensions.py

Lines changed: 152 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -7193,10 +7193,24 @@ def test_attributes(self):
71937193

71947194
subscripted_tupleT = Variadic[Unpack[Tuple[int, T]]]
71957195
self.assertEqual(subscripted_tupleT.__name__, "Variadic")
7196-
self.assertEqual(subscripted_tupleT.__value__, Tuple[int, Unpack[Ts]])
7197-
self.assertEqual(subscripted_tupleT.__type_params__, (Ts,))
71987196
self.assertEqual(subscripted_tupleT.__parameters__, (T, ))
71997197

7198+
# Use with Callable
7199+
# Use with Callable+Concatenate
7200+
subscripted_callable_concat = Variadic[Callable[Concatenate[Literal["s"], P], T]]
7201+
self.assertEqual(subscripted_callable_concat.__parameters__, (P, T))
7202+
7203+
subcriped_callable_tvt = Variadic[Callable[[Unpack[Ts]], T]]
7204+
self.assertEqual(subcriped_callable_tvt.__parameters__, (Ts, T))
7205+
7206+
# Use with Callable+Unpack
7207+
CallableTs = TypeAliasType("CallableTs", Callable[[Unpack[Ts]], Any], type_params=(Ts, ))
7208+
self.assertEqual(CallableTs.__type_params__, (Ts,))
7209+
self.assertEqual(CallableTs.__parameters__, (*Ts,))
7210+
7211+
unpack_callable = CallableTs[Unpack[Tuple[int, T]]]
7212+
self.assertEqual(unpack_callable.__parameters__, (T,))
7213+
72007214
def test_cannot_set_attributes(self):
72017215
Simple = TypeAliasType("Simple", int)
72027216
with self.assertRaisesRegex(AttributeError, "readonly attribute"):
@@ -7262,8 +7276,8 @@ def test_getitem(self):
72627276
subscripted = ListOrSetT[int]
72637277
self.assertEqual(get_args(subscripted), (int,))
72647278
self.assertIs(get_origin(subscripted), ListOrSetT)
7265-
with self.assertRaises(TypeError):
7266-
subscripted[int] # TypeError: ListOrSetT[int] is not a generic class
7279+
with self.assertRaises(TypeError, msg="not a generic class"):
7280+
subscripted[int]
72677281

72687282
still_generic = ListOrSetT[Iterable[T]]
72697283
self.assertEqual(get_args(still_generic), (Iterable[T],))
@@ -7279,36 +7293,116 @@ def test_getitem(self):
72797293
callable_no_arg = CallableP[[]]
72807294
self.assertEqual(get_args(callable_no_arg), ([],))
72817295
# (int) -> Any
7282-
callable_arg_raw = CallableP[int]
7283-
self.assertEqual(get_args(callable_arg_raw), (int,))
7284-
callable_arg = CallableP[[int]]
7285-
self.assertEqual(get_args(callable_arg), ([int],))
7296+
callable_arg = CallableP[int]
7297+
self.assertEqual(get_args(callable_arg), (int,))
7298+
7299+
callable_arg_list = CallableP[[int]]
7300+
self.assertEqual(get_args(callable_arg_list), ([int],))
7301+
72867302
# (int, int) -> Any
7287-
callable_arg2 = CallableP[[int, int]]
7288-
self.assertEqual(get_args(callable_arg2), ([int, int],))
7303+
callable_arg2 = CallableP[int, int]
7304+
self.assertEqual(get_args(callable_arg2), (int, int,))
7305+
7306+
callable_arg2_list = CallableP[[int, int]]
7307+
self.assertEqual(get_args(callable_arg2_list), ([int, int],))
72897308
# (...) -> Any
72907309
callable_ellipsis = CallableP[...]
72917310
self.assertEqual(get_args(callable_ellipsis), (...,))
7311+
72927312
callable_ellipsis2 = CallableP[(...,)]
72937313
self.assertEqual(callable_ellipsis, callable_ellipsis2)
72947314
# (int, ...) -> Any
72957315
callable_arg_more = CallableP[[int, ...]]
72967316
self.assertEqual(get_args(callable_arg_more), ([int, ...],))
72977317
# (T) -> Any
7298-
callable_generic = CallableP[[T]]
7299-
self.assertEqual(get_args(callable_generic), ([T],))
73007318
callable_generic_raw = CallableP[T]
73017319
self.assertEqual(get_args(callable_generic_raw), (T,))
7320+
self.assertEqual(callable_generic_raw.__parameters__, (T,))
73027321

7303-
# test invalid usage
7304-
if not TYPING_3_11_0:
7305-
with self.assertRaises(TypeError):
7306-
ListOrSetT[Generic[T]]
7307-
with self.assertRaises(TypeError):
7308-
ListOrSetT[(Generic[T], )]
7322+
# Usage with Concatenate
7323+
callable_concat = CallableP[Concatenate[int, P]]
7324+
self.assertEqual(callable_concat.__parameters__, (P,))
7325+
if TYPING_3_11_0:
7326+
self.assertEqual(get_args(callable_concat), (Concatenate[int, P],))
7327+
concat_usage = callable_concat[str]
7328+
self.assertEqual(get_args(concat_usage), ((int, str),))
7329+
self.assertEqual(concat_usage, callable_concat[[str]])
7330+
elif TYPING_3_10_0:
7331+
self.assertEqual(get_args(callable_concat), (int, P,))
7332+
with self.assertRaises(TypeError, msg="Parameters to generic types must be types"):
7333+
callable_concat[str]
7334+
concat_usage = callable_concat[[str]]
7335+
self.assertEqual(get_args(concat_usage), (int, [str]))
7336+
else:
7337+
self.assertEqual(get_args(callable_concat), (int, P,))
7338+
with self.assertRaises(TypeError, msg="Parameters to generic types must be types"):
7339+
callable_concat[[str]]
7340+
concat_usage = callable_concat[str]
7341+
self.assertEqual(get_args(concat_usage), (int, str))
7342+
7343+
# More complex cases
7344+
Ts = TypeVarTuple("Ts")
7345+
CallableTs = TypeAliasType("CallableTs", Callable[[Unpack[Ts]], Any], type_params=(Ts, ))
7346+
unpack_callable = CallableTs[Unpack[Tuple[int, T]]]
7347+
if TYPING_3_11_0:
7348+
self.assertEqual(get_args(unpack_callable), (Unpack[Tuple[int, T]],))
7349+
else:
7350+
self.assertEqual(get_args(unpack_callable), (Tuple[int, T],))
7351+
self.assertEqual(unpack_callable.__parameters__, (T,))
7352+
7353+
Variadic = TypeAliasType("Variadic", Tuple[int, Unpack[Ts]], type_params=(Ts,))
7354+
mixed_subscripedPT = Variadic[Callable[Concatenate[int, P], T]]
7355+
self.assertEqual(mixed_subscripedPT.__parameters__, (P, T))
7356+
self.assertEqual(get_args(mixed_subscripedPT), (Callable[Concatenate[int, P], T],))
7357+
7358+
done_subscripted_no_list = mixed_subscripedPT[T, Any] # Expected ParamSpec, ellipsis, or list of types
7359+
if TYPING_3_10_0:
7360+
done_subscripted_list = mixed_subscripedPT[[T], Any]
7361+
self.assertEqual(done_subscripted_list, done_subscripted_no_list)
7362+
else:
7363+
with self.assertRaises(TypeError, msg="Parameters to generic types must be types."):
7364+
mixed_subscripedPT[[T], Any]
7365+
7366+
@skipUnless(TYPING_3_11_0, "__args__ behaves differently")
7367+
def test_311_substitution(self):
7368+
# To pass these tests alias.__args__ in TypeAliasType.__getitem__ needs adjustment
7369+
# Unpack and Concatenate are unpacked in versions before
7370+
T = TypeVar("T")
7371+
Ts = TypeVarTuple("Ts")
7372+
7373+
CallableTs = TypeAliasType("CallableTs", Callable[[Unpack[Ts]], Any], type_params=(Ts, ))
7374+
unpack_callable = CallableTs[Unpack[Tuple[int, T]]]
7375+
self.assertEqual(get_args(unpack_callable), (Unpack[Tuple[int, T]],))
7376+
7377+
P = ParamSpec('P')
7378+
CallableP = TypeAliasType("CallableP", Callable[P, T], type_params=(P, T))
7379+
callable_concat = CallableP[Concatenate[int, P], Any]
7380+
self.assertEqual(get_args(callable_concat), (Concatenate[int, P], Any))
7381+
7382+
@skipUnless(TYPING_3_12_0, "__args__ behaves differently")
7383+
def test_312_substitution(self):
7384+
# To pass these tests alias.__args__ in TypeAliasType.__getitem__ needs to be adjustment
7385+
# Would raise: TypeError: Substitution of bare TypeVarTuple is not supported
7386+
T = TypeVar("T")
7387+
Ts = TypeVarTuple("Ts")
7388+
Variadic = TypeAliasType("Variadic", Tuple[int, Unpack[Ts]], type_params=(Ts,))
7389+
7390+
subcriped_callable_tvt = Variadic[Callable[[Unpack[Ts]], T]]
7391+
variadic_tvt_callableA = subcriped_callable_tvt[str, object]
7392+
variadic_tvt_callableA2 = subcriped_callable_tvt[Unpack[Tuple[str]], object]
7393+
self.assertEqual(variadic_tvt_callableA, variadic_tvt_callableA2)
7394+
7395+
variadic_tvt_callableB = subcriped_callable_tvt[[str, int], object]
7396+
variadic_tvt_callableB2 = subcriped_callable_tvt[Unpack[Tuple[str, int]], object]
7397+
variadic_tvt_callableB3 = subcriped_callable_tvt[str, int, object]
7398+
self.assertNotEqual(variadic_tvt_callableB, variadic_tvt_callableB2)
7399+
self.assertEqual(variadic_tvt_callableB2, variadic_tvt_callableB3)
73097400

73107401
def test_invalid_cases(self):
7311-
# If these cases fail the specificiation might have changed
7402+
# NOTE: If these cases fail the specificiation might have changed
7403+
# some of the cases could be seen as valid but are currently not
7404+
7405+
# More parameters
73127406
T = TypeVar("T")
73137407
T2 = TypeVar("T2")
73147408
ListOrSetT = TypeAliasType("ListOrSetT", Union[List[T], Set[T]], type_params=(T,))
@@ -7317,6 +7411,7 @@ def test_invalid_cases(self):
73177411
self.assertEqual(get_args(too_many), (int, bool))
73187412
self.assertEqual(too_many.__parameters__, ())
73197413

7414+
# Not enough parameters
73207415
ListOrSet2T = TypeAliasType("ListOrSet2T", Union[List[T], Set[T2]], type_params=(T, T2))
73217416
not_enough = ListOrSet2T[int]
73227417
self.assertEqual(get_args(not_enough), (int,))
@@ -7357,15 +7452,45 @@ def test_invalid_cases(self):
73577452
invalud_tuple_C = Variadic[[int, T]]
73587453
self.assertEqual(invalud_tuple_C.__parameters__, ())
73597454
self.assertEqual(get_args(invalud_tuple_C), ([int, T],))
7360-
7361-
@skipUnless(TYPING_3_11_0, "Concatenate not unpacked anymore")
7362-
def test_further_invalid_cases(self):
7363-
P = ParamSpec('P')
7455+
7456+
# Callable
7457+
# NOTE: This these cases seem to be more like a limitation in the typing variant
7458+
# The final variable is parameterless if using a list here.
7459+
callable_T = CallableP[[T]]
7460+
self.assertEqual(get_args(callable_T), ([T],))
7461+
self.assertEqual(callable_T.__parameters__, ())
7462+
with self.assertRaises(TypeError, msg="is not a generic class"):
7463+
callable_T[str]
7464+
7465+
InvalidConcatP = CallableP[[int, P]]
7466+
self.assertEqual(get_args(InvalidConcatP), ([int, P],))
7467+
self.assertEqual(InvalidConcatP.__parameters__, ())
7468+
with self.assertRaises(TypeError, msg="is not a generic class"):
7469+
InvalidConcatP[str]
7470+
7471+
# Callable
7472+
# NOTE: This these cases seem to be more like a limitation in the typing variant
7473+
callable_T = CallableP[[T]]
7474+
self.assertEqual(get_args(callable_T), ([T],))
7475+
self.assertEqual(callable_T.__parameters__, ())
7476+
with self.assertRaises(TypeError, msg="is not a generic class"):
7477+
callable_T[str]
7478+
7479+
InvalidConcatP = CallableP[[int, P]]
7480+
self.assertEqual(get_args(InvalidConcatP), ([int, P],))
7481+
self.assertEqual(InvalidConcatP.__parameters__, ())
7482+
with self.assertRaises(TypeError, msg="is not a generic class"):
7483+
InvalidConcatP[str]
7484+
7485+
@skipIf(TYPING_3_11_0, "Most cases are allowed in 3.11+")
7486+
def test_invalid_cases_before_3_11(self):
73647487
T = TypeVar("T")
7365-
T2 = TypeVar("T2")
7366-
CallableP = TypeAliasType("CallableP", Callable[P, T], type_params=(P,))
7367-
callable_concat = CallableP[Concatenate[Any, T2, P], Any]
7368-
self.assertEqual(get_args(callable_concat), (Concatenate[Any, T2, P], Any))
7488+
ListOrSetT = TypeAliasType("ListOrSetT", Union[List[T], Set[T]], type_params=(T,))
7489+
with self.assertRaises(TypeError):
7490+
ListOrSetT[Generic[T]]
7491+
with self.assertRaises(TypeError):
7492+
ListOrSetT[(Generic[T], )]
7493+
73697494

73707495
def test_pickle(self):
73717496
global Alias

0 commit comments

Comments
 (0)