2525from typing import Pattern , Match
2626from typing import Annotated , ForwardRef
2727from typing import TypeAlias
28+ from typing import ParamSpec , Concatenate
2829import abc
2930import typing
3031import weakref
@@ -1130,10 +1131,6 @@ class P(PR[int, T], Protocol[T]):
11301131 PR [int ]
11311132 with self .assertRaises (TypeError ):
11321133 P [int , str ]
1133- with self .assertRaises (TypeError ):
1134- PR [int , 1 ]
1135- with self .assertRaises (TypeError ):
1136- PR [int , ClassVar ]
11371134
11381135 class C (PR [int , T ]): pass
11391136
@@ -1155,8 +1152,6 @@ class P(PR[int, str], Protocol):
11551152 self .assertIsSubclass (P , PR )
11561153 with self .assertRaises (TypeError ):
11571154 PR [int ]
1158- with self .assertRaises (TypeError ):
1159- PR [int , 1 ]
11601155
11611156 class P1 (Protocol , Generic [T ]):
11621157 def bar (self , x : T ) -> str : ...
@@ -1175,8 +1170,6 @@ def bar(self, x: str) -> str:
11751170 return x
11761171
11771172 self .assertIsInstance (Test (), PSub )
1178- with self .assertRaises (TypeError ):
1179- PR [int , ClassVar ]
11801173
11811174 def test_init_called (self ):
11821175 T = TypeVar ('T' )
@@ -1746,8 +1739,6 @@ def test_extended_generic_rules_eq(self):
17461739 self .assertEqual (typing .Iterable [Tuple [T , T ]][T ], typing .Iterable [Tuple [T , T ]])
17471740 with self .assertRaises (TypeError ):
17481741 Tuple [T , int ][()]
1749- with self .assertRaises (TypeError ):
1750- Tuple [T , U ][T , ...]
17511742
17521743 self .assertEqual (Union [T , int ][int ], int )
17531744 self .assertEqual (Union [T , U ][int , Union [int , str ]], Union [int , str ])
@@ -1759,10 +1750,6 @@ class Derived(Base): ...
17591750
17601751 self .assertEqual (Callable [[T ], T ][KT ], Callable [[KT ], KT ])
17611752 self .assertEqual (Callable [..., List [T ]][int ], Callable [..., List [int ]])
1762- with self .assertRaises (TypeError ):
1763- Callable [[T ], U ][..., int ]
1764- with self .assertRaises (TypeError ):
1765- Callable [[T ], U ][[], int ]
17661753
17671754 def test_extended_generic_rules_repr (self ):
17681755 T = TypeVar ('T' )
@@ -4243,6 +4230,111 @@ def test_cannot_subscript(self):
42434230 TypeAlias [int ]
42444231
42454232
4233+ class ParamSpecTests (BaseTestCase ):
4234+
4235+ def test_basic_plain (self ):
4236+ P = ParamSpec ('P' )
4237+ self .assertEqual (P , P )
4238+ self .assertIsInstance (P , ParamSpec )
4239+
4240+ def test_valid_uses (self ):
4241+ P = ParamSpec ('P' )
4242+ T = TypeVar ('T' )
4243+ C1 = Callable [P , int ]
4244+ self .assertEqual (C1 .__args__ , (P , int ))
4245+ self .assertEqual (C1 .__parameters__ , (P ,))
4246+ C2 = Callable [P , T ]
4247+ self .assertEqual (C2 .__args__ , (P , T ))
4248+ self .assertEqual (C2 .__parameters__ , (P , T ))
4249+ # Test collections.abc.Callable too.
4250+ C3 = collections .abc .Callable [P , int ]
4251+ self .assertEqual (C3 .__args__ , (P , int ))
4252+ self .assertEqual (C3 .__parameters__ , (P ,))
4253+ C4 = collections .abc .Callable [P , T ]
4254+ self .assertEqual (C4 .__args__ , (P , T ))
4255+ self .assertEqual (C4 .__parameters__ , (P , T ))
4256+
4257+ # ParamSpec instances should also have args and kwargs attributes.
4258+ self .assertIn ('args' , dir (P ))
4259+ self .assertIn ('kwargs' , dir (P ))
4260+ P .args
4261+ P .kwargs
4262+
4263+ def test_user_generics (self ):
4264+ T = TypeVar ("T" )
4265+ P = ParamSpec ("P" )
4266+ P_2 = ParamSpec ("P_2" )
4267+
4268+ class X (Generic [T , P ]):
4269+ f : Callable [P , int ]
4270+ x : T
4271+ G1 = X [int , P_2 ]
4272+ self .assertEqual (G1 .__args__ , (int , P_2 ))
4273+ self .assertEqual (G1 .__parameters__ , (P_2 ,))
4274+
4275+ G2 = X [int , Concatenate [int , P_2 ]]
4276+ self .assertEqual (G2 .__args__ , (int , Concatenate [int , P_2 ]))
4277+ self .assertEqual (G2 .__parameters__ , (P_2 ,))
4278+
4279+ G3 = X [int , [int , bool ]]
4280+ self .assertEqual (G3 .__args__ , (int , (int , bool )))
4281+ self .assertEqual (G3 .__parameters__ , ())
4282+
4283+ G4 = X [int , ...]
4284+ self .assertEqual (G4 .__args__ , (int , Ellipsis ))
4285+ self .assertEqual (G4 .__parameters__ , ())
4286+
4287+ class Z (Generic [P ]):
4288+ f : Callable [P , int ]
4289+
4290+ G5 = Z [[int , str , bool ]]
4291+ self .assertEqual (G5 .__args__ , ((int , str , bool ),))
4292+ self .assertEqual (G5 .__parameters__ , ())
4293+
4294+ G6 = Z [int , str , bool ]
4295+ self .assertEqual (G6 .__args__ , ((int , str , bool ),))
4296+ self .assertEqual (G6 .__parameters__ , ())
4297+
4298+ # G5 and G6 should be equivalent according to the PEP
4299+ self .assertEqual (G5 .__args__ , G6 .__args__ )
4300+ self .assertEqual (G5 .__origin__ , G6 .__origin__ )
4301+ self .assertEqual (G5 .__parameters__ , G6 .__parameters__ )
4302+ self .assertEqual (G5 , G6 )
4303+
4304+ def test_var_substitution (self ):
4305+ T = TypeVar ("T" )
4306+ P = ParamSpec ("P" )
4307+ C1 = Callable [P , T ]
4308+ self .assertEqual (C1 [int , str ], Callable [[int ], str ])
4309+ self .assertEqual (C1 [[int , str , dict ], float ], Callable [[int , str , dict ], float ])
4310+
4311+
4312+ class ConcatenateTests (BaseTestCase ):
4313+ def test_basics (self ):
4314+ P = ParamSpec ('P' )
4315+ class MyClass : ...
4316+ c = Concatenate [MyClass , P ]
4317+ self .assertNotEqual (c , Concatenate )
4318+
4319+ def test_valid_uses (self ):
4320+ P = ParamSpec ('P' )
4321+ T = TypeVar ('T' )
4322+ C1 = Callable [Concatenate [int , P ], int ]
4323+ self .assertEqual (C1 .__args__ , (Concatenate [int , P ], int ))
4324+ self .assertEqual (C1 .__parameters__ , (P ,))
4325+ C2 = Callable [Concatenate [int , T , P ], T ]
4326+ self .assertEqual (C2 .__args__ , (Concatenate [int , T , P ], T ))
4327+ self .assertEqual (C2 .__parameters__ , (T , P ))
4328+
4329+ # Test collections.abc.Callable too.
4330+ C3 = collections .abc .Callable [Concatenate [int , P ], int ]
4331+ self .assertEqual (C3 .__args__ , (Concatenate [int , P ], int ))
4332+ self .assertEqual (C3 .__parameters__ , (P ,))
4333+ C4 = collections .abc .Callable [Concatenate [int , T , P ], T ]
4334+ self .assertEqual (C4 .__args__ , (Concatenate [int , T , P ], T ))
4335+ self .assertEqual (C4 .__parameters__ , (T , P ))
4336+
4337+
42464338class AllTests (BaseTestCase ):
42474339 """Tests for __all__."""
42484340
0 commit comments