@@ -7369,6 +7369,80 @@ def test_attributes(self):
73697369 self .assertEqual (Variadic .__type_params__ , (Ts ,))
73707370 self .assertEqual (Variadic .__parameters__ , tuple (iter (Ts )))
73717371
7372+ P = ParamSpec ('P' )
7373+ CallableP = TypeAliasType ("CallableP" , Callable [P , Any ], type_params = (P , ))
7374+ self .assertEqual (CallableP .__name__ , "CallableP" )
7375+ self .assertEqual (CallableP .__value__ , Callable [P , Any ])
7376+ self .assertEqual (CallableP .__type_params__ , (P ,))
7377+ self .assertEqual (CallableP .__parameters__ , (P ,))
7378+
7379+ def test_alias_types_and_substitutions (self ):
7380+ T = TypeVar ('T' )
7381+ T2 = TypeVar ('T2' )
7382+ T_default = TypeVar ("T_default" , default = int )
7383+ Ts = TypeVarTuple ("Ts" )
7384+ P = ParamSpec ('P' )
7385+
7386+ test_argument_cases = {
7387+ # arguments : expected parameters
7388+ int : (),
7389+ ... : (),
7390+ None : (),
7391+ T2 : (T2 ,),
7392+ Union [int , List [T2 ]] : (T2 ,),
7393+ Tuple [int , str ] : (),
7394+ Tuple [T , T_default , T2 ] : (T , T_default , T2 ),
7395+ Tuple [Unpack [Ts ]] : (Ts ,),
7396+ Callable [[Unpack [Ts ]], T2 ] : (Ts , T2 ),
7397+ Callable [P , T2 ] : (P , T2 ),
7398+ Callable [Concatenate [T2 , P ], T_default ] : (T2 , P , T_default ),
7399+ TypeAliasType ("NestedAlias" , List [T ], type_params = (T ,))[T2 ] : (T2 ,),
7400+ Unpack [Ts ] : (Ts ,),
7401+ Unpack [Tuple [int , T2 ]] : (T2 ,),
7402+ Concatenate [int , P ] : (P ,),
7403+ # Not tested usage of bare TypeVarTuple, would need 3.11+
7404+ # Ts : (Ts,), # invalid case
7405+ }
7406+
7407+ test_alias_cases = [
7408+ # Simple cases
7409+ TypeAliasType ("ListT" , List [T ], type_params = (T ,)),
7410+ TypeAliasType ("UnionT" , Union [int , List [T ]], type_params = (T ,)),
7411+ # Value has no parameter but in type_param
7412+ TypeAliasType ("ValueWithoutT" , int , type_params = (T ,)),
7413+ # Callable
7414+ TypeAliasType ("CallableP" , Callable [P , Any ], type_params = (P , )),
7415+ TypeAliasType ("CallableT" , Callable [..., T ], type_params = (T , )),
7416+ TypeAliasType ("CallableTs" , Callable [[Unpack [Ts ]], Any ], type_params = (Ts , )),
7417+ # TypeVarTuple
7418+ TypeAliasType ("Variadic" , Tuple [int , Unpack [Ts ]], type_params = (Ts ,)),
7419+ # TypeVar with default
7420+ TypeAliasType ("TupleT_default" , Tuple [T_default , T ], type_params = (T , T_default )),
7421+ TypeAliasType ("CallableT_default" , Callable [[T ], T_default ], type_params = (T , T_default )),
7422+ ]
7423+
7424+ for alias in test_alias_cases :
7425+ with self .subTest (alias = alias , args = []):
7426+ subscripted = alias [[]]
7427+ self .assertEqual (get_args (subscripted ), ([],))
7428+ self .assertEqual (subscripted .__parameters__ , ())
7429+ with self .subTest (alias = alias , args = ()):
7430+ subscripted = alias [()]
7431+ self .assertEqual (get_args (subscripted ), ())
7432+ self .assertEqual (subscripted .__parameters__ , ())
7433+ with self .subTest (alias = alias , args = (int , float )):
7434+ subscripted = alias [int , float ]
7435+ self .assertEqual (get_args (subscripted ), (int , float ))
7436+ self .assertEqual (subscripted .__parameters__ , ())
7437+ with self .subTest (alias = alias , args = [int , float ]):
7438+ subscripted = alias [[int , float ]]
7439+ self .assertEqual (get_args (subscripted ), ([int , float ],))
7440+ self .assertEqual (subscripted .__parameters__ , ())
7441+ for expected_args , expected_parameters in test_argument_cases .items ():
7442+ with self .subTest (alias = alias , args = expected_args ):
7443+ self .assertEqual (get_args (alias [expected_args ]), (expected_args ,))
7444+ self .assertEqual (alias [expected_args ].__parameters__ , expected_parameters )
7445+
73727446 def test_cannot_set_attributes (self ):
73737447 Simple = TypeAliasType ("Simple" , int )
73747448 with self .assertRaisesRegex (AttributeError , "readonly attribute" ):
@@ -7429,12 +7503,19 @@ def test_or(self):
74297503 Alias | "Ref"
74307504
74317505 def test_getitem (self ):
7506+ T = TypeVar ('T' )
74327507 ListOrSetT = TypeAliasType ("ListOrSetT" , Union [List [T ], Set [T ]], type_params = (T ,))
74337508 subscripted = ListOrSetT [int ]
74347509 self .assertEqual (get_args (subscripted ), (int ,))
74357510 self .assertIs (get_origin (subscripted ), ListOrSetT )
7436- with self .assertRaises (TypeError ):
7437- subscripted [str ]
7511+ with self .assertRaisesRegex (TypeError ,
7512+ "not a generic class"
7513+ # types.GenericAlias raises a different error in 3.10
7514+ if sys .version_info [:2 ] != (3 , 10 )
7515+ else "There are no type variables left in ListOrSetT"
7516+ ):
7517+ subscripted [int ]
7518+
74387519
74397520 still_generic = ListOrSetT [Iterable [T ]]
74407521 self .assertEqual (get_args (still_generic ), (Iterable [T ],))
@@ -7443,6 +7524,114 @@ def test_getitem(self):
74437524 self .assertEqual (get_args (fully_subscripted ), (Iterable [float ],))
74447525 self .assertIs (get_origin (fully_subscripted ), ListOrSetT )
74457526
7527+ ValueWithoutTypeVar = TypeAliasType ("ValueWithoutTypeVar" , int , type_params = (T ,))
7528+ still_subscripted = ValueWithoutTypeVar [str ]
7529+ self .assertEqual (get_args (still_subscripted ), (str ,))
7530+
7531+ def test_callable_without_concatenate (self ):
7532+ P = ParamSpec ('P' )
7533+ CallableP = TypeAliasType ("CallableP" , Callable [P , Any ], type_params = (P ,))
7534+ get_args_test_cases = [
7535+ # List of (alias, expected_args)
7536+ # () -> Any
7537+ (CallableP [()], ()),
7538+ (CallableP [[]], ([],)),
7539+ # (int) -> Any
7540+ (CallableP [int ], (int ,)),
7541+ (CallableP [[int ]], ([int ],)),
7542+ # (int, int) -> Any
7543+ (CallableP [int , int ], (int , int )),
7544+ (CallableP [[int , int ]], ([int , int ],)),
7545+ # (...) -> Any
7546+ (CallableP [...], (...,)),
7547+ # (int, ...) -> Any
7548+ (CallableP [[int , ...]], ([int , ...],)),
7549+ ]
7550+
7551+ for index , (expression , expected_args ) in enumerate (get_args_test_cases ):
7552+ with self .subTest (index = index , expression = expression ):
7553+ self .assertEqual (get_args (expression ), expected_args )
7554+
7555+ self .assertEqual (CallableP [...], CallableP [(...,)])
7556+ # (T) -> Any
7557+ CallableT = CallableP [T ]
7558+ self .assertEqual (get_args (CallableT ), (T ,))
7559+ self .assertEqual (CallableT .__parameters__ , (T ,))
7560+
7561+ def test_callable_with_concatenate (self ):
7562+ P = ParamSpec ('P' )
7563+ P2 = ParamSpec ('P2' )
7564+ CallableP = TypeAliasType ("CallableP" , Callable [P , Any ], type_params = (P ,))
7565+
7566+ callable_concat = CallableP [Concatenate [int , P2 ]]
7567+ self .assertEqual (callable_concat .__parameters__ , (P2 ,))
7568+ concat_usage = callable_concat [str ]
7569+ with self .subTest ("get_args of Concatenate in TypeAliasType" ):
7570+ if not TYPING_3_9_0 :
7571+ # args are: ([<class 'int'>, ~P2],)
7572+ self .skipTest ("Nested ParamSpec is not substituted" )
7573+ if sys .version_info < (3 , 10 , 2 ):
7574+ self .skipTest ("GenericAlias keeps Concatenate in __args__ prior to 3.10.2" )
7575+ self .assertEqual (get_args (concat_usage ), ((int , str ),))
7576+ with self .subTest ("Equality of parameter_expression without []" ):
7577+ if not TYPING_3_10_0 :
7578+ self .skipTest ("Nested list is invalid type form" )
7579+ self .assertEqual (concat_usage , callable_concat [[str ]])
7580+
7581+ def test_substitution (self ):
7582+ T = TypeVar ('T' )
7583+ Ts = TypeVarTuple ("Ts" )
7584+
7585+ CallableTs = TypeAliasType ("CallableTs" , Callable [[Unpack [Ts ]], Any ], type_params = (Ts , ))
7586+ unpack_callable = CallableTs [Unpack [Tuple [int , T ]]]
7587+ self .assertEqual (get_args (unpack_callable ), (Unpack [Tuple [int , T ]],))
7588+
7589+ P = ParamSpec ('P' )
7590+ CallableP = TypeAliasType ("CallableP" , Callable [P , T ], type_params = (P , T ))
7591+ callable_concat = CallableP [Concatenate [int , P ], Any ]
7592+ self .assertEqual (get_args (callable_concat ), (Concatenate [int , P ], Any ))
7593+
7594+ def test_wrong_amount_of_parameters (self ):
7595+ T = TypeVar ('T' )
7596+ T2 = TypeVar ("T2" )
7597+ P = ParamSpec ('P' )
7598+ ListOrSetT = TypeAliasType ("ListOrSetT" , Union [List [T ], Set [T ]], type_params = (T ,))
7599+ TwoT = TypeAliasType ("TwoT" , Union [List [T ], Set [T2 ]], type_params = (T , T2 ))
7600+ CallablePT = TypeAliasType ("CallablePT" , Callable [P , T ], type_params = (P , T ))
7601+
7602+ # Not enough parameters
7603+ test_cases = [
7604+ # not_enough
7605+ (TwoT [int ], [(int ,), ()]),
7606+ (TwoT [T ], [(T ,), (T ,)]),
7607+ # callable and not enough
7608+ (CallablePT [int ], [(int ,), ()]),
7609+ # too many
7610+ (ListOrSetT [int , bool ], [(int , bool ), ()]),
7611+ # callable and too many
7612+ (CallablePT [str , float , int ], [(str , float , int ), ()]),
7613+ # Check if TypeVar is still present even if over substituted
7614+ (ListOrSetT [int , T ], [(int , T ), (T ,)]),
7615+ # With and without list for ParamSpec
7616+ (CallablePT [str , float , T ], [(str , float , T ), (T ,)]),
7617+ (CallablePT [[str ], float , int , T2 ], [([str ], float , int , T2 ), (T2 ,)]),
7618+ ]
7619+
7620+ for index , (alias , [expected_args , expected_params ]) in enumerate (test_cases ):
7621+ with self .subTest (index = index , alias = alias ):
7622+ self .assertEqual (get_args (alias ), expected_args )
7623+ self .assertEqual (alias .__parameters__ , expected_params )
7624+
7625+ # The condition should align with the version of GeneriAlias usage in __getitem__ or be 3.11+
7626+ @skipIf (TYPING_3_10_0 , "Most arguments are allowed in 3.11+ or with GenericAlias" )
7627+ def test_invalid_cases_before_3_10 (self ):
7628+ T = TypeVar ('T' )
7629+ ListOrSetT = TypeAliasType ("ListOrSetT" , Union [List [T ], Set [T ]], type_params = (T ,))
7630+ with self .assertRaises (TypeError ):
7631+ ListOrSetT [Generic [T ]]
7632+ with self .assertRaises (TypeError ):
7633+ ListOrSetT [(Generic [T ], )]
7634+
74467635 def test_unpack_parameter_collection (self ):
74477636 Ts = TypeVarTuple ("Ts" )
74487637
0 commit comments