@@ -7267,6 +7267,80 @@ def test_attributes(self):
72677267 self .assertEqual (Variadic .__type_params__ , (Ts ,))
72687268 self .assertEqual (Variadic .__parameters__ , tuple (iter (Ts )))
72697269
7270+ P = ParamSpec ('P' )
7271+ CallableP = TypeAliasType ("CallableP" , Callable [P , Any ], type_params = (P , ))
7272+ self .assertEqual (CallableP .__name__ , "CallableP" )
7273+ self .assertEqual (CallableP .__value__ , Callable [P , Any ])
7274+ self .assertEqual (CallableP .__type_params__ , (P ,))
7275+ self .assertEqual (CallableP .__parameters__ , (P ,))
7276+
7277+ def test_alias_types_and_substitutions (self ):
7278+ T = TypeVar ('T' )
7279+ T2 = TypeVar ('T2' )
7280+ T_default = TypeVar ("T_default" , default = int )
7281+ Ts = TypeVarTuple ("Ts" )
7282+ P = ParamSpec ('P' )
7283+
7284+ test_argument_cases = {
7285+ # arguments : expected parameters
7286+ int : (),
7287+ ... : (),
7288+ None : (),
7289+ T2 : (T2 ,),
7290+ Union [int , List [T2 ]] : (T2 ,),
7291+ Tuple [int , str ] : (),
7292+ Tuple [T , T_default , T2 ] : (T , T_default , T2 ),
7293+ Tuple [Unpack [Ts ]] : (Ts ,),
7294+ Callable [[Unpack [Ts ]], T2 ] : (Ts , T2 ),
7295+ Callable [P , T2 ] : (P , T2 ),
7296+ Callable [Concatenate [T2 , P ], T_default ] : (T2 , P , T_default ),
7297+ TypeAliasType ("NestedAlias" , List [T ], type_params = (T ,))[T2 ] : (T2 ,),
7298+ Unpack [Ts ] : (Ts ,),
7299+ Unpack [Tuple [int , T2 ]] : (T2 ,),
7300+ Concatenate [int , P ] : (P ,),
7301+ # Not tested usage of bare TypeVarTuple, would need 3.11+
7302+ # Ts : (Ts,), # invalid case
7303+ }
7304+
7305+ test_alias_cases = [
7306+ # Simple cases
7307+ TypeAliasType ("ListT" , List [T ], type_params = (T ,)),
7308+ TypeAliasType ("UnionT" , Union [int , List [T ]], type_params = (T ,)),
7309+ # Value has no parameter but in type_param
7310+ TypeAliasType ("ValueWithoutT" , int , type_params = (T ,)),
7311+ # Callable
7312+ TypeAliasType ("CallableP" , Callable [P , Any ], type_params = (P , )),
7313+ TypeAliasType ("CallableT" , Callable [..., T ], type_params = (T , )),
7314+ TypeAliasType ("CallableTs" , Callable [[Unpack [Ts ]], Any ], type_params = (Ts , )),
7315+ # TypeVarTuple
7316+ TypeAliasType ("Variadic" , Tuple [int , Unpack [Ts ]], type_params = (Ts ,)),
7317+ # TypeVar with default
7318+ TypeAliasType ("TupleT_default" , Tuple [T_default , T ], type_params = (T , T_default )),
7319+ TypeAliasType ("CallableT_default" , Callable [[T ], T_default ], type_params = (T , T_default )),
7320+ ]
7321+
7322+ for alias in test_alias_cases :
7323+ with self .subTest (alias = alias , args = []):
7324+ subscripted = alias [[]]
7325+ self .assertEqual (get_args (subscripted ), ([],))
7326+ self .assertEqual (subscripted .__parameters__ , ())
7327+ with self .subTest (alias = alias , args = ()):
7328+ subscripted = alias [()]
7329+ self .assertEqual (get_args (subscripted ), ())
7330+ self .assertEqual (subscripted .__parameters__ , ())
7331+ with self .subTest (alias = alias , args = (int , float )):
7332+ subscripted = alias [int , float ]
7333+ self .assertEqual (get_args (subscripted ), (int , float ))
7334+ self .assertEqual (subscripted .__parameters__ , ())
7335+ with self .subTest (alias = alias , args = [int , float ]):
7336+ subscripted = alias [[int , float ]]
7337+ self .assertEqual (get_args (subscripted ), ([int , float ],))
7338+ self .assertEqual (subscripted .__parameters__ , ())
7339+ for expected_args , expected_parameters in test_argument_cases .items ():
7340+ with self .subTest (alias = alias , args = expected_args ):
7341+ self .assertEqual (get_args (alias [expected_args ]), (expected_args ,))
7342+ self .assertEqual (alias [expected_args ].__parameters__ , expected_parameters )
7343+
72707344 def test_cannot_set_attributes (self ):
72717345 Simple = TypeAliasType ("Simple" , int )
72727346 with self .assertRaisesRegex (AttributeError , "readonly attribute" ):
@@ -7327,12 +7401,19 @@ def test_or(self):
73277401 Alias | "Ref"
73287402
73297403 def test_getitem (self ):
7404+ T = TypeVar ('T' )
73307405 ListOrSetT = TypeAliasType ("ListOrSetT" , Union [List [T ], Set [T ]], type_params = (T ,))
73317406 subscripted = ListOrSetT [int ]
73327407 self .assertEqual (get_args (subscripted ), (int ,))
73337408 self .assertIs (get_origin (subscripted ), ListOrSetT )
7334- with self .assertRaises (TypeError ):
7335- subscripted [str ]
7409+ with self .assertRaisesRegex (TypeError ,
7410+ "not a generic class"
7411+ # types.GenericAlias raises a different error in 3.10
7412+ if sys .version_info [:2 ] != (3 , 10 )
7413+ else "There are no type variables left in ListOrSetT"
7414+ ):
7415+ subscripted [int ]
7416+
73367417
73377418 still_generic = ListOrSetT [Iterable [T ]]
73387419 self .assertEqual (get_args (still_generic ), (Iterable [T ],))
@@ -7341,6 +7422,114 @@ def test_getitem(self):
73417422 self .assertEqual (get_args (fully_subscripted ), (Iterable [float ],))
73427423 self .assertIs (get_origin (fully_subscripted ), ListOrSetT )
73437424
7425+ ValueWithoutTypeVar = TypeAliasType ("ValueWithoutTypeVar" , int , type_params = (T ,))
7426+ still_subscripted = ValueWithoutTypeVar [str ]
7427+ self .assertEqual (get_args (still_subscripted ), (str ,))
7428+
7429+ def test_callable_without_concatenate (self ):
7430+ P = ParamSpec ('P' )
7431+ CallableP = TypeAliasType ("CallableP" , Callable [P , Any ], type_params = (P ,))
7432+ get_args_test_cases = [
7433+ # List of (alias, expected_args)
7434+ # () -> Any
7435+ (CallableP [()], ()),
7436+ (CallableP [[]], ([],)),
7437+ # (int) -> Any
7438+ (CallableP [int ], (int ,)),
7439+ (CallableP [[int ]], ([int ],)),
7440+ # (int, int) -> Any
7441+ (CallableP [int , int ], (int , int )),
7442+ (CallableP [[int , int ]], ([int , int ],)),
7443+ # (...) -> Any
7444+ (CallableP [...], (...,)),
7445+ # (int, ...) -> Any
7446+ (CallableP [[int , ...]], ([int , ...],)),
7447+ ]
7448+
7449+ for index , (expression , expected_args ) in enumerate (get_args_test_cases ):
7450+ with self .subTest (index = index , expression = expression ):
7451+ self .assertEqual (get_args (expression ), expected_args )
7452+
7453+ self .assertEqual (CallableP [...], CallableP [(...,)])
7454+ # (T) -> Any
7455+ CallableT = CallableP [T ]
7456+ self .assertEqual (get_args (CallableT ), (T ,))
7457+ self .assertEqual (CallableT .__parameters__ , (T ,))
7458+
7459+ def test_callable_with_concatenate (self ):
7460+ P = ParamSpec ('P' )
7461+ P2 = ParamSpec ('P2' )
7462+ CallableP = TypeAliasType ("CallableP" , Callable [P , Any ], type_params = (P ,))
7463+
7464+ callable_concat = CallableP [Concatenate [int , P2 ]]
7465+ self .assertEqual (callable_concat .__parameters__ , (P2 ,))
7466+ concat_usage = callable_concat [str ]
7467+ with self .subTest ("get_args of Concatenate in TypeAliasType" ):
7468+ if not TYPING_3_9_0 :
7469+ # args are: ([<class 'int'>, ~P2],)
7470+ self .skipTest ("Nested ParamSpec is not substituted" )
7471+ if sys .version_info < (3 , 10 , 2 ):
7472+ self .skipTest ("GenericAlias keeps Concatenate in __args__ prior to 3.10.2" )
7473+ self .assertEqual (get_args (concat_usage ), ((int , str ),))
7474+ with self .subTest ("Equality of parameter_expression without []" ):
7475+ if not TYPING_3_10_0 :
7476+ self .skipTest ("Nested list is invalid type form" )
7477+ self .assertEqual (concat_usage , callable_concat [[str ]])
7478+
7479+ def test_substitution (self ):
7480+ T = TypeVar ('T' )
7481+ Ts = TypeVarTuple ("Ts" )
7482+
7483+ CallableTs = TypeAliasType ("CallableTs" , Callable [[Unpack [Ts ]], Any ], type_params = (Ts , ))
7484+ unpack_callable = CallableTs [Unpack [Tuple [int , T ]]]
7485+ self .assertEqual (get_args (unpack_callable ), (Unpack [Tuple [int , T ]],))
7486+
7487+ P = ParamSpec ('P' )
7488+ CallableP = TypeAliasType ("CallableP" , Callable [P , T ], type_params = (P , T ))
7489+ callable_concat = CallableP [Concatenate [int , P ], Any ]
7490+ self .assertEqual (get_args (callable_concat ), (Concatenate [int , P ], Any ))
7491+
7492+ def test_wrong_amount_of_parameters (self ):
7493+ T = TypeVar ('T' )
7494+ T2 = TypeVar ("T2" )
7495+ P = ParamSpec ('P' )
7496+ ListOrSetT = TypeAliasType ("ListOrSetT" , Union [List [T ], Set [T ]], type_params = (T ,))
7497+ TwoT = TypeAliasType ("TwoT" , Union [List [T ], Set [T2 ]], type_params = (T , T2 ))
7498+ CallablePT = TypeAliasType ("CallablePT" , Callable [P , T ], type_params = (P , T ))
7499+
7500+ # Not enough parameters
7501+ test_cases = [
7502+ # not_enough
7503+ (TwoT [int ], [(int ,), ()]),
7504+ (TwoT [T ], [(T ,), (T ,)]),
7505+ # callable and not enough
7506+ (CallablePT [int ], [(int ,), ()]),
7507+ # too many
7508+ (ListOrSetT [int , bool ], [(int , bool ), ()]),
7509+ # callable and too many
7510+ (CallablePT [str , float , int ], [(str , float , int ), ()]),
7511+ # Check if TypeVar is still present even if over substituted
7512+ (ListOrSetT [int , T ], [(int , T ), (T ,)]),
7513+ # With and without list for ParamSpec
7514+ (CallablePT [str , float , T ], [(str , float , T ), (T ,)]),
7515+ (CallablePT [[str ], float , int , T2 ], [([str ], float , int , T2 ), (T2 ,)]),
7516+ ]
7517+
7518+ for index , (alias , [expected_args , expected_params ]) in enumerate (test_cases ):
7519+ with self .subTest (index = index , alias = alias ):
7520+ self .assertEqual (get_args (alias ), expected_args )
7521+ self .assertEqual (alias .__parameters__ , expected_params )
7522+
7523+ # The condition should align with the version of GeneriAlias usage in __getitem__ or be 3.11+
7524+ @skipIf (TYPING_3_10_0 , "Most arguments are allowed in 3.11+ or with GenericAlias" )
7525+ def test_invalid_cases_before_3_10 (self ):
7526+ T = TypeVar ('T' )
7527+ ListOrSetT = TypeAliasType ("ListOrSetT" , Union [List [T ], Set [T ]], type_params = (T ,))
7528+ with self .assertRaises (TypeError ):
7529+ ListOrSetT [Generic [T ]]
7530+ with self .assertRaises (TypeError ):
7531+ ListOrSetT [(Generic [T ], )]
7532+
73447533 def test_unpack_parameter_collection (self ):
73457534 Ts = TypeVarTuple ("Ts" )
73467535
0 commit comments