mirror of
				https://github.com/python/cpython.git
				synced 2025-11-04 07:31:38 +00:00 
			
		
		
		
	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
					
				
					 6 changed files with 40 additions and 20 deletions
				
			
		| 
						 | 
					@ -157,8 +157,8 @@ def _factory(self):
 | 
				
			||||||
                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,10 +4077,13 @@ 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)",
 | 
				
			||||||
 | 
					                                _PyType_Name(Py_TYPE(lz)),
 | 
				
			||||||
                                lz->long_cnt, lz->long_step);
 | 
					                                lz->long_cnt, lz->long_step);
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -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…
	
	Add table
		Add a link
		
	
		Reference in a new issue