bpo-44793: Fix checking the number of arguments when subscribe a generic type with ParamSpec parameter. (GH-27515)

For example Callable[P, T][[int], str, float] will now raise an error.

Use also term "arguments" instead of "parameters" in error
message for too few/many arguments.
This commit is contained in:
Serhiy Storchaka 2021-08-02 09:17:46 +03:00 committed by GitHub
parent 208a7e957b
commit f92b9133ef
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
3 changed files with 15 additions and 8 deletions

View file

@ -228,7 +228,7 @@ def _check_generic(cls, parameters, elen):
raise TypeError(f"{cls} is not a generic class")
alen = len(parameters)
if alen != elen:
raise TypeError(f"Too {'many' if alen > elen else 'few'} parameters for {cls};"
raise TypeError(f"Too {'many' if alen > elen else 'few'} arguments for {cls};"
f" actual {alen}, expected {elen}")
def _prepare_paramspec_params(cls, params):
@ -239,6 +239,7 @@ def _prepare_paramspec_params(cls, params):
if len(cls.__parameters__) == 1 and len(params) > 1:
return (params,)
else:
_check_generic(cls, params, len(cls.__parameters__))
_params = []
# Convert lists to tuples to help other libraries cache the results.
for p, tvar in zip(params, cls.__parameters__):
@ -1022,10 +1023,11 @@ class _GenericAlias(_BaseGenericAlias, _root=True):
if not isinstance(params, tuple):
params = (params,)
params = tuple(_type_convert(p) for p in params)
if self._paramspec_tvars:
if any(isinstance(t, ParamSpec) for t in self.__parameters__):
params = _prepare_paramspec_params(self, params)
_check_generic(self, params, len(self.__parameters__))
if (self._paramspec_tvars
and any(isinstance(t, ParamSpec) for t in self.__parameters__)):
params = _prepare_paramspec_params(self, params)
else:
_check_generic(self, params, len(self.__parameters__))
subst = dict(zip(self.__parameters__, params))
new_args = []
@ -1292,7 +1294,8 @@ class Generic:
# Subscripting a regular Generic subclass.
if any(isinstance(t, ParamSpec) for t in cls.__parameters__):
params = _prepare_paramspec_params(cls, params)
_check_generic(cls, params, len(cls.__parameters__))
else:
_check_generic(cls, params, len(cls.__parameters__))
return _GenericAlias(cls, params,
_typevar_types=(TypeVar, ParamSpec),
_paramspec_tvars=True)