@@ -7396,6 +7396,80 @@ def test_attributes(self):
73967396 self .assertEqual (Variadic .__type_params__ , (Ts ,))
73977397 self .assertEqual (Variadic .__parameters__ , tuple (iter (Ts )))
73987398
7399+ P = ParamSpec ('P' )
7400+ CallableP = TypeAliasType ("CallableP" , Callable [P , Any ], type_params = (P , ))
7401+ self .assertEqual (CallableP .__name__ , "CallableP" )
7402+ self .assertEqual (CallableP .__value__ , Callable [P , Any ])
7403+ self .assertEqual (CallableP .__type_params__ , (P ,))
7404+ self .assertEqual (CallableP .__parameters__ , (P ,))
7405+
7406+ def test_alias_types_and_substitutions (self ):
7407+ T = TypeVar ('T' )
7408+ T2 = TypeVar ('T2' )
7409+ T_default = TypeVar ("T_default" , default = int )
7410+ Ts = TypeVarTuple ("Ts" )
7411+ P = ParamSpec ('P' )
7412+
7413+ test_argument_cases = {
7414+ # arguments : expected parameters
7415+ int : (),
7416+ ... : (),
7417+ None : (),
7418+ T2 : (T2 ,),
7419+ Union [int , List [T2 ]] : (T2 ,),
7420+ Tuple [int , str ] : (),
7421+ Tuple [T , T_default , T2 ] : (T , T_default , T2 ),
7422+ Tuple [Unpack [Ts ]] : (Ts ,),
7423+ Callable [[Unpack [Ts ]], T2 ] : (Ts , T2 ),
7424+ Callable [P , T2 ] : (P , T2 ),
7425+ Callable [Concatenate [T2 , P ], T_default ] : (T2 , P , T_default ),
7426+ TypeAliasType ("NestedAlias" , List [T ], type_params = (T ,))[T2 ] : (T2 ,),
7427+ Unpack [Ts ] : (Ts ,),
7428+ Unpack [Tuple [int , T2 ]] : (T2 ,),
7429+ Concatenate [int , P ] : (P ,),
7430+ # Not tested usage of bare TypeVarTuple, would need 3.11+
7431+ # Ts : (Ts,), # invalid case
7432+ }
7433+
7434+ test_alias_cases = [
7435+ # Simple cases
7436+ TypeAliasType ("ListT" , List [T ], type_params = (T ,)),
7437+ TypeAliasType ("UnionT" , Union [int , List [T ]], type_params = (T ,)),
7438+ # Value has no parameter but in type_param
7439+ TypeAliasType ("ValueWithoutT" , int , type_params = (T ,)),
7440+ # Callable
7441+ TypeAliasType ("CallableP" , Callable [P , Any ], type_params = (P , )),
7442+ TypeAliasType ("CallableT" , Callable [..., T ], type_params = (T , )),
7443+ TypeAliasType ("CallableTs" , Callable [[Unpack [Ts ]], Any ], type_params = (Ts , )),
7444+ # TypeVarTuple
7445+ TypeAliasType ("Variadic" , Tuple [int , Unpack [Ts ]], type_params = (Ts ,)),
7446+ # TypeVar with default
7447+ TypeAliasType ("TupleT_default" , Tuple [T_default , T ], type_params = (T , T_default )),
7448+ TypeAliasType ("CallableT_default" , Callable [[T ], T_default ], type_params = (T , T_default )),
7449+ ]
7450+
7451+ for alias in test_alias_cases :
7452+ with self .subTest (alias = alias , args = []):
7453+ subscripted = alias [[]]
7454+ self .assertEqual (get_args (subscripted ), ([],))
7455+ self .assertEqual (subscripted .__parameters__ , ())
7456+ with self .subTest (alias = alias , args = ()):
7457+ subscripted = alias [()]
7458+ self .assertEqual (get_args (subscripted ), ())
7459+ self .assertEqual (subscripted .__parameters__ , ())
7460+ with self .subTest (alias = alias , args = (int , float )):
7461+ subscripted = alias [int , float ]
7462+ self .assertEqual (get_args (subscripted ), (int , float ))
7463+ self .assertEqual (subscripted .__parameters__ , ())
7464+ with self .subTest (alias = alias , args = [int , float ]):
7465+ subscripted = alias [[int , float ]]
7466+ self .assertEqual (get_args (subscripted ), ([int , float ],))
7467+ self .assertEqual (subscripted .__parameters__ , ())
7468+ for expected_args , expected_parameters in test_argument_cases .items ():
7469+ with self .subTest (alias = alias , args = expected_args ):
7470+ self .assertEqual (get_args (alias [expected_args ]), (expected_args ,))
7471+ self .assertEqual (alias [expected_args ].__parameters__ , expected_parameters )
7472+
73997473 def test_cannot_set_attributes (self ):
74007474 Simple = TypeAliasType ("Simple" , int )
74017475 with self .assertRaisesRegex (AttributeError , "readonly attribute" ):
@@ -7456,12 +7530,19 @@ def test_or(self):
74567530 Alias | "Ref"
74577531
74587532 def test_getitem (self ):
7533+ T = TypeVar ('T' )
74597534 ListOrSetT = TypeAliasType ("ListOrSetT" , Union [List [T ], Set [T ]], type_params = (T ,))
74607535 subscripted = ListOrSetT [int ]
74617536 self .assertEqual (get_args (subscripted ), (int ,))
74627537 self .assertIs (get_origin (subscripted ), ListOrSetT )
7463- with self .assertRaises (TypeError ):
7464- subscripted [str ]
7538+ with self .assertRaisesRegex (TypeError ,
7539+ "not a generic class"
7540+ # types.GenericAlias raises a different error in 3.10
7541+ if sys .version_info [:2 ] != (3 , 10 )
7542+ else "There are no type variables left in ListOrSetT"
7543+ ):
7544+ subscripted [int ]
7545+
74657546
74667547 still_generic = ListOrSetT [Iterable [T ]]
74677548 self .assertEqual (get_args (still_generic ), (Iterable [T ],))
@@ -7470,6 +7551,114 @@ def test_getitem(self):
74707551 self .assertEqual (get_args (fully_subscripted ), (Iterable [float ],))
74717552 self .assertIs (get_origin (fully_subscripted ), ListOrSetT )
74727553
7554+ ValueWithoutTypeVar = TypeAliasType ("ValueWithoutTypeVar" , int , type_params = (T ,))
7555+ still_subscripted = ValueWithoutTypeVar [str ]
7556+ self .assertEqual (get_args (still_subscripted ), (str ,))
7557+
7558+ def test_callable_without_concatenate (self ):
7559+ P = ParamSpec ('P' )
7560+ CallableP = TypeAliasType ("CallableP" , Callable [P , Any ], type_params = (P ,))
7561+ get_args_test_cases = [
7562+ # List of (alias, expected_args)
7563+ # () -> Any
7564+ (CallableP [()], ()),
7565+ (CallableP [[]], ([],)),
7566+ # (int) -> Any
7567+ (CallableP [int ], (int ,)),
7568+ (CallableP [[int ]], ([int ],)),
7569+ # (int, int) -> Any
7570+ (CallableP [int , int ], (int , int )),
7571+ (CallableP [[int , int ]], ([int , int ],)),
7572+ # (...) -> Any
7573+ (CallableP [...], (...,)),
7574+ # (int, ...) -> Any
7575+ (CallableP [[int , ...]], ([int , ...],)),
7576+ ]
7577+
7578+ for index , (expression , expected_args ) in enumerate (get_args_test_cases ):
7579+ with self .subTest (index = index , expression = expression ):
7580+ self .assertEqual (get_args (expression ), expected_args )
7581+
7582+ self .assertEqual (CallableP [...], CallableP [(...,)])
7583+ # (T) -> Any
7584+ CallableT = CallableP [T ]
7585+ self .assertEqual (get_args (CallableT ), (T ,))
7586+ self .assertEqual (CallableT .__parameters__ , (T ,))
7587+
7588+ def test_callable_with_concatenate (self ):
7589+ P = ParamSpec ('P' )
7590+ P2 = ParamSpec ('P2' )
7591+ CallableP = TypeAliasType ("CallableP" , Callable [P , Any ], type_params = (P ,))
7592+
7593+ callable_concat = CallableP [Concatenate [int , P2 ]]
7594+ self .assertEqual (callable_concat .__parameters__ , (P2 ,))
7595+ concat_usage = callable_concat [str ]
7596+ with self .subTest ("get_args of Concatenate in TypeAliasType" ):
7597+ if not TYPING_3_9_0 :
7598+ # args are: ([<class 'int'>, ~P2],)
7599+ self .skipTest ("Nested ParamSpec is not substituted" )
7600+ if sys .version_info < (3 , 10 , 2 ):
7601+ self .skipTest ("GenericAlias keeps Concatenate in __args__ prior to 3.10.2" )
7602+ self .assertEqual (get_args (concat_usage ), ((int , str ),))
7603+ with self .subTest ("Equality of parameter_expression without []" ):
7604+ if not TYPING_3_10_0 :
7605+ self .skipTest ("Nested list is invalid type form" )
7606+ self .assertEqual (concat_usage , callable_concat [[str ]])
7607+
7608+ def test_substitution (self ):
7609+ T = TypeVar ('T' )
7610+ Ts = TypeVarTuple ("Ts" )
7611+
7612+ CallableTs = TypeAliasType ("CallableTs" , Callable [[Unpack [Ts ]], Any ], type_params = (Ts , ))
7613+ unpack_callable = CallableTs [Unpack [Tuple [int , T ]]]
7614+ self .assertEqual (get_args (unpack_callable ), (Unpack [Tuple [int , T ]],))
7615+
7616+ P = ParamSpec ('P' )
7617+ CallableP = TypeAliasType ("CallableP" , Callable [P , T ], type_params = (P , T ))
7618+ callable_concat = CallableP [Concatenate [int , P ], Any ]
7619+ self .assertEqual (get_args (callable_concat ), (Concatenate [int , P ], Any ))
7620+
7621+ def test_wrong_amount_of_parameters (self ):
7622+ T = TypeVar ('T' )
7623+ T2 = TypeVar ("T2" )
7624+ P = ParamSpec ('P' )
7625+ ListOrSetT = TypeAliasType ("ListOrSetT" , Union [List [T ], Set [T ]], type_params = (T ,))
7626+ TwoT = TypeAliasType ("TwoT" , Union [List [T ], Set [T2 ]], type_params = (T , T2 ))
7627+ CallablePT = TypeAliasType ("CallablePT" , Callable [P , T ], type_params = (P , T ))
7628+
7629+ # Not enough parameters
7630+ test_cases = [
7631+ # not_enough
7632+ (TwoT [int ], [(int ,), ()]),
7633+ (TwoT [T ], [(T ,), (T ,)]),
7634+ # callable and not enough
7635+ (CallablePT [int ], [(int ,), ()]),
7636+ # too many
7637+ (ListOrSetT [int , bool ], [(int , bool ), ()]),
7638+ # callable and too many
7639+ (CallablePT [str , float , int ], [(str , float , int ), ()]),
7640+ # Check if TypeVar is still present even if over substituted
7641+ (ListOrSetT [int , T ], [(int , T ), (T ,)]),
7642+ # With and without list for ParamSpec
7643+ (CallablePT [str , float , T ], [(str , float , T ), (T ,)]),
7644+ (CallablePT [[str ], float , int , T2 ], [([str ], float , int , T2 ), (T2 ,)]),
7645+ ]
7646+
7647+ for index , (alias , [expected_args , expected_params ]) in enumerate (test_cases ):
7648+ with self .subTest (index = index , alias = alias ):
7649+ self .assertEqual (get_args (alias ), expected_args )
7650+ self .assertEqual (alias .__parameters__ , expected_params )
7651+
7652+ # The condition should align with the version of GeneriAlias usage in __getitem__ or be 3.11+
7653+ @skipIf (TYPING_3_10_0 , "Most arguments are allowed in 3.11+ or with GenericAlias" )
7654+ def test_invalid_cases_before_3_10 (self ):
7655+ T = TypeVar ('T' )
7656+ ListOrSetT = TypeAliasType ("ListOrSetT" , Union [List [T ], Set [T ]], type_params = (T ,))
7657+ with self .assertRaises (TypeError ):
7658+ ListOrSetT [Generic [T ]]
7659+ with self .assertRaises (TypeError ):
7660+ ListOrSetT [(Generic [T ], )]
7661+
74737662 def test_unpack_parameter_collection (self ):
74747663 Ts = TypeVarTuple ("Ts" )
74757664
0 commit comments