]> git.ipfire.org Git - thirdparty/Python/cpython.git/commitdiff
gh-102721: Improve coverage of `_collections_abc._CallableGenericAlias` (#102722)
authorNikita Sobolev <mail@sobolevn.me>
Thu, 16 Mar 2023 14:47:30 +0000 (17:47 +0300)
committerGitHub <noreply@github.com>
Thu, 16 Mar 2023 14:47:30 +0000 (14:47 +0000)
Co-authored-by: Alex Waygood <Alex.Waygood@Gmail.com>
Lib/_collections_abc.py
Lib/test/test_typing.py

index f86b91a5e6fb0d441924f4772926699d03f0da0d..9d7724c33474cc58fb0a9ad1dc983685201706f6 100644 (file)
@@ -481,15 +481,8 @@ class _CallableGenericAlias(GenericAlias):
         # rather than the default types.GenericAlias object.  Most of the
         # code is copied from typing's _GenericAlias and the builtin
         # types.GenericAlias.
-
         if not isinstance(item, tuple):
             item = (item,)
-        # A special case in PEP 612 where if X = Callable[P, int],
-        # then X[int, str] == X[[int, str]].
-        if (len(self.__parameters__) == 1
-                and _is_param_expr(self.__parameters__[0])
-                and item and not _is_param_expr(item[0])):
-            item = (item,)
 
         new_args = super().__getitem__(item).__args__
 
index 89c725cda54f1299a62fb452df35fea84a402cab..c9f55de95c548f9ce76640eac5a6f74a7d56cac9 100644 (file)
@@ -1921,14 +1921,29 @@ class BaseCallableTests:
         self.assertEqual(weakref.ref(alias)(), alias)
 
     def test_pickle(self):
+        global T_pickle, P_pickle, TS_pickle  # needed for pickling
         Callable = self.Callable
-        alias = Callable[[int, str], float]
-        for proto in range(pickle.HIGHEST_PROTOCOL + 1):
-            s = pickle.dumps(alias, proto)
-            loaded = pickle.loads(s)
-            self.assertEqual(alias.__origin__, loaded.__origin__)
-            self.assertEqual(alias.__args__, loaded.__args__)
-            self.assertEqual(alias.__parameters__, loaded.__parameters__)
+        T_pickle = TypeVar('T_pickle')
+        P_pickle = ParamSpec('P_pickle')
+        TS_pickle = TypeVarTuple('TS_pickle')
+
+        samples = [
+            Callable[[int, str], float],
+            Callable[P_pickle, int],
+            Callable[P_pickle, T_pickle],
+            Callable[Concatenate[int, P_pickle], int],
+            Callable[Concatenate[*TS_pickle, P_pickle], int],
+        ]
+        for alias in samples:
+            for proto in range(pickle.HIGHEST_PROTOCOL + 1):
+                with self.subTest(alias=alias, proto=proto):
+                    s = pickle.dumps(alias, proto)
+                    loaded = pickle.loads(s)
+                    self.assertEqual(alias.__origin__, loaded.__origin__)
+                    self.assertEqual(alias.__args__, loaded.__args__)
+                    self.assertEqual(alias.__parameters__, loaded.__parameters__)
+
+        del T_pickle, P_pickle, TS_pickle  # cleaning up global state
 
     def test_var_substitution(self):
         Callable = self.Callable
@@ -1954,6 +1969,16 @@ class BaseCallableTests:
         self.assertEqual(C5[int, str, float],
                          Callable[[typing.List[int], tuple[str, int], float], int])
 
+    def test_type_subst_error(self):
+        Callable = self.Callable
+        P = ParamSpec('P')
+        T = TypeVar('T')
+
+        pat = "Expected a list of types, an ellipsis, ParamSpec, or Concatenate."
+
+        with self.assertRaisesRegex(TypeError, pat):
+            Callable[P, T][0, int]
+
     def test_type_erasure(self):
         Callable = self.Callable
         class C1(Callable):