bpo-44791: Fix substitution of ParamSpec in Concatenate with different parameter expressions (GH-27518)

* Substitution with a list of types returns now a tuple of types.
* Substitution with Concatenate returns now a Concatenate with
  concatenated lists of arguments.
* Substitution with Ellipsis is not supported.
This commit is contained in:
Serhiy Storchaka 2022-01-27 14:34:55 +02:00 committed by GitHub
parent 82bce54614
commit ecfacc362d
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
4 changed files with 65 additions and 5 deletions

View file

@ -628,10 +628,31 @@ class BaseCallableTests:
def test_concatenate(self):
Callable = self.Callable
fullname = f"{Callable.__module__}.Callable"
T = TypeVar('T')
P = ParamSpec('P')
C1 = Callable[typing.Concatenate[int, P], int]
self.assertEqual(repr(C1),
f"{fullname}[typing.Concatenate[int, ~P], int]")
P2 = ParamSpec('P2')
C = Callable[Concatenate[int, P], T]
self.assertEqual(repr(C),
f"{fullname}[typing.Concatenate[int, ~P], ~T]")
self.assertEqual(C[P2, int], Callable[Concatenate[int, P2], int])
self.assertEqual(C[[str, float], int], Callable[[int, str, float], int])
self.assertEqual(C[[], int], Callable[[int], int])
self.assertEqual(C[Concatenate[str, P2], int],
Callable[Concatenate[int, str, P2], int])
with self.assertRaises(TypeError):
C[..., int]
C = Callable[Concatenate[int, P], int]
self.assertEqual(repr(C),
f"{fullname}[typing.Concatenate[int, ~P], int]")
self.assertEqual(C[P2], Callable[Concatenate[int, P2], int])
self.assertEqual(C[[str, float]], Callable[[int, str, float], int])
self.assertEqual(C[str, float], Callable[[int, str, float], int])
self.assertEqual(C[[]], Callable[[int], int])
self.assertEqual(C[Concatenate[str, P2]],
Callable[Concatenate[int, str, P2], int])
with self.assertRaises(TypeError):
C[...]
def test_errors(self):
Callable = self.Callable
@ -5004,6 +5025,27 @@ class ConcatenateTests(BaseTestCase):
self.assertEqual(C4.__args__, (Concatenate[int, T, P], T))
self.assertEqual(C4.__parameters__, (T, P))
def test_var_substitution(self):
T = TypeVar('T')
P = ParamSpec('P')
P2 = ParamSpec('P2')
C = Concatenate[T, P]
self.assertEqual(C[int, P2], Concatenate[int, P2])
self.assertEqual(C[int, [str, float]], (int, str, float))
self.assertEqual(C[int, []], (int,))
self.assertEqual(C[int, Concatenate[str, P2]],
Concatenate[int, str, P2])
with self.assertRaises(TypeError):
C[int, ...]
C = Concatenate[int, P]
self.assertEqual(C[P2], Concatenate[int, P2])
self.assertEqual(C[[str, float]], (int, str, float))
self.assertEqual(C[str, float], (int, str, float))
self.assertEqual(C[[]], (int,))
self.assertEqual(C[Concatenate[str, P2]], Concatenate[int, str, P2])
with self.assertRaises(TypeError):
C[...]
class TypeGuardTests(BaseTestCase):
def test_basics(self):