From 3402de93fb4fcf4160eb1e1331c36b61c6010dd6 Mon Sep 17 00:00:00 2001 From: sobolevn Date: Thu, 8 Jun 2023 09:10:44 +0300 Subject: [PATCH 1/4] gh-105487: Change the `repr` of `ParamSpec` list of args in `GenericAlias` --- Lib/test/test_type_aliases.py | 16 ++++++++ ...-06-08-09-10-15.gh-issue-105487.dev-WS.rst | 1 + Objects/genericaliasobject.c | 41 ++++++++++++++++++- 3 files changed, 57 insertions(+), 1 deletion(-) create mode 100644 Misc/NEWS.d/next/Core and Builtins/2023-06-08-09-10-15.gh-issue-105487.dev-WS.rst diff --git a/Lib/test/test_type_aliases.py b/Lib/test/test_type_aliases.py index a3067e521e023e..8bdd10d8c32406 100644 --- a/Lib/test/test_type_aliases.py +++ b/Lib/test/test_type_aliases.py @@ -142,7 +142,16 @@ def test_subscripting(self): def test_repr(self): type Simple = int + type VeryGeneric[T, *Ts, **P] = Callable[P, tuple[T, *Ts]] + self.assertEqual(repr(Simple), "Simple") + self.assertEqual(repr(VeryGeneric), "VeryGeneric") + self.assertEqual(repr(VeryGeneric[int, bytes, str, [float, object]]), + "VeryGeneric[int, bytes, str, [float, object]]") + self.assertEqual(repr(VeryGeneric[int, []]), + "VeryGeneric[int, []]") + self.assertEqual(repr(VeryGeneric[int, [VeryGeneric[int], list[str]]]), + "VeryGeneric[int, [VeryGeneric[int], list[str]]]") def test_recursive_repr(self): type Recursive = Recursive @@ -151,6 +160,13 @@ def test_recursive_repr(self): type X = list[Y] type Y = list[X] self.assertEqual(repr(X), "X") + self.assertEqual(repr(Y), "Y") + + type GenericRecursive[X] = list[X | GenericRecursive[X]] + self.assertEqual(repr(GenericRecursive), "GenericRecursive") + self.assertEqual(repr(GenericRecursive[int]), "GenericRecursive[int]") + self.assertEqual(repr(GenericRecursive[GenericRecursive[int]]), + "GenericRecursive[GenericRecursive[int]]") class TypeAliasConstructorTest(unittest.TestCase): diff --git a/Misc/NEWS.d/next/Core and Builtins/2023-06-08-09-10-15.gh-issue-105487.dev-WS.rst b/Misc/NEWS.d/next/Core and Builtins/2023-06-08-09-10-15.gh-issue-105487.dev-WS.rst new file mode 100644 index 00000000000000..9f735db3dc89c3 --- /dev/null +++ b/Misc/NEWS.d/next/Core and Builtins/2023-06-08-09-10-15.gh-issue-105487.dev-WS.rst @@ -0,0 +1 @@ +Change the repr of ``ParamSpec`` list of args in ``types.GenericAlias``. diff --git a/Objects/genericaliasobject.c b/Objects/genericaliasobject.c index 888cb16edd1b46..8a434194b6e007 100644 --- a/Objects/genericaliasobject.c +++ b/Objects/genericaliasobject.c @@ -121,6 +121,39 @@ ga_repr_item(_PyUnicodeWriter *writer, PyObject *p) return err; } +static int +ga_repr_items_list(_PyUnicodeWriter *writer, PyObject *p) +{ + assert(PyList_CheckExact(p)); + + Py_ssize_t len = PyList_GET_SIZE(p); + + if (_PyUnicodeWriter_WriteASCIIString(writer, "[", 1) < 0) { + goto error; + } + + for (Py_ssize_t i = 0; i < len; i++) { + if (i > 0) { + if (_PyUnicodeWriter_WriteASCIIString(writer, ", ", 2) < 0) { + goto error; + } + } + PyObject *item = PyList_GET_ITEM(p, i); + if (ga_repr_item(writer, item) < 0) { + goto error; + } + } + + if (_PyUnicodeWriter_WriteASCIIString(writer, "]", 1) < 0) { + goto error; + } + + return 0; + +error: + return -1; +} + static PyObject * ga_repr(PyObject *self) { @@ -148,7 +181,13 @@ ga_repr(PyObject *self) } } PyObject *p = PyTuple_GET_ITEM(alias->args, i); - if (ga_repr_item(&writer, p) < 0) { + if (PyList_CheckExact(p)) { + // Looks like we are working with ParamSpec's list of type args: + if (ga_repr_items_list(&writer, p) < 0) { + goto error; + } + } + else if (ga_repr_item(&writer, p) < 0) { goto error; } } From 7bc17073a27c0a4cc1a9777c9a0164b13beb661b Mon Sep 17 00:00:00 2001 From: sobolevn Date: Thu, 8 Jun 2023 19:35:20 +0300 Subject: [PATCH 2/4] Address review --- Objects/genericaliasobject.c | 11 ++++------- 1 file changed, 4 insertions(+), 7 deletions(-) diff --git a/Objects/genericaliasobject.c b/Objects/genericaliasobject.c index 8a434194b6e007..117b4e8dfb960a 100644 --- a/Objects/genericaliasobject.c +++ b/Objects/genericaliasobject.c @@ -129,29 +129,26 @@ ga_repr_items_list(_PyUnicodeWriter *writer, PyObject *p) Py_ssize_t len = PyList_GET_SIZE(p); if (_PyUnicodeWriter_WriteASCIIString(writer, "[", 1) < 0) { - goto error; + return -1; } for (Py_ssize_t i = 0; i < len; i++) { if (i > 0) { if (_PyUnicodeWriter_WriteASCIIString(writer, ", ", 2) < 0) { - goto error; + return -1; } } PyObject *item = PyList_GET_ITEM(p, i); if (ga_repr_item(writer, item) < 0) { - goto error; + return -1; } } if (_PyUnicodeWriter_WriteASCIIString(writer, "]", 1) < 0) { - goto error; + return -1; } return 0; - -error: - return -1; } static PyObject * From 4de2f6fe166b2d1c2512cf5a6970af86fee50e1a Mon Sep 17 00:00:00 2001 From: sobolevn Date: Thu, 8 Jun 2023 21:13:42 +0300 Subject: [PATCH 3/4] Add repr test --- Lib/test/test_genericalias.py | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/Lib/test/test_genericalias.py b/Lib/test/test_genericalias.py index 24d4216417521c..bf600a0f4d1834 100644 --- a/Lib/test/test_genericalias.py +++ b/Lib/test/test_genericalias.py @@ -209,6 +209,9 @@ class MyList(list): def test_repr(self): class MyList(list): pass + class MyGeneric: + __class_getitem__ = classmethod(GenericAlias) + self.assertEqual(repr(list[str]), 'list[str]') self.assertEqual(repr(list[()]), 'list[()]') self.assertEqual(repr(tuple[int, ...]), 'tuple[int, ...]') @@ -221,6 +224,11 @@ class MyList(list): self.assertTrue(repr(MyList[int]).endswith('.BaseTest.test_repr..MyList[int]')) self.assertEqual(repr(list[str]()), '[]') # instances should keep their normal repr + # gh-105488 + self.assertTrue(repr(MyGeneric[int]).endswith('MyGeneric[int]')) + self.assertTrue(repr(MyGeneric[[]]).endswith('MyGeneric[[]]')) + self.assertTrue(repr(MyGeneric[[int, str]]).endswith('MyGeneric[[int, str]]')) + def test_exposed_type(self): import types a = types.GenericAlias(list, int) From e2a3d9c57a9b2410e58319c9b01a56ed591195ef Mon Sep 17 00:00:00 2001 From: Jelle Zijlstra Date: Fri, 30 Jun 2023 16:38:20 -0700 Subject: [PATCH 4/4] Rename NEWS file --- ....dev-WS.rst => 2023-06-08-09-10-15.gh-issue-105486.dev-WS.rst} | 0 1 file changed, 0 insertions(+), 0 deletions(-) rename Misc/NEWS.d/next/Core and Builtins/{2023-06-08-09-10-15.gh-issue-105487.dev-WS.rst => 2023-06-08-09-10-15.gh-issue-105486.dev-WS.rst} (100%) diff --git a/Misc/NEWS.d/next/Core and Builtins/2023-06-08-09-10-15.gh-issue-105487.dev-WS.rst b/Misc/NEWS.d/next/Core and Builtins/2023-06-08-09-10-15.gh-issue-105486.dev-WS.rst similarity index 100% rename from Misc/NEWS.d/next/Core and Builtins/2023-06-08-09-10-15.gh-issue-105487.dev-WS.rst rename to Misc/NEWS.d/next/Core and Builtins/2023-06-08-09-10-15.gh-issue-105486.dev-WS.rst