@@ -3705,6 +3705,10 @@ def __call__(self, *args: P.args, **kwargs: P.kwargs) -> T: ...
37053705 self .assertEqual (Y .__parameters__ , ())
37063706 self .assertEqual (Y .__args__ , ((int , str , str ), bytes , memoryview ))
37073707
3708+ # Regression test; fixing #126 might cause an error here
3709+ with self .assertRaisesRegex (TypeError , "not a generic class" ):
3710+ Y [int ]
3711+
37083712 def test_protocol_generic_over_typevartuple (self ):
37093713 Ts = TypeVarTuple ("Ts" )
37103714 T = TypeVar ("T" )
@@ -5259,6 +5263,7 @@ class X(Generic[T, P]):
52595263 class Y (Protocol [T , P ]):
52605264 pass
52615265
5266+ things = "arguments" if sys .version_info >= (3 , 10 ) else "parameters"
52625267 for klass in X , Y :
52635268 with self .subTest (klass = klass .__name__ ):
52645269 G1 = klass [int , P_2 ]
@@ -5273,20 +5278,76 @@ class Y(Protocol[T, P]):
52735278 self .assertEqual (G3 .__args__ , (int , Concatenate [int , ...]))
52745279 self .assertEqual (G3 .__parameters__ , ())
52755280
5281+ with self .assertRaisesRegex (
5282+ TypeError ,
5283+ f"Too few { things } for { klass } "
5284+ ):
5285+ klass [int ]
5286+
52765287 # The following are some valid uses cases in PEP 612 that don't work:
52775288 # These do not work in 3.9, _type_check blocks the list and ellipsis.
52785289 # G3 = X[int, [int, bool]]
52795290 # G4 = X[int, ...]
52805291 # G5 = Z[[int, str, bool]]
5281- # Not working because this is special-cased in 3.10.
5282- # G6 = Z[int, str, bool]
5292+
5293+ def test_single_argument_generic (self ):
5294+ P = ParamSpec ("P" )
5295+ T = TypeVar ("T" )
5296+ P_2 = ParamSpec ("P_2" )
52835297
52845298 class Z (Generic [P ]):
52855299 pass
52865300
52875301 class ProtoZ (Protocol [P ]):
52885302 pass
52895303
5304+ things = "arguments" if sys .version_info >= (3 , 10 ) else "parameters"
5305+ for klass in Z , ProtoZ :
5306+ with self .subTest (klass = klass .__name__ ):
5307+ # Note: For 3.10+ __args__ are nested tuples here ((int, ),) instead of (int, )
5308+ G6 = klass [int , str , bool ]
5309+ G6args = G6 .__args__ [0 ] if sys .version_info >= (3 , 10 ) else G6 .__args__
5310+ self .assertEqual (G6args , (int , str , bool ))
5311+ self .assertEqual (G6 .__parameters__ , ())
5312+
5313+ # P = [int]
5314+ G7 = klass [int ]
5315+ G7args = G7 .__args__ [0 ] if sys .version_info >= (3 , 10 ) else G7 .__args__
5316+ self .assertEqual (G7args , (int ,))
5317+ self .assertEqual (G7 .__parameters__ , ())
5318+
5319+ # P = [int, int, ...]
5320+ G8 = klass [T , Concatenate [int , ...]]
5321+ G8args = G8 .__args__ [0 ] if sys .version_info >= (3 , 10 ) else G8 .__args__
5322+ self .assertEqual (G8args , (T , Concatenate [int , ...]))
5323+
5324+ # P = [int, int, P_2]
5325+ G9 = klass [int , Concatenate [T , P_2 ]]
5326+ G9args = G9 .__args__ [0 ] if sys .version_info >= (3 , 10 ) else G9 .__args__
5327+ self .assertEqual (G9args , (int , Concatenate [T , P_2 ]))
5328+
5329+ with self .subTest ("Recursive ParamSpec Test A" ):
5330+ if sys .version_info [:2 ] == (3 , 10 ):
5331+ self .skipTest ("Parameter detection fails in 3.10" )
5332+ with self .assertRaisesRegex (TypeError , f"Too few { things } " ):
5333+ G9 [int ] # for python 3.10 this has no parameters
5334+ self .assertEqual (G8 .__parameters__ , (T ,))
5335+ self .assertEqual (G9 .__parameters__ , (T , P_2 ))
5336+
5337+ with self .subTest ("Recursive ParamSpec Test B" ):
5338+ if sys .version_info [:2 ] == (3 , 10 ):
5339+ self .skipTest ("Parameter detection fails in 3.10" )
5340+ if (3 , 11 , 0 ) <= sys .version_info [:3 ] < (3 , 11 , 3 ):
5341+ self .skipTest ("Wrong recursive substitution" )
5342+ H1 = G8 [int ]
5343+ H2 = G8 [T ][int ]
5344+ self .assertEqual (H2 .__parameters__ , ())
5345+ self .assertEqual (H1 .__parameters__ , ())
5346+ with self .assertRaisesRegex (TypeError , "not a generic class" ):
5347+ H1 [str ] # for python 3.11.0-3 this still has a parameter
5348+ with self .assertRaisesRegex (TypeError , "not a generic class" ):
5349+ H2 [str ] # for python 3.11.0-3 this still has a parameter
5350+
52905351 def test_pickle (self ):
52915352 global P , P_co , P_contra , P_default
52925353 P = ParamSpec ('P' )
0 commit comments