]> git.ipfire.org Git - thirdparty/Python/cpython.git/commitdiff
gh-98852: Fix subscription of type aliases (GH-98920)
authorSerhiy Storchaka <storchaka@gmail.com>
Tue, 1 Nov 2022 07:33:09 +0000 (09:33 +0200)
committerGitHub <noreply@github.com>
Tue, 1 Nov 2022 07:33:09 +0000 (09:33 +0200)
Fix subscription of type aliases containing bare generic types or types
like TypeVar: for example tuple[A, T][int] and tuple[TypeVar, T][int],
where A is a generic type, and T is a type variable.

Lib/test/test_typing.py
Lib/typing.py
Misc/NEWS.d/next/Core and Builtins/2022-10-31-21-01-35.gh-issue-98852.MYaRN6.rst [new file with mode: 0644]
Objects/genericaliasobject.c

index 9571d9529034cb22f3f99e63c3716bd7a6875aaf..f8168bd19f4e820de60748952d6d3c3cc3c30efd 100644 (file)
@@ -3916,6 +3916,34 @@ class GenericTests(BaseTestCase):
         # C version of GenericAlias
         self.assertEqual(list[A()].__parameters__, (T,))
 
+    def test_non_generic_subscript(self):
+        T = TypeVar('T')
+        class G(Generic[T]):
+            pass
+        class A:
+            __parameters__ = (T,)
+
+        for s in (int, G, A, List, list,
+                  TypeVar, TypeVarTuple, ParamSpec,
+                  types.GenericAlias, types.UnionType):
+
+            for t in Tuple, tuple:
+                with self.subTest(tuple=t, sub=s):
+                    self.assertEqual(t[s, T][int], t[s, int])
+                    self.assertEqual(t[T, s][int], t[int, s])
+                    a = t[s]
+                    with self.assertRaises(TypeError):
+                        a[int]
+
+            for c in Callable, collections.abc.Callable:
+                with self.subTest(callable=c, sub=s):
+                    self.assertEqual(c[[s], T][int], c[[s], int])
+                    self.assertEqual(c[[T], s][int], c[[int], s])
+                    a = c[[s], s]
+                    with self.assertRaises(TypeError):
+                        a[int]
+
+
 class ClassVarTests(BaseTestCase):
 
     def test_basics(self):
index 95bd61c7f8c61f4b0c54cf2c933e2e20888bf937..233941598f76a342dff82c0a39d0d3e7ba8357e5 100644 (file)
@@ -1437,6 +1437,10 @@ class _GenericAlias(_BaseGenericAlias, _root=True):
         new_args = []
         for old_arg in self.__args__:
 
+            if isinstance(old_arg, type):
+                new_args.append(old_arg)
+                continue
+
             substfunc = getattr(old_arg, '__typing_subst__', None)
             if substfunc:
                 new_arg = substfunc(new_arg_by_param[old_arg])
diff --git a/Misc/NEWS.d/next/Core and Builtins/2022-10-31-21-01-35.gh-issue-98852.MYaRN6.rst b/Misc/NEWS.d/next/Core and Builtins/2022-10-31-21-01-35.gh-issue-98852.MYaRN6.rst
new file mode 100644 (file)
index 0000000..0e15819
--- /dev/null
@@ -0,0 +1,4 @@
+Fix subscription of type aliases containing bare generic types or types like
+:class:`~typing.TypeVar`: for example ``tuple[A, T][int]`` and
+``tuple[TypeVar, T][int]``, where ``A`` is a generic type, and ``T`` is a
+type variable.
index 19f011fd3a7437f2d00aa98767b4860e089230fe..77acd1bc57a568417e9e741b8aaa3c819230ad60 100644 (file)
@@ -458,6 +458,13 @@ _Py_subs_parameters(PyObject *self, PyObject *args, PyObject *parameters, PyObje
     }
     for (Py_ssize_t iarg = 0, jarg = 0; iarg < nargs; iarg++) {
         PyObject *arg = PyTuple_GET_ITEM(args, iarg);
+        if (PyType_Check(arg)) {
+            Py_INCREF(arg);
+            PyTuple_SET_ITEM(newargs, jarg, arg);
+            jarg++;
+            continue;
+        }
+
         int unpack = _is_unpacked_typevartuple(arg);
         if (unpack < 0) {
             Py_DECREF(newargs);