From 87b91c0bf6558ee1992cca0b56dbd0e076181236 Mon Sep 17 00:00:00 2001 From: sobolevn Date: Wed, 25 Sep 2024 12:15:46 +0300 Subject: [PATCH 1/2] gh-124498: Fix `TypeAliasType` not to be generic, when `type_params=()` --- Lib/test/test_type_aliases.py | 13 +++++++++++++ .../2024-09-25-12-14-58.gh-issue-124498.Ozxs55.rst | 2 ++ Objects/typevarobject.c | 3 ++- 3 files changed, 17 insertions(+), 1 deletion(-) create mode 100644 Misc/NEWS.d/next/Library/2024-09-25-12-14-58.gh-issue-124498.Ozxs55.rst diff --git a/Lib/test/test_type_aliases.py b/Lib/test/test_type_aliases.py index 49d6aa810304fb..254f3803f8f41e 100644 --- a/Lib/test/test_type_aliases.py +++ b/Lib/test/test_type_aliases.py @@ -211,6 +211,19 @@ def test_generic(self): self.assertEqual(TA.__value__, list[T]) self.assertEqual(TA.__type_params__, (T,)) self.assertEqual(TA.__module__, __name__) + self.assertIs(TA[int].__class__, types.GenericAlias) + + def test_not_generic(self): + TA = TypeAliasType("TA", list[int], type_params=()) + self.assertEqual(TA.__name__, "TA") + self.assertEqual(TA.__value__, list[int]) + self.assertEqual(TA.__type_params__, ()) + self.assertEqual(TA.__module__, __name__) + with self.assertRaisesRegex( + TypeError, + "Only generic type aliases are subscriptable", + ): + TA[int] def test_keywords(self): TA = TypeAliasType(name="TA", value=int) diff --git a/Misc/NEWS.d/next/Library/2024-09-25-12-14-58.gh-issue-124498.Ozxs55.rst b/Misc/NEWS.d/next/Library/2024-09-25-12-14-58.gh-issue-124498.Ozxs55.rst new file mode 100644 index 00000000000000..4dbf4eb709733d --- /dev/null +++ b/Misc/NEWS.d/next/Library/2024-09-25-12-14-58.gh-issue-124498.Ozxs55.rst @@ -0,0 +1,2 @@ +Fix :class:`typing.TypeAliasType` not to be generic, when ``type_params`` is +an empty tuple. diff --git a/Objects/typevarobject.c b/Objects/typevarobject.c index d3656155fae330..6c2361f076c24c 100644 --- a/Objects/typevarobject.c +++ b/Objects/typevarobject.c @@ -1957,7 +1957,8 @@ typealias_reduce_impl(typealiasobject *self) static PyObject * typealias_subscript(PyObject *self, PyObject *args) { - if (((typealiasobject *)self)->type_params == NULL) { + typealiasobject *ta = ((typealiasobject *)self); + if (ta->type_params == NULL || PyTuple_GET_SIZE(ta->type_params) == 0) { PyErr_SetString(PyExc_TypeError, "Only generic type aliases are subscriptable"); return NULL; From 210592519186e662eaee31117e09866d138bcb8e Mon Sep 17 00:00:00 2001 From: sobolevn Date: Thu, 26 Sep 2024 15:27:57 +0300 Subject: [PATCH 2/2] Address review --- Lib/test/test_type_aliases.py | 2 +- Objects/typevarobject.c | 14 +++++++++++--- 2 files changed, 12 insertions(+), 4 deletions(-) diff --git a/Lib/test/test_type_aliases.py b/Lib/test/test_type_aliases.py index 254f3803f8f41e..ebb65d8c6cf81b 100644 --- a/Lib/test/test_type_aliases.py +++ b/Lib/test/test_type_aliases.py @@ -211,7 +211,7 @@ def test_generic(self): self.assertEqual(TA.__value__, list[T]) self.assertEqual(TA.__type_params__, (T,)) self.assertEqual(TA.__module__, __name__) - self.assertIs(TA[int].__class__, types.GenericAlias) + self.assertIs(type(TA[int]), types.GenericAlias) def test_not_generic(self): TA = TypeAliasType("TA", list[int], type_params=()) diff --git a/Objects/typevarobject.c b/Objects/typevarobject.c index 6c2361f076c24c..b01c6dc705930c 100644 --- a/Objects/typevarobject.c +++ b/Objects/typevarobject.c @@ -1914,7 +1914,16 @@ typealias_alloc(PyObject *name, PyObject *type_params, PyObject *compute_value, return NULL; } ta->name = Py_NewRef(name); - ta->type_params = Py_IsNone(type_params) ? NULL : Py_XNewRef(type_params); + if ( + type_params == NULL + || Py_IsNone(type_params) + || (PyTuple_Check(type_params) && PyTuple_GET_SIZE(type_params) == 0) + ) { + ta->type_params = NULL; + } + else { + ta->type_params = Py_NewRef(type_params); + } ta->compute_value = Py_XNewRef(compute_value); ta->value = Py_XNewRef(value); ta->module = Py_XNewRef(module); @@ -1957,8 +1966,7 @@ typealias_reduce_impl(typealiasobject *self) static PyObject * typealias_subscript(PyObject *self, PyObject *args) { - typealiasobject *ta = ((typealiasobject *)self); - if (ta->type_params == NULL || PyTuple_GET_SIZE(ta->type_params) == 0) { + if (((typealiasobject *)self)->type_params == NULL) { PyErr_SetString(PyExc_TypeError, "Only generic type aliases are subscriptable"); return NULL;