Affected classes are bytearray, array, deque, defaultdict, count and repeat.
return []
d = sub()
self.assertRegex(repr(d),
- r"defaultdict\(<bound method .*sub\._factory "
- r"of defaultdict\(\.\.\., \{\}\)>, \{\}\)")
+ r"sub\(<bound method .*sub\._factory "
+ r"of sub\(\.\.\., \{\}\)>, \{\}\)")
# NOTE: printing a subclass of a builtin type does not call its
# tp_print slot. So this part is essentially the same test as above.
--- /dev/null
+Reprs of subclasses of some collection and iterator classes (`bytearray`,
+`array.array`, `collections.deque`, `collections.defaultdict`,
+`itertools.count`, `itertools.repeat`) now contain actual type name insteads
+of hardcoded name of the base class.
return NULL;
}
if (((dequeobject *)deque)->maxlen >= 0)
- result = PyUnicode_FromFormat("deque(%R, maxlen=%zd)",
- aslist, ((dequeobject *)deque)->maxlen);
+ result = PyUnicode_FromFormat("%s(%R, maxlen=%zd)",
+ _PyType_Name(Py_TYPE(deque)), aslist,
+ ((dequeobject *)deque)->maxlen);
else
- result = PyUnicode_FromFormat("deque(%R)", aslist);
+ result = PyUnicode_FromFormat("%s(%R)",
+ _PyType_Name(Py_TYPE(deque)), aslist);
Py_ReprLeave(deque);
Py_DECREF(aslist);
return result;
Py_DECREF(baserepr);
return NULL;
}
- result = PyUnicode_FromFormat("defaultdict(%U, %U)",
+ result = PyUnicode_FromFormat("%s(%U, %U)",
+ _PyType_Name(Py_TYPE(dd)),
defrepr, baserepr);
Py_DECREF(defrepr);
Py_DECREF(baserepr);
len = Py_SIZE(a);
typecode = a->ob_descr->typecode;
if (len == 0) {
- return PyUnicode_FromFormat("array('%c')", (int)typecode);
+ return PyUnicode_FromFormat("%s('%c')",
+ _PyType_Name(Py_TYPE(a)), (int)typecode);
}
if (typecode == 'u') {
v = array_array_tounicode_impl(a);
if (v == NULL)
return NULL;
- s = PyUnicode_FromFormat("array('%c', %R)", (int)typecode, v);
+ s = PyUnicode_FromFormat("%s('%c', %R)",
+ _PyType_Name(Py_TYPE(a)), (int)typecode, v);
Py_DECREF(v);
return s;
}
count_repr(countobject *lz)
{
if (lz->cnt != PY_SSIZE_T_MAX)
- return PyUnicode_FromFormat("count(%zd)", lz->cnt);
+ return PyUnicode_FromFormat("%s(%zd)",
+ _PyType_Name(Py_TYPE(lz)), lz->cnt);
if (PyLong_Check(lz->long_step)) {
long step = PyLong_AsLong(lz->long_step);
}
if (step == 1) {
/* Don't display step when it is an integer equal to 1 */
- return PyUnicode_FromFormat("count(%R)", lz->long_cnt);
+ return PyUnicode_FromFormat("%s(%R)",
+ _PyType_Name(Py_TYPE(lz)),
+ lz->long_cnt);
}
}
- return PyUnicode_FromFormat("count(%R, %R)",
- lz->long_cnt, lz->long_step);
+ return PyUnicode_FromFormat("%s(%R, %R)",
+ _PyType_Name(Py_TYPE(lz)),
+ lz->long_cnt, lz->long_step);
}
static PyObject *
repeat_repr(repeatobject *ro)
{
if (ro->cnt == -1)
- return PyUnicode_FromFormat("repeat(%R)", ro->element);
+ return PyUnicode_FromFormat("%s(%R)",
+ _PyType_Name(Py_TYPE(ro)), ro->element);
else
- return PyUnicode_FromFormat("repeat(%R, %zd)", ro->element, ro->cnt);
+ return PyUnicode_FromFormat("%s(%R, %zd)",
+ _PyType_Name(Py_TYPE(ro)), ro->element,
+ ro->cnt);
}
static PyObject *
static PyObject *
bytearray_repr(PyByteArrayObject *self)
{
- const char *quote_prefix = "bytearray(b";
+ const char *className = _PyType_Name(Py_TYPE(self));
+ const char *quote_prefix = "(b";
const char *quote_postfix = ")";
Py_ssize_t length = Py_SIZE(self);
- /* 15 == strlen(quote_prefix) + 2 + strlen(quote_postfix) + 1 */
- size_t newsize;
+ /* 6 == strlen(quote_prefix) + 2 + strlen(quote_postfix) + 1 */
+ Py_ssize_t newsize;
PyObject *v;
Py_ssize_t i;
char *bytes;
char *test, *start;
char *buffer;
- if (length > (PY_SSIZE_T_MAX - 15) / 4) {
+ newsize = strlen(className);
+ if (length > (PY_SSIZE_T_MAX - 6 - newsize) / 4) {
PyErr_SetString(PyExc_OverflowError,
"bytearray object is too large to make repr");
return NULL;
}
- newsize = 15 + length * 4;
+ newsize += 6 + length * 4;
buffer = PyObject_Malloc(newsize);
if (buffer == NULL) {
PyErr_NoMemory();
}
p = buffer;
+ while (*className)
+ *p++ = *className++;
while (*quote_prefix)
*p++ = *quote_prefix++;
*p++ = quote;
*p++ = *quote_postfix++;
}
- v = PyUnicode_DecodeASCII(buffer, p - buffer, NULL);
+ v = PyUnicode_FromStringAndSize(buffer, p - buffer);
PyObject_Free(buffer);
return v;
}