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:
parent
9adda0cdf8
commit
b3a77964ea
|
@ -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.
|
||||||
|
|
|
@ -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.
|
|
@ -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);
|
||||||
|
|
|
@ -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;
|
||||||
}
|
}
|
||||||
|
|
|
@ -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 *
|
||||||
|
|
|
@ -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;
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue