@@ -266,7 +266,7 @@ def _collect_parameters(args):
266
266
>>> _collect_parameters((T, Callable[P, T]))
267
267
(~T, ~P)
268
268
"""
269
- # required TypeVarLike cannot appear after TypeVarLike with default
269
+ # required type parameter cannot appear after parameter with default
270
270
default_encountered = False
271
271
parameters = []
272
272
for t in args :
@@ -296,36 +296,32 @@ def _collect_parameters(args):
296
296
return tuple (parameters )
297
297
298
298
299
- def _check_generic (cls , parameters , elen ):
299
+ def _check_generic_specialization (cls , parameters ):
300
300
"""Check correct count for parameters of a generic cls (internal helper).
301
301
302
302
This gives a nice error message in case of count mismatch.
303
303
"""
304
+ elen = len (cls .__parameters__ )
304
305
if not elen :
305
306
raise TypeError (f"{ cls } is not a generic class" )
306
307
alen = len (parameters )
307
308
if alen != elen :
308
- expect_val = elen
309
- if hasattr (cls , "__parameters__" ):
310
- parameters = [p for p in cls .__parameters__ if get_origin (p ) is not Unpack ]
311
-
312
- # deal with TypeVarLike defaults
313
- # required TypeVarLikes cannot appear after a defaulted one.
314
- if alen < elen :
315
- # since we validate TypeVarLike default in _collect_type_vars
316
- # or _collect_parameters we can safely check parameters[alen]
317
- if parameters [alen ].__default__ is not None :
318
- return
319
-
320
- num_default_tv = sum (p .__default__ is not None for p in parameters )
321
-
322
- elen -= num_default_tv
323
-
324
- expect_val = f"at least { elen } "
309
+ # deal with defaults
310
+ if alen < elen :
311
+ # since we validate defaults in _collect_type_vars
312
+ # or _collect_parameters, we can safely check parameters[alen]
313
+ if cls .__parameters__ [alen ].__default__ is not None :
314
+ return
315
+
316
+ elen -= sum (p .__default__ is not None for p in cls .__parameters__ )
317
+ expect_val = f"at least { elen } "
318
+ else :
319
+ expect_val = elen
325
320
326
321
raise TypeError (f"Too { 'many' if alen > elen else 'few' } arguments"
327
322
f" for { cls } ; actual { alen } , expected { expect_val } " )
328
323
324
+
329
325
def _unpack_args (args ):
330
326
newargs = []
331
327
for arg in args :
@@ -1115,11 +1111,15 @@ def _typevartuple_prepare_subst(self, alias, args):
1115
1111
elif left + right > alen :
1116
1112
raise TypeError (f"Too few arguments for { alias } ;"
1117
1113
f" actual { alen } , expected at least { plen - 1 } " )
1114
+ if left == alen - right and self .__default__ is not None :
1115
+ replacement = self .__default__
1116
+ else :
1117
+ replacement = tuple (args [left : alen - right ])
1118
1118
1119
1119
return (
1120
1120
* args [:left ],
1121
1121
* ([fillarg ]* (typevartuple_index - left )),
1122
- tuple ( args [ left : alen - right ]) ,
1122
+ replacement ,
1123
1123
* ([fillarg ]* (plen - right - left - typevartuple_index - 1 )),
1124
1124
* args [alen - right :],
1125
1125
)
@@ -1185,7 +1185,7 @@ def _generic_class_getitem(cls, params):
1185
1185
prepare = getattr (param , '__typing_prepare_subst__' , None )
1186
1186
if prepare is not None :
1187
1187
params = prepare (cls , params )
1188
- _check_generic (cls , params , len ( cls . __parameters__ ) )
1188
+ _check_generic_specialization (cls , params )
1189
1189
1190
1190
new_args = []
1191
1191
for param , new_arg in zip (cls .__parameters__ , params ):
@@ -1578,7 +1578,12 @@ def __getitem__(self, params):
1578
1578
params = (params ,)
1579
1579
msg = "Parameters to generic types must be types."
1580
1580
params = tuple (_type_check (p , msg ) for p in params )
1581
- _check_generic (self , params , self ._nparams )
1581
+ if not self ._nparams :
1582
+ raise TypeError (f"{ self } is not a generic class" )
1583
+ alen = len (params )
1584
+ if alen != self ._nparams :
1585
+ raise TypeError (f"Too { 'many' if alen > self ._nparams else 'few' } arguments for { self } ;"
1586
+ f" actual { alen } , expected { self ._nparams } " )
1582
1587
return self .copy_with (params )
1583
1588
1584
1589
def copy_with (self , params ):
0 commit comments