Mailing List Archive

bpo-44793: Fix checking the number of arguments when subscribe a generic type with ParamSpec parameter. (GH-27515)
https://github.com/python/cpython/commit/f92b9133ef67e77605cbd315b6b6c81036ce110e
commit: f92b9133ef67e77605cbd315b6b6c81036ce110e
branch: main
author: Serhiy Storchaka <storchaka@gmail.com>
committer: serhiy-storchaka <storchaka@gmail.com>
date: 2021-08-02T09:17:46+03:00
summary:

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.

files:
A Misc/NEWS.d/next/Library/2021-07-31-20-28-20.bpo-44793.woaQSg.rst
M Lib/test/test_typing.py
M Lib/typing.py

diff --git a/Lib/test/test_typing.py b/Lib/test/test_typing.py
index fbdf634c5c3be..6cd83a1586a13 100644
--- a/Lib/test/test_typing.py
+++ b/Lib/test/test_typing.py
@@ -626,8 +626,6 @@ def test_consistency(self):
self.assertEqual(c1.__args__, c2.__args__)
self.assertEqual(hash(c1.__args__), hash(c2.__args__))

- test_errors = skip("known bug #44793")(BaseCallableTests.test_errors)
-

class CollectionsCallableTests(BaseCallableTests, BaseTestCase):
Callable = collections.abc.Callable
@@ -4588,6 +4586,10 @@ class X(Generic[T, P]):
G1 = X[int, P_2]
self.assertEqual(G1.__args__, (int, 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]]
self.assertEqual(G2.__args__, (int, Concatenate[int, P_2]))
diff --git a/Lib/typing.py b/Lib/typing.py
index 702bb647269d0..16ad5ce7c2d04 100644
--- a/Lib/typing.py
+++ b/Lib/typing.py
@@ -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 @@ def __getitem__(self, params):
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 @@ def __class_getitem__(cls, params):
# 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)
diff --git a/Misc/NEWS.d/next/Library/2021-07-31-20-28-20.bpo-44793.woaQSg.rst b/Misc/NEWS.d/next/Library/2021-07-31-20-28-20.bpo-44793.woaQSg.rst
new file mode 100644
index 0000000000000..1d94d67615a47
--- /dev/null
+++ b/Misc/NEWS.d/next/Library/2021-07-31-20-28-20.bpo-44793.woaQSg.rst
@@ -0,0 +1,2 @@
+Fix checking the number of arguments when subscribe a generic type with
+``ParamSpec`` parameter.

_______________________________________________
Python-checkins mailing list
Python-checkins@python.org
https://mail.python.org/mailman/listinfo/python-checkins
bpo-44793: Fix checking the number of arguments when subscribe a generic type with ParamSpec parameter. (GH-27515) [ In reply to ]
https://github.com/python/cpython/commit/c8db292012dd84aab81eb3ed9146709696a3d290
commit: c8db292012dd84aab81eb3ed9146709696a3d290
branch: 3.10
author: Miss Islington (bot) <31488909+miss-islington@users.noreply.github.com>
committer: miss-islington <31488909+miss-islington@users.noreply.github.com>
date: 2021-08-02T00:08:24-07:00
summary:

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.
(cherry picked from commit f92b9133ef67e77605cbd315b6b6c81036ce110e)

Co-authored-by: Serhiy Storchaka <storchaka@gmail.com>

files:
A Misc/NEWS.d/next/Library/2021-07-31-20-28-20.bpo-44793.woaQSg.rst
M Lib/test/test_typing.py
M Lib/typing.py

diff --git a/Lib/test/test_typing.py b/Lib/test/test_typing.py
index 029a1586a02a1..3d9a347dcb707 100644
--- a/Lib/test/test_typing.py
+++ b/Lib/test/test_typing.py
@@ -620,8 +620,6 @@ def test_consistency(self):
self.assertEqual(c1.__args__, c2.__args__)
self.assertEqual(hash(c1.__args__), hash(c2.__args__))

- test_errors = skip("known bug #44793")(BaseCallableTests.test_errors)
-

class CollectionsCallableTests(BaseCallableTests, BaseTestCase):
Callable = collections.abc.Callable
@@ -4548,6 +4546,10 @@ class X(Generic[T, P]):
G1 = X[int, P_2]
self.assertEqual(G1.__args__, (int, 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]]
self.assertEqual(G2.__args__, (int, Concatenate[int, P_2]))
diff --git a/Lib/typing.py b/Lib/typing.py
index bcb22b2d178c3..e492bd2ee916b 100644
--- a/Lib/typing.py
+++ b/Lib/typing.py
@@ -220,7 +220,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):
@@ -231,6 +231,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__):
@@ -1020,10 +1021,11 @@ def __getitem__(self, params):
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 = []
@@ -1290,7 +1292,8 @@ def __class_getitem__(cls, params):
# 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)
diff --git a/Misc/NEWS.d/next/Library/2021-07-31-20-28-20.bpo-44793.woaQSg.rst b/Misc/NEWS.d/next/Library/2021-07-31-20-28-20.bpo-44793.woaQSg.rst
new file mode 100644
index 0000000000000..1d94d67615a47
--- /dev/null
+++ b/Misc/NEWS.d/next/Library/2021-07-31-20-28-20.bpo-44793.woaQSg.rst
@@ -0,0 +1,2 @@
+Fix checking the number of arguments when subscribe a generic type with
+``ParamSpec`` parameter.

_______________________________________________
Python-checkins mailing list
Python-checkins@python.org
https://mail.python.org/mailman/listinfo/python-checkins