]> granicus.if.org Git - python/commitdiff
bpo-27541: Reprs of subclasses of some classes now contain actual type name. (#3631)
authorSerhiy Storchaka <storchaka@gmail.com>
Thu, 21 Sep 2017 11:24:13 +0000 (14:24 +0300)
committerGitHub <noreply@github.com>
Thu, 21 Sep 2017 11:24:13 +0000 (14:24 +0300)
Affected classes are bytearray, array, deque, defaultdict, count and repeat.

Lib/test/test_defaultdict.py
Misc/NEWS.d/next/Library/2017-09-17-19-59-04.bpo-27541.cIMFJW.rst [new file with mode: 0644]
Modules/_collectionsmodule.c
Modules/arraymodule.c
Modules/itertoolsmodule.c
Objects/bytearrayobject.c

index 72183498acb7912de5d3c07483c39416da89c6c5..b9f1fb9f23d39d27b92e88df16c3ab439ca60db0 100644 (file)
@@ -157,8 +157,8 @@ class TestDefaultDict(unittest.TestCase):
                 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.
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 (file)
index 0000000..c5c058c
--- /dev/null
@@ -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.
index 8766d86dd3ef37118412a43038e03209d0f0d3cc..e78399ddefa43c0ee7a7eef987520cd2fbdeb33a 100644 (file)
@@ -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);
index 1d9a4f11d8766e65016302875e6c2b2828d4892e..4f778a2dea3ec336be1691770ef86e4625de5ffc 100644 (file)
@@ -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;
 }
index 0e5cbbd18dd69455ba91f03c5d31fc1cf5f7a7da..48e6c35db4fe0434eb75e88f4541c4d3c86ba6fd 100644 (file)
@@ -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 *
index d09b1f22b44d0ba810831a224c3addf2b498a9e1..840d5b0f9baaf339bb78712673184b211b8dc04b 100644 (file)
@@ -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;
 }