From 6e75a2033f3c0a8db875f938d568adcf6dda0eaa Mon Sep 17 00:00:00 2001 From: Serhiy Storchaka Date: Sun, 17 Sep 2017 19:59:28 +0300 Subject: [PATCH] bpo-27541: Reprs of subclasses of some classes now contain actual type name. Affected classes are bytearray, array, deque, defaultdict, count and repeat. --- Lib/test/test_defaultdict.py | 4 ++-- .../2017-09-17-19-59-04.bpo-27541.cIMFJW.rst | 4 ++++ Modules/_collectionsmodule.c | 11 +++++++---- Modules/arraymodule.c | 6 ++++-- Modules/itertoolsmodule.c | 19 +++++++++++++------ Objects/bytearrayobject.c | 16 ++++++++++------ 6 files changed, 40 insertions(+), 20 deletions(-) create mode 100644 Misc/NEWS.d/next/Library/2017-09-17-19-59-04.bpo-27541.cIMFJW.rst diff --git a/Lib/test/test_defaultdict.py b/Lib/test/test_defaultdict.py index 72183498acb791..b9f1fb9f23d39d 100644 --- a/Lib/test/test_defaultdict.py +++ b/Lib/test/test_defaultdict.py @@ -157,8 +157,8 @@ def _factory(self): return [] d = sub() self.assertRegex(repr(d), - r"defaultdict\(, \{\}\)") + r"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. diff --git a/Misc/NEWS.d/next/Library/2017-09-17-19-59-04.bpo-27541.cIMFJW.rst b/Misc/NEWS.d/next/Library/2017-09-17-19-59-04.bpo-27541.cIMFJW.rst new file mode 100644 index 00000000000000..c5c058c3b9b734 --- /dev/null +++ b/Misc/NEWS.d/next/Library/2017-09-17-19-59-04.bpo-27541.cIMFJW.rst @@ -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. diff --git a/Modules/_collectionsmodule.c b/Modules/_collectionsmodule.c index 8766d86dd3ef37..e78399ddefa43c 100644 --- a/Modules/_collectionsmodule.c +++ b/Modules/_collectionsmodule.c @@ -1384,10 +1384,12 @@ deque_repr(PyObject *deque) 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; @@ -2127,7 +2129,8 @@ defdict_repr(defdictobject *dd) 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); diff --git a/Modules/arraymodule.c b/Modules/arraymodule.c index 1d9a4f11d8766e..4f778a2dea3ec3 100644 --- a/Modules/arraymodule.c +++ b/Modules/arraymodule.c @@ -2307,7 +2307,8 @@ array_repr(arrayobject *a) 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); @@ -2317,7 +2318,8 @@ array_repr(arrayobject *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; } diff --git a/Modules/itertoolsmodule.c b/Modules/itertoolsmodule.c index 0e5cbbd18dd694..48e6c35db4fe04 100644 --- a/Modules/itertoolsmodule.c +++ b/Modules/itertoolsmodule.c @@ -4067,7 +4067,8 @@ static PyObject * 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); @@ -4076,11 +4077,14 @@ count_repr(countobject *lz) } 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 * @@ -4220,9 +4224,12 @@ 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 * diff --git a/Objects/bytearrayobject.c b/Objects/bytearrayobject.c index d09b1f22b44d0b..840d5b0f9baaf3 100644 --- a/Objects/bytearrayobject.c +++ b/Objects/bytearrayobject.c @@ -891,11 +891,12 @@ bytearray_init(PyByteArrayObject *self, PyObject *args, PyObject *kwds) 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; @@ -905,13 +906,14 @@ bytearray_repr(PyByteArrayObject *self) 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(); @@ -931,6 +933,8 @@ bytearray_repr(PyByteArrayObject *self) } p = buffer; + while (*className) + *p++ = *className++; while (*quote_prefix) *p++ = *quote_prefix++; *p++ = quote; @@ -966,7 +970,7 @@ bytearray_repr(PyByteArrayObject *self) *p++ = *quote_postfix++; } - v = PyUnicode_DecodeASCII(buffer, p - buffer, NULL); + v = PyUnicode_FromStringAndSize(buffer, p - buffer); PyObject_Free(buffer); return v; }