mirror of
https://github.com/python/cpython.git
synced 2025-07-28 13:44:43 +00:00
bpo-44801: Check arguments in substitution of ParamSpec in Callable (GH-27585)
(cherry picked from commit 3875a69547
)
Co-authored-by: Serhiy Storchaka <storchaka@gmail.com>
This commit is contained in:
parent
c2593b4d06
commit
536e35ae6a
4 changed files with 89 additions and 37 deletions
|
@ -575,17 +575,33 @@ class BaseCallableTests:
|
|||
Callable = self.Callable
|
||||
fullname = f"{Callable.__module__}.Callable"
|
||||
P = ParamSpec('P')
|
||||
P2 = ParamSpec('P2')
|
||||
C1 = Callable[P, T]
|
||||
# substitution
|
||||
self.assertEqual(C1[int, str], Callable[[int], str])
|
||||
self.assertEqual(C1[[int], str], Callable[[int], str])
|
||||
self.assertEqual(C1[[int, str], str], Callable[[int, str], str])
|
||||
self.assertEqual(C1[[], str], Callable[[], str])
|
||||
self.assertEqual(C1[..., str], Callable[..., str])
|
||||
self.assertEqual(C1[P2, str], Callable[P2, str])
|
||||
self.assertEqual(C1[Concatenate[int, P2], str],
|
||||
Callable[Concatenate[int, P2], str])
|
||||
self.assertEqual(repr(C1), f"{fullname}[~P, ~T]")
|
||||
self.assertEqual(repr(C1[int, str]), f"{fullname}[[int], str]")
|
||||
self.assertEqual(repr(C1[[int, str], str]), f"{fullname}[[int, str], str]")
|
||||
with self.assertRaises(TypeError):
|
||||
C1[int, str]
|
||||
|
||||
C2 = Callable[P, int]
|
||||
self.assertEqual(C2[[int]], Callable[[int], int])
|
||||
self.assertEqual(C2[[int, str]], Callable[[int, str], int])
|
||||
self.assertEqual(C2[[]], Callable[[], int])
|
||||
self.assertEqual(C2[...], Callable[..., int])
|
||||
self.assertEqual(C2[P2], Callable[P2, int])
|
||||
self.assertEqual(C2[Concatenate[int, P2]],
|
||||
Callable[Concatenate[int, P2], int])
|
||||
# special case in PEP 612 where
|
||||
# X[int, str, float] == X[[int, str, float]]
|
||||
self.assertEqual(C2[int, str, float], C2[[int, str, float]])
|
||||
self.assertEqual(C2[int], Callable[[int], int])
|
||||
self.assertEqual(C2[int, str], Callable[[int, str], int])
|
||||
self.assertEqual(repr(C2), f"{fullname}[~P, int]")
|
||||
self.assertEqual(repr(C2[int, str]), f"{fullname}[[int, str], int]")
|
||||
|
||||
|
@ -4616,6 +4632,29 @@ class ParamSpecTests(BaseTestCase):
|
|||
self.assertEqual(G5.__parameters__, G6.__parameters__)
|
||||
self.assertEqual(G5, G6)
|
||||
|
||||
G7 = Z[int]
|
||||
self.assertEqual(G7.__args__, ((int,),))
|
||||
self.assertEqual(G7.__parameters__, ())
|
||||
|
||||
with self.assertRaisesRegex(TypeError, "many arguments for"):
|
||||
Z[[int, str], bool]
|
||||
with self.assertRaisesRegex(TypeError, "many arguments for"):
|
||||
Z[P_2, bool]
|
||||
|
||||
def test_multiple_paramspecs_in_user_generics(self):
|
||||
P = ParamSpec("P")
|
||||
P2 = ParamSpec("P2")
|
||||
|
||||
class X(Generic[P, P2]):
|
||||
f: Callable[P, int]
|
||||
g: Callable[P2, str]
|
||||
|
||||
G1 = X[[int, str], [bytes]]
|
||||
G2 = X[[int], [str, bytes]]
|
||||
self.assertNotEqual(G1, G2)
|
||||
self.assertEqual(G1.__args__, ((int, str), (bytes,)))
|
||||
self.assertEqual(G2.__args__, ((int,), (str, bytes)))
|
||||
|
||||
def test_no_paramspec_in__parameters__(self):
|
||||
# ParamSpec should not be found in __parameters__
|
||||
# of generics. Usages outside Callable, Concatenate
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue