bpo-27541: Reprs of subclasses of some classes now contain actual type name. (#3631)

Affected classes are bytearray, array, deque, defaultdict, count and repeat.
This commit is contained in:
Serhiy Storchaka 2017-09-21 14:24:13 +03:00 committed by GitHub
parent 9adda0cdf8
commit b3a77964ea
6 changed files with 40 additions and 20 deletions

View File

@ -157,8 +157,8 @@ class TestDefaultDict(unittest.TestCase):
return [] return []
d = sub() d = sub()
self.assertRegex(repr(d), self.assertRegex(repr(d),
r"defaultdict\(<bound method .*sub\._factory " r"sub\(<bound method .*sub\._factory "
r"of defaultdict\(\.\.\., \{\}\)>, \{\}\)") r"of sub\(\.\.\., \{\}\)>, \{\}\)")
# NOTE: printing a subclass of a builtin type does not call its # 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. # tp_print slot. So this part is essentially the same test as above.

View File

@ -0,0 +1,4 @@
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.

View File

@ -1384,10 +1384,12 @@ deque_repr(PyObject *deque)
return NULL; return NULL;
} }
if (((dequeobject *)deque)->maxlen >= 0) if (((dequeobject *)deque)->maxlen >= 0)
result = PyUnicode_FromFormat("deque(%R, maxlen=%zd)", result = PyUnicode_FromFormat("%s(%R, maxlen=%zd)",
aslist, ((dequeobject *)deque)->maxlen); _PyType_Name(Py_TYPE(deque)), aslist,
((dequeobject *)deque)->maxlen);
else else
result = PyUnicode_FromFormat("deque(%R)", aslist); result = PyUnicode_FromFormat("%s(%R)",
_PyType_Name(Py_TYPE(deque)), aslist);
Py_ReprLeave(deque); Py_ReprLeave(deque);
Py_DECREF(aslist); Py_DECREF(aslist);
return result; return result;
@ -2127,7 +2129,8 @@ defdict_repr(defdictobject *dd)
Py_DECREF(baserepr); Py_DECREF(baserepr);
return NULL; return NULL;
} }
result = PyUnicode_FromFormat("defaultdict(%U, %U)", result = PyUnicode_FromFormat("%s(%U, %U)",
_PyType_Name(Py_TYPE(dd)),
defrepr, baserepr); defrepr, baserepr);
Py_DECREF(defrepr); Py_DECREF(defrepr);
Py_DECREF(baserepr); Py_DECREF(baserepr);

View File

@ -2307,7 +2307,8 @@ array_repr(arrayobject *a)
len = Py_SIZE(a); len = Py_SIZE(a);
typecode = a->ob_descr->typecode; typecode = a->ob_descr->typecode;
if (len == 0) { 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') { if (typecode == 'u') {
v = array_array_tounicode_impl(a); v = array_array_tounicode_impl(a);
@ -2317,7 +2318,8 @@ array_repr(arrayobject *a)
if (v == NULL) if (v == NULL)
return 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); Py_DECREF(v);
return s; return s;
} }

View File

@ -4067,7 +4067,8 @@ static PyObject *
count_repr(countobject *lz) count_repr(countobject *lz)
{ {
if (lz->cnt != PY_SSIZE_T_MAX) 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)) { if (PyLong_Check(lz->long_step)) {
long step = PyLong_AsLong(lz->long_step); long step = PyLong_AsLong(lz->long_step);
@ -4076,11 +4077,14 @@ count_repr(countobject *lz)
} }
if (step == 1) { if (step == 1) {
/* Don't display step when it is an integer equal to 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)", return PyUnicode_FromFormat("%s(%R, %R)",
lz->long_cnt, lz->long_step); _PyType_Name(Py_TYPE(lz)),
lz->long_cnt, lz->long_step);
} }
static PyObject * static PyObject *
@ -4220,9 +4224,12 @@ static PyObject *
repeat_repr(repeatobject *ro) repeat_repr(repeatobject *ro)
{ {
if (ro->cnt == -1) if (ro->cnt == -1)
return PyUnicode_FromFormat("repeat(%R)", ro->element); return PyUnicode_FromFormat("%s(%R)",
_PyType_Name(Py_TYPE(ro)), ro->element);
else 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 *

View File

@ -891,11 +891,12 @@ bytearray_init(PyByteArrayObject *self, PyObject *args, PyObject *kwds)
static PyObject * static PyObject *
bytearray_repr(PyByteArrayObject *self) 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 = ")"; const char *quote_postfix = ")";
Py_ssize_t length = Py_SIZE(self); Py_ssize_t length = Py_SIZE(self);
/* 15 == strlen(quote_prefix) + 2 + strlen(quote_postfix) + 1 */ /* 6 == strlen(quote_prefix) + 2 + strlen(quote_postfix) + 1 */
size_t newsize; Py_ssize_t newsize;
PyObject *v; PyObject *v;
Py_ssize_t i; Py_ssize_t i;
char *bytes; char *bytes;
@ -905,13 +906,14 @@ bytearray_repr(PyByteArrayObject *self)
char *test, *start; char *test, *start;
char *buffer; 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, PyErr_SetString(PyExc_OverflowError,
"bytearray object is too large to make repr"); "bytearray object is too large to make repr");
return NULL; return NULL;
} }
newsize = 15 + length * 4; newsize += 6 + length * 4;
buffer = PyObject_Malloc(newsize); buffer = PyObject_Malloc(newsize);
if (buffer == NULL) { if (buffer == NULL) {
PyErr_NoMemory(); PyErr_NoMemory();
@ -931,6 +933,8 @@ bytearray_repr(PyByteArrayObject *self)
} }
p = buffer; p = buffer;
while (*className)
*p++ = *className++;
while (*quote_prefix) while (*quote_prefix)
*p++ = *quote_prefix++; *p++ = *quote_prefix++;
*p++ = quote; *p++ = quote;
@ -966,7 +970,7 @@ bytearray_repr(PyByteArrayObject *self)
*p++ = *quote_postfix++; *p++ = *quote_postfix++;
} }
v = PyUnicode_DecodeASCII(buffer, p - buffer, NULL); v = PyUnicode_FromStringAndSize(buffer, p - buffer);
PyObject_Free(buffer); PyObject_Free(buffer);
return v; return v;
} }