]> git.ipfire.org Git - thirdparty/Python/cpython.git/commitdiff
bpo-44791: Accept ellipsis as the last argument of typing.Concatenate (#30969)
authorSerhiy Storchaka <storchaka@gmail.com>
Fri, 29 Apr 2022 21:01:40 +0000 (00:01 +0300)
committerGitHub <noreply@github.com>
Fri, 29 Apr 2022 21:01:40 +0000 (15:01 -0600)
Doc/library/typing.rst
Lib/test/test_typing.py
Lib/typing.py
Misc/NEWS.d/next/Library/2022-01-27-14-46-15.bpo-44791.tR1JFG.rst [new file with mode: 0644]

index d4a6f32aa36d2caee426e1ee7fa1f7ad33ca111d..0de380551c9fb441640dd8b4d147c9bc66719caf 100644 (file)
@@ -852,7 +852,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
index dab549b17e149c82cb98cb7185f0ec52783b81fb..929f0df960ae03439a3cb510f04da5a9b085d408 100644 (file)
@@ -1755,8 +1755,7 @@ class BaseCallableTests:
         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),
@@ -1767,8 +1766,7 @@ class BaseCallableTests:
         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
@@ -6739,8 +6737,7 @@ class ConcatenateTests(BaseTestCase):
         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])
@@ -6748,8 +6745,7 @@ class ConcatenateTests(BaseTestCase):
         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):
index f4d4fa4d6713c5c120db1f378828481a78c3a45f..b250f2992dfff38d6761bc81047dc6781ebcbf47 100644 (file)
@@ -714,9 +714,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,
@@ -1641,9 +1641,6 @@ class _ConcatenateGenericAlias(_GenericAlias, _root=True):
             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 (file)
index 0000000..31c6dcc
--- /dev/null
@@ -0,0 +1 @@
+Accept ellipsis as the last argument of :data:`typing.Concatenate`.