Skip to content

Commit 81120b6

Browse files
bpo-44791: Accept ellipsis as the last argument of typing.Concatenate (#30969)
1 parent f665616 commit 81120b6

File tree

4 files changed

+9
-14
lines changed

4 files changed

+9
-14
lines changed

Doc/library/typing.rst

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -852,7 +852,8 @@ These can be used as types in annotations using ``[]``, each having a unique syn
852852
callable. Usage is in the form
853853
``Concatenate[Arg1Type, Arg2Type, ..., ParamSpecVariable]``. ``Concatenate``
854854
is currently only valid when used as the first argument to a :data:`Callable`.
855-
The last parameter to ``Concatenate`` must be a :class:`ParamSpec`.
855+
The last parameter to ``Concatenate`` must be a :class:`ParamSpec` or
856+
ellipsis (``...``).
856857

857858
For example, to annotate a decorator ``with_lock`` which provides a
858859
:class:`threading.Lock` to the decorated function, ``Concatenate`` can be

Lib/test/test_typing.py

Lines changed: 4 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1755,8 +1755,7 @@ def test_concatenate(self):
17551755
self.assertEqual(C[[], int], Callable[[int], int])
17561756
self.assertEqual(C[Concatenate[str, P2], int],
17571757
Callable[Concatenate[int, str, P2], int])
1758-
with self.assertRaises(TypeError):
1759-
C[..., int]
1758+
self.assertEqual(C[..., int], Callable[Concatenate[int, ...], int])
17601759

17611760
C = Callable[Concatenate[int, P], int]
17621761
self.assertEqual(repr(C),
@@ -1767,8 +1766,7 @@ def test_concatenate(self):
17671766
self.assertEqual(C[[]], Callable[[int], int])
17681767
self.assertEqual(C[Concatenate[str, P2]],
17691768
Callable[Concatenate[int, str, P2], int])
1770-
with self.assertRaises(TypeError):
1771-
C[...]
1769+
self.assertEqual(C[...], Callable[Concatenate[int, ...], int])
17721770

17731771
def test_errors(self):
17741772
Callable = self.Callable
@@ -6739,17 +6737,15 @@ def test_var_substitution(self):
67396737
self.assertEqual(C[int, []], (int,))
67406738
self.assertEqual(C[int, Concatenate[str, P2]],
67416739
Concatenate[int, str, P2])
6742-
with self.assertRaises(TypeError):
6743-
C[int, ...]
6740+
self.assertEqual(C[int, ...], Concatenate[int, ...])
67446741

67456742
C = Concatenate[int, P]
67466743
self.assertEqual(C[P2], Concatenate[int, P2])
67476744
self.assertEqual(C[[str, float]], (int, str, float))
67486745
self.assertEqual(C[str, float], (int, str, float))
67496746
self.assertEqual(C[[]], (int,))
67506747
self.assertEqual(C[Concatenate[str, P2]], Concatenate[int, str, P2])
6751-
with self.assertRaises(TypeError):
6752-
C[...]
6748+
self.assertEqual(C[...], Concatenate[int, ...])
67536749

67546750
class TypeGuardTests(BaseTestCase):
67556751
def test_basics(self):

Lib/typing.py

Lines changed: 2 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -714,9 +714,9 @@ def Concatenate(self, parameters):
714714
raise TypeError("Cannot take a Concatenate of no types.")
715715
if not isinstance(parameters, tuple):
716716
parameters = (parameters,)
717-
if not isinstance(parameters[-1], ParamSpec):
717+
if not (parameters[-1] is ... or isinstance(parameters[-1], ParamSpec)):
718718
raise TypeError("The last parameter to Concatenate should be a "
719-
"ParamSpec variable.")
719+
"ParamSpec variable or ellipsis.")
720720
msg = "Concatenate[arg, ...]: each arg must be a type."
721721
parameters = (*(_type_check(p, msg) for p in parameters[:-1]), parameters[-1])
722722
return _ConcatenateGenericAlias(self, parameters,
@@ -1641,9 +1641,6 @@ def copy_with(self, params):
16411641
return (*params[:-1], *params[-1])
16421642
if isinstance(params[-1], _ConcatenateGenericAlias):
16431643
params = (*params[:-1], *params[-1].__args__)
1644-
elif not isinstance(params[-1], ParamSpec):
1645-
raise TypeError("The last parameter to Concatenate should be a "
1646-
"ParamSpec variable.")
16471644
return super().copy_with(params)
16481645

16491646

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
Accept ellipsis as the last argument of :data:`typing.Concatenate`.

0 commit comments

Comments
 (0)