From 78203183373f56911afc1e4a9d7e9a72d0e53cc0 Mon Sep 17 00:00:00 2001 From: Serhiy Storchaka Date: Thu, 27 Jan 2022 14:37:46 +0200 Subject: [PATCH] bpo-44791: Accept ellipsis as the last argument of Concatenate --- Doc/library/typing.rst | 3 ++- Lib/test/test_typing.py | 12 ++++-------- Lib/typing.py | 7 ++----- .../Library/2022-01-27-14-46-15.bpo-44791.tR1JFG.rst | 1 + 4 files changed, 9 insertions(+), 14 deletions(-) create mode 100644 Misc/NEWS.d/next/Library/2022-01-27-14-46-15.bpo-44791.tR1JFG.rst diff --git a/Doc/library/typing.rst b/Doc/library/typing.rst index cdfd403a34ef91..4e6f36dd162ecd 100644 --- a/Doc/library/typing.rst +++ b/Doc/library/typing.rst @@ -725,7 +725,8 @@ These can be used as types in annotations using ``[]``, each having a unique syn callable. Usage is in the form ``Concatenate[Arg1Type, Arg2Type, ..., ParamSpecVariable]``. ``Concatenate`` is currently only valid when used as the first argument to a :data:`Callable`. - The last parameter to ``Concatenate`` must be a :class:`ParamSpec`. + The last parameter to ``Concatenate`` must be a :class:`ParamSpec` or + ellipsis (``...``). For example, to annotate a decorator ``with_lock`` which provides a :class:`threading.Lock` to the decorated function, ``Concatenate`` can be diff --git a/Lib/test/test_typing.py b/Lib/test/test_typing.py index 3069331c2a3541..c783cd8e152e37 100644 --- a/Lib/test/test_typing.py +++ b/Lib/test/test_typing.py @@ -639,8 +639,7 @@ def test_concatenate(self): 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] + self.assertEqual(C[..., int], Callable[Concatenate[int, ...], int]) C = Callable[Concatenate[int, P], int] self.assertEqual(repr(C), @@ -651,8 +650,7 @@ def test_concatenate(self): self.assertEqual(C[[]], Callable[[int], int]) self.assertEqual(C[Concatenate[str, P2]], Callable[Concatenate[int, str, P2], int]) - with self.assertRaises(TypeError): - C[...] + self.assertEqual(C[...], Callable[Concatenate[int, ...], int]) def test_errors(self): Callable = self.Callable @@ -5035,8 +5033,7 @@ def test_var_substitution(self): self.assertEqual(C[int, []], (int,)) self.assertEqual(C[int, Concatenate[str, P2]], Concatenate[int, str, P2]) - with self.assertRaises(TypeError): - C[int, ...] + self.assertEqual(C[int, ...], Concatenate[int, ...]) C = Concatenate[int, P] self.assertEqual(C[P2], Concatenate[int, P2]) @@ -5044,8 +5041,7 @@ def test_var_substitution(self): 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[...] + self.assertEqual(C[...], Concatenate[int, ...]) class TypeGuardTests(BaseTestCase): def test_basics(self): diff --git a/Lib/typing.py b/Lib/typing.py index 36b95d70dea5ba..746dc8dd6a5c49 100644 --- a/Lib/typing.py +++ b/Lib/typing.py @@ -600,9 +600,9 @@ def Concatenate(self, parameters): raise TypeError("Cannot take a Concatenate of no types.") if not isinstance(parameters, tuple): parameters = (parameters,) - if not isinstance(parameters[-1], ParamSpec): + if not (parameters[-1] is ... or isinstance(parameters[-1], ParamSpec)): raise TypeError("The last parameter to Concatenate should be a " - "ParamSpec variable.") + "ParamSpec variable or ellipsis.") msg = "Concatenate[arg, ...]: each arg must be a type." parameters = (*(_type_check(p, msg) for p in parameters[:-1]), parameters[-1]) return _ConcatenateGenericAlias(self, parameters) @@ -1279,9 +1279,6 @@ def copy_with(self, params): return (*params[:-1], *params[-1]) if isinstance(params[-1], _ConcatenateGenericAlias): params = (*params[:-1], *params[-1].__args__) - elif not isinstance(params[-1], ParamSpec): - raise TypeError("The last parameter to Concatenate should be a " - "ParamSpec variable.") return super().copy_with(params) diff --git a/Misc/NEWS.d/next/Library/2022-01-27-14-46-15.bpo-44791.tR1JFG.rst b/Misc/NEWS.d/next/Library/2022-01-27-14-46-15.bpo-44791.tR1JFG.rst new file mode 100644 index 00000000000000..31c6dcc058e94f --- /dev/null +++ b/Misc/NEWS.d/next/Library/2022-01-27-14-46-15.bpo-44791.tR1JFG.rst @@ -0,0 +1 @@ +Accept ellipsis as the last argument of :data:`typing.Concatenate`.