Skip to content

Commit eb7d6e7

Browse files
authored
gh-105486: Change the repr of ParamSpec list of args in GenericAlias (#105488)
1 parent e212618 commit eb7d6e7

File tree

4 files changed

+62
-1
lines changed

4 files changed

+62
-1
lines changed

Lib/test/test_genericalias.py

+8
Original file line numberDiff line numberDiff line change
@@ -209,6 +209,9 @@ class MyList(list):
209209
def test_repr(self):
210210
class MyList(list):
211211
pass
212+
class MyGeneric:
213+
__class_getitem__ = classmethod(GenericAlias)
214+
212215
self.assertEqual(repr(list[str]), 'list[str]')
213216
self.assertEqual(repr(list[()]), 'list[()]')
214217
self.assertEqual(repr(tuple[int, ...]), 'tuple[int, ...]')
@@ -221,6 +224,11 @@ class MyList(list):
221224
self.assertTrue(repr(MyList[int]).endswith('.BaseTest.test_repr.<locals>.MyList[int]'))
222225
self.assertEqual(repr(list[str]()), '[]') # instances should keep their normal repr
223226

227+
# gh-105488
228+
self.assertTrue(repr(MyGeneric[int]).endswith('MyGeneric[int]'))
229+
self.assertTrue(repr(MyGeneric[[]]).endswith('MyGeneric[[]]'))
230+
self.assertTrue(repr(MyGeneric[[int, str]]).endswith('MyGeneric[[int, str]]'))
231+
224232
def test_exposed_type(self):
225233
import types
226234
a = types.GenericAlias(list, int)

Lib/test/test_type_aliases.py

+16
Original file line numberDiff line numberDiff line change
@@ -142,7 +142,16 @@ def test_subscripting(self):
142142

143143
def test_repr(self):
144144
type Simple = int
145+
type VeryGeneric[T, *Ts, **P] = Callable[P, tuple[T, *Ts]]
146+
145147
self.assertEqual(repr(Simple), "Simple")
148+
self.assertEqual(repr(VeryGeneric), "VeryGeneric")
149+
self.assertEqual(repr(VeryGeneric[int, bytes, str, [float, object]]),
150+
"VeryGeneric[int, bytes, str, [float, object]]")
151+
self.assertEqual(repr(VeryGeneric[int, []]),
152+
"VeryGeneric[int, []]")
153+
self.assertEqual(repr(VeryGeneric[int, [VeryGeneric[int], list[str]]]),
154+
"VeryGeneric[int, [VeryGeneric[int], list[str]]]")
146155

147156
def test_recursive_repr(self):
148157
type Recursive = Recursive
@@ -151,6 +160,13 @@ def test_recursive_repr(self):
151160
type X = list[Y]
152161
type Y = list[X]
153162
self.assertEqual(repr(X), "X")
163+
self.assertEqual(repr(Y), "Y")
164+
165+
type GenericRecursive[X] = list[X | GenericRecursive[X]]
166+
self.assertEqual(repr(GenericRecursive), "GenericRecursive")
167+
self.assertEqual(repr(GenericRecursive[int]), "GenericRecursive[int]")
168+
self.assertEqual(repr(GenericRecursive[GenericRecursive[int]]),
169+
"GenericRecursive[GenericRecursive[int]]")
154170

155171

156172
class TypeAliasConstructorTest(unittest.TestCase):
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
Change the repr of ``ParamSpec`` list of args in ``types.GenericAlias``.

Objects/genericaliasobject.c

+37-1
Original file line numberDiff line numberDiff line change
@@ -121,6 +121,36 @@ ga_repr_item(_PyUnicodeWriter *writer, PyObject *p)
121121
return err;
122122
}
123123

124+
static int
125+
ga_repr_items_list(_PyUnicodeWriter *writer, PyObject *p)
126+
{
127+
assert(PyList_CheckExact(p));
128+
129+
Py_ssize_t len = PyList_GET_SIZE(p);
130+
131+
if (_PyUnicodeWriter_WriteASCIIString(writer, "[", 1) < 0) {
132+
return -1;
133+
}
134+
135+
for (Py_ssize_t i = 0; i < len; i++) {
136+
if (i > 0) {
137+
if (_PyUnicodeWriter_WriteASCIIString(writer, ", ", 2) < 0) {
138+
return -1;
139+
}
140+
}
141+
PyObject *item = PyList_GET_ITEM(p, i);
142+
if (ga_repr_item(writer, item) < 0) {
143+
return -1;
144+
}
145+
}
146+
147+
if (_PyUnicodeWriter_WriteASCIIString(writer, "]", 1) < 0) {
148+
return -1;
149+
}
150+
151+
return 0;
152+
}
153+
124154
static PyObject *
125155
ga_repr(PyObject *self)
126156
{
@@ -148,7 +178,13 @@ ga_repr(PyObject *self)
148178
}
149179
}
150180
PyObject *p = PyTuple_GET_ITEM(alias->args, i);
151-
if (ga_repr_item(&writer, p) < 0) {
181+
if (PyList_CheckExact(p)) {
182+
// Looks like we are working with ParamSpec's list of type args:
183+
if (ga_repr_items_list(&writer, p) < 0) {
184+
goto error;
185+
}
186+
}
187+
else if (ga_repr_item(&writer, p) < 0) {
152188
goto error;
153189
}
154190
}

0 commit comments

Comments
 (0)