@@ -7356,6 +7356,80 @@ def test_attributes(self):
73567356 self .assertEqual (Variadic .__type_params__ , (Ts ,))
73577357 self .assertEqual (Variadic .__parameters__ , tuple (iter (Ts )))
73587358
7359+ P = ParamSpec ('P' )
7360+ CallableP = TypeAliasType ("CallableP" , Callable [P , Any ], type_params = (P , ))
7361+ self .assertEqual (CallableP .__name__ , "CallableP" )
7362+ self .assertEqual (CallableP .__value__ , Callable [P , Any ])
7363+ self .assertEqual (CallableP .__type_params__ , (P ,))
7364+ self .assertEqual (CallableP .__parameters__ , (P ,))
7365+
7366+ def test_alias_types_and_substitutions (self ):
7367+ T = TypeVar ('T' )
7368+ T2 = TypeVar ('T2' )
7369+ T_default = TypeVar ("T_default" , default = int )
7370+ Ts = TypeVarTuple ("Ts" )
7371+ P = ParamSpec ('P' )
7372+
7373+ test_argument_cases = {
7374+ # arguments : expected parameters
7375+ int : (),
7376+ ... : (),
7377+ None : (),
7378+ T2 : (T2 ,),
7379+ Union [int , List [T2 ]] : (T2 ,),
7380+ Tuple [int , str ] : (),
7381+ Tuple [T , T_default , T2 ] : (T , T_default , T2 ),
7382+ Tuple [Unpack [Ts ]] : (Ts ,),
7383+ Callable [[Unpack [Ts ]], T2 ] : (Ts , T2 ),
7384+ Callable [P , T2 ] : (P , T2 ),
7385+ Callable [Concatenate [T2 , P ], T_default ] : (T2 , P , T_default ),
7386+ TypeAliasType ("NestedAlias" , List [T ], type_params = (T ,))[T2 ] : (T2 ,),
7387+ Unpack [Ts ] : (Ts ,),
7388+ Unpack [Tuple [int , T2 ]] : (T2 ,),
7389+ Concatenate [int , P ] : (P ,),
7390+ # Not tested usage of bare TypeVarTuple, would need 3.11+
7391+ # Ts : (Ts,), # invalid case
7392+ }
7393+
7394+ test_alias_cases = [
7395+ # Simple cases
7396+ TypeAliasType ("ListT" , List [T ], type_params = (T ,)),
7397+ TypeAliasType ("UnionT" , Union [int , List [T ]], type_params = (T ,)),
7398+ # Value has no parameter but in type_param
7399+ TypeAliasType ("ValueWithoutT" , int , type_params = (T ,)),
7400+ # Callable
7401+ TypeAliasType ("CallableP" , Callable [P , Any ], type_params = (P , )),
7402+ TypeAliasType ("CallableT" , Callable [..., T ], type_params = (T , )),
7403+ TypeAliasType ("CallableTs" , Callable [[Unpack [Ts ]], Any ], type_params = (Ts , )),
7404+ # TypeVarTuple
7405+ TypeAliasType ("Variadic" , Tuple [int , Unpack [Ts ]], type_params = (Ts ,)),
7406+ # TypeVar with default
7407+ TypeAliasType ("TupleT_default" , Tuple [T_default , T ], type_params = (T , T_default )),
7408+ TypeAliasType ("CallableT_default" , Callable [[T ], T_default ], type_params = (T , T_default )),
7409+ ]
7410+
7411+ for alias in test_alias_cases :
7412+ with self .subTest (alias = alias , args = []):
7413+ subscripted = alias [[]]
7414+ self .assertEqual (get_args (subscripted ), ([],))
7415+ self .assertEqual (subscripted .__parameters__ , ())
7416+ with self .subTest (alias = alias , args = ()):
7417+ subscripted = alias [()]
7418+ self .assertEqual (get_args (subscripted ), ())
7419+ self .assertEqual (subscripted .__parameters__ , ())
7420+ with self .subTest (alias = alias , args = (int , float )):
7421+ subscripted = alias [int , float ]
7422+ self .assertEqual (get_args (subscripted ), (int , float ))
7423+ self .assertEqual (subscripted .__parameters__ , ())
7424+ with self .subTest (alias = alias , args = [int , float ]):
7425+ subscripted = alias [[int , float ]]
7426+ self .assertEqual (get_args (subscripted ), ([int , float ],))
7427+ self .assertEqual (subscripted .__parameters__ , ())
7428+ for expected_args , expected_parameters in test_argument_cases .items ():
7429+ with self .subTest (alias = alias , args = expected_args ):
7430+ self .assertEqual (get_args (alias [expected_args ]), (expected_args ,))
7431+ self .assertEqual (alias [expected_args ].__parameters__ , expected_parameters )
7432+
73597433 def test_cannot_set_attributes (self ):
73607434 Simple = TypeAliasType ("Simple" , int )
73617435 with self .assertRaisesRegex (AttributeError , "readonly attribute" ):
@@ -7416,12 +7490,19 @@ def test_or(self):
74167490 Alias | "Ref"
74177491
74187492 def test_getitem (self ):
7493+ T = TypeVar ('T' )
74197494 ListOrSetT = TypeAliasType ("ListOrSetT" , Union [List [T ], Set [T ]], type_params = (T ,))
74207495 subscripted = ListOrSetT [int ]
74217496 self .assertEqual (get_args (subscripted ), (int ,))
74227497 self .assertIs (get_origin (subscripted ), ListOrSetT )
7423- with self .assertRaises (TypeError ):
7424- subscripted [str ]
7498+ with self .assertRaisesRegex (TypeError ,
7499+ "not a generic class"
7500+ # types.GenericAlias raises a different error in 3.10
7501+ if sys .version_info [:2 ] != (3 , 10 )
7502+ else "There are no type variables left in ListOrSetT"
7503+ ):
7504+ subscripted [int ]
7505+
74257506
74267507 still_generic = ListOrSetT [Iterable [T ]]
74277508 self .assertEqual (get_args (still_generic ), (Iterable [T ],))
@@ -7430,6 +7511,114 @@ def test_getitem(self):
74307511 self .assertEqual (get_args (fully_subscripted ), (Iterable [float ],))
74317512 self .assertIs (get_origin (fully_subscripted ), ListOrSetT )
74327513
7514+ ValueWithoutTypeVar = TypeAliasType ("ValueWithoutTypeVar" , int , type_params = (T ,))
7515+ still_subscripted = ValueWithoutTypeVar [str ]
7516+ self .assertEqual (get_args (still_subscripted ), (str ,))
7517+
7518+ def test_callable_without_concatenate (self ):
7519+ P = ParamSpec ('P' )
7520+ CallableP = TypeAliasType ("CallableP" , Callable [P , Any ], type_params = (P ,))
7521+ get_args_test_cases = [
7522+ # List of (alias, expected_args)
7523+ # () -> Any
7524+ (CallableP [()], ()),
7525+ (CallableP [[]], ([],)),
7526+ # (int) -> Any
7527+ (CallableP [int ], (int ,)),
7528+ (CallableP [[int ]], ([int ],)),
7529+ # (int, int) -> Any
7530+ (CallableP [int , int ], (int , int )),
7531+ (CallableP [[int , int ]], ([int , int ],)),
7532+ # (...) -> Any
7533+ (CallableP [...], (...,)),
7534+ # (int, ...) -> Any
7535+ (CallableP [[int , ...]], ([int , ...],)),
7536+ ]
7537+
7538+ for index , (expression , expected_args ) in enumerate (get_args_test_cases ):
7539+ with self .subTest (index = index , expression = expression ):
7540+ self .assertEqual (get_args (expression ), expected_args )
7541+
7542+ self .assertEqual (CallableP [...], CallableP [(...,)])
7543+ # (T) -> Any
7544+ CallableT = CallableP [T ]
7545+ self .assertEqual (get_args (CallableT ), (T ,))
7546+ self .assertEqual (CallableT .__parameters__ , (T ,))
7547+
7548+ def test_callable_with_concatenate (self ):
7549+ P = ParamSpec ('P' )
7550+ P2 = ParamSpec ('P2' )
7551+ CallableP = TypeAliasType ("CallableP" , Callable [P , Any ], type_params = (P ,))
7552+
7553+ callable_concat = CallableP [Concatenate [int , P2 ]]
7554+ self .assertEqual (callable_concat .__parameters__ , (P2 ,))
7555+ concat_usage = callable_concat [str ]
7556+ with self .subTest ("get_args of Concatenate in TypeAliasType" ):
7557+ if not TYPING_3_9_0 :
7558+ # args are: ([<class 'int'>, ~P2],)
7559+ self .skipTest ("Nested ParamSpec is not substituted" )
7560+ if sys .version_info < (3 , 10 , 2 ):
7561+ self .skipTest ("GenericAlias keeps Concatenate in __args__ prior to 3.10.2" )
7562+ self .assertEqual (get_args (concat_usage ), ((int , str ),))
7563+ with self .subTest ("Equality of parameter_expression without []" ):
7564+ if not TYPING_3_10_0 :
7565+ self .skipTest ("Nested list is invalid type form" )
7566+ self .assertEqual (concat_usage , callable_concat [[str ]])
7567+
7568+ def test_substitution (self ):
7569+ T = TypeVar ('T' )
7570+ Ts = TypeVarTuple ("Ts" )
7571+
7572+ CallableTs = TypeAliasType ("CallableTs" , Callable [[Unpack [Ts ]], Any ], type_params = (Ts , ))
7573+ unpack_callable = CallableTs [Unpack [Tuple [int , T ]]]
7574+ self .assertEqual (get_args (unpack_callable ), (Unpack [Tuple [int , T ]],))
7575+
7576+ P = ParamSpec ('P' )
7577+ CallableP = TypeAliasType ("CallableP" , Callable [P , T ], type_params = (P , T ))
7578+ callable_concat = CallableP [Concatenate [int , P ], Any ]
7579+ self .assertEqual (get_args (callable_concat ), (Concatenate [int , P ], Any ))
7580+
7581+ def test_wrong_amount_of_parameters (self ):
7582+ T = TypeVar ('T' )
7583+ T2 = TypeVar ("T2" )
7584+ P = ParamSpec ('P' )
7585+ ListOrSetT = TypeAliasType ("ListOrSetT" , Union [List [T ], Set [T ]], type_params = (T ,))
7586+ TwoT = TypeAliasType ("TwoT" , Union [List [T ], Set [T2 ]], type_params = (T , T2 ))
7587+ CallablePT = TypeAliasType ("CallablePT" , Callable [P , T ], type_params = (P , T ))
7588+
7589+ # Not enough parameters
7590+ test_cases = [
7591+ # not_enough
7592+ (TwoT [int ], [(int ,), ()]),
7593+ (TwoT [T ], [(T ,), (T ,)]),
7594+ # callable and not enough
7595+ (CallablePT [int ], [(int ,), ()]),
7596+ # too many
7597+ (ListOrSetT [int , bool ], [(int , bool ), ()]),
7598+ # callable and too many
7599+ (CallablePT [str , float , int ], [(str , float , int ), ()]),
7600+ # Check if TypeVar is still present even if over substituted
7601+ (ListOrSetT [int , T ], [(int , T ), (T ,)]),
7602+ # With and without list for ParamSpec
7603+ (CallablePT [str , float , T ], [(str , float , T ), (T ,)]),
7604+ (CallablePT [[str ], float , int , T2 ], [([str ], float , int , T2 ), (T2 ,)]),
7605+ ]
7606+
7607+ for index , (alias , [expected_args , expected_params ]) in enumerate (test_cases ):
7608+ with self .subTest (index = index , alias = alias ):
7609+ self .assertEqual (get_args (alias ), expected_args )
7610+ self .assertEqual (alias .__parameters__ , expected_params )
7611+
7612+ # The condition should align with the version of GeneriAlias usage in __getitem__ or be 3.11+
7613+ @skipIf (TYPING_3_10_0 , "Most arguments are allowed in 3.11+ or with GenericAlias" )
7614+ def test_invalid_cases_before_3_10 (self ):
7615+ T = TypeVar ('T' )
7616+ ListOrSetT = TypeAliasType ("ListOrSetT" , Union [List [T ], Set [T ]], type_params = (T ,))
7617+ with self .assertRaises (TypeError ):
7618+ ListOrSetT [Generic [T ]]
7619+ with self .assertRaises (TypeError ):
7620+ ListOrSetT [(Generic [T ], )]
7621+
74337622 def test_unpack_parameter_collection (self ):
74347623 Ts = TypeVarTuple ("Ts" )
74357624
0 commit comments