mirror of
https://github.com/python/cpython.git
synced 2025-12-11 03:20:01 +00:00
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:
parent
208a7e957b
commit
f92b9133ef
3 changed files with 15 additions and 8 deletions
|
|
@ -626,8 +626,6 @@ class TypingCallableTests(BaseCallableTests, BaseTestCase):
|
||||||
self.assertEqual(c1.__args__, c2.__args__)
|
self.assertEqual(c1.__args__, c2.__args__)
|
||||||
self.assertEqual(hash(c1.__args__), hash(c2.__args__))
|
self.assertEqual(hash(c1.__args__), hash(c2.__args__))
|
||||||
|
|
||||||
test_errors = skip("known bug #44793")(BaseCallableTests.test_errors)
|
|
||||||
|
|
||||||
|
|
||||||
class CollectionsCallableTests(BaseCallableTests, BaseTestCase):
|
class CollectionsCallableTests(BaseCallableTests, BaseTestCase):
|
||||||
Callable = collections.abc.Callable
|
Callable = collections.abc.Callable
|
||||||
|
|
@ -4588,6 +4586,10 @@ class ParamSpecTests(BaseTestCase):
|
||||||
G1 = X[int, P_2]
|
G1 = X[int, P_2]
|
||||||
self.assertEqual(G1.__args__, (int, P_2))
|
self.assertEqual(G1.__args__, (int, P_2))
|
||||||
self.assertEqual(G1.__parameters__, (P_2,))
|
self.assertEqual(G1.__parameters__, (P_2,))
|
||||||
|
with self.assertRaisesRegex(TypeError, "few arguments for"):
|
||||||
|
X[int]
|
||||||
|
with self.assertRaisesRegex(TypeError, "many arguments for"):
|
||||||
|
X[int, P_2, str]
|
||||||
|
|
||||||
G2 = X[int, Concatenate[int, P_2]]
|
G2 = X[int, Concatenate[int, P_2]]
|
||||||
self.assertEqual(G2.__args__, (int, Concatenate[int, P_2]))
|
self.assertEqual(G2.__args__, (int, Concatenate[int, P_2]))
|
||||||
|
|
|
||||||
|
|
@ -228,7 +228,7 @@ def _check_generic(cls, parameters, elen):
|
||||||
raise TypeError(f"{cls} is not a generic class")
|
raise TypeError(f"{cls} is not a generic class")
|
||||||
alen = len(parameters)
|
alen = len(parameters)
|
||||||
if alen != elen:
|
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}")
|
f" actual {alen}, expected {elen}")
|
||||||
|
|
||||||
def _prepare_paramspec_params(cls, params):
|
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:
|
if len(cls.__parameters__) == 1 and len(params) > 1:
|
||||||
return (params,)
|
return (params,)
|
||||||
else:
|
else:
|
||||||
|
_check_generic(cls, params, len(cls.__parameters__))
|
||||||
_params = []
|
_params = []
|
||||||
# Convert lists to tuples to help other libraries cache the results.
|
# Convert lists to tuples to help other libraries cache the results.
|
||||||
for p, tvar in zip(params, cls.__parameters__):
|
for p, tvar in zip(params, cls.__parameters__):
|
||||||
|
|
@ -1022,9 +1023,10 @@ class _GenericAlias(_BaseGenericAlias, _root=True):
|
||||||
if not isinstance(params, tuple):
|
if not isinstance(params, tuple):
|
||||||
params = (params,)
|
params = (params,)
|
||||||
params = tuple(_type_convert(p) for p in params)
|
params = tuple(_type_convert(p) for p in params)
|
||||||
if self._paramspec_tvars:
|
if (self._paramspec_tvars
|
||||||
if any(isinstance(t, ParamSpec) for t in self.__parameters__):
|
and any(isinstance(t, ParamSpec) for t in self.__parameters__)):
|
||||||
params = _prepare_paramspec_params(self, params)
|
params = _prepare_paramspec_params(self, params)
|
||||||
|
else:
|
||||||
_check_generic(self, params, len(self.__parameters__))
|
_check_generic(self, params, len(self.__parameters__))
|
||||||
|
|
||||||
subst = dict(zip(self.__parameters__, params))
|
subst = dict(zip(self.__parameters__, params))
|
||||||
|
|
@ -1292,6 +1294,7 @@ class Generic:
|
||||||
# Subscripting a regular Generic subclass.
|
# Subscripting a regular Generic subclass.
|
||||||
if any(isinstance(t, ParamSpec) for t in cls.__parameters__):
|
if any(isinstance(t, ParamSpec) for t in cls.__parameters__):
|
||||||
params = _prepare_paramspec_params(cls, params)
|
params = _prepare_paramspec_params(cls, params)
|
||||||
|
else:
|
||||||
_check_generic(cls, params, len(cls.__parameters__))
|
_check_generic(cls, params, len(cls.__parameters__))
|
||||||
return _GenericAlias(cls, params,
|
return _GenericAlias(cls, params,
|
||||||
_typevar_types=(TypeVar, ParamSpec),
|
_typevar_types=(TypeVar, ParamSpec),
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,2 @@
|
||||||
|
Fix checking the number of arguments when subscribe a generic type with
|
||||||
|
``ParamSpec`` parameter.
|
||||||
Loading…
Add table
Add a link
Reference in a new issue