diff -r d6501421b86b -r 4ae151db1bd9 Include/object.h --- a/Include/object.h Wed Apr 16 18:33:39 2014 +0200 +++ b/Include/object.h Wed Apr 16 19:11:10 2014 -0400 @@ -508,6 +508,7 @@ PyAPI_FUNC(void) _PyObject_Dump(PyObject *); #endif PyAPI_FUNC(PyObject *) PyObject_Repr(PyObject *); +PyAPI_FUNC(PyObject *) PyObject_SafeRepr(PyObject *); PyAPI_FUNC(PyObject *) PyObject_Str(PyObject *); PyAPI_FUNC(PyObject *) PyObject_ASCII(PyObject *); PyAPI_FUNC(PyObject *) PyObject_Bytes(PyObject *); diff -r d6501421b86b -r 4ae151db1bd9 Objects/object.c --- a/Objects/object.c Wed Apr 16 18:33:39 2014 +0200 +++ b/Objects/object.c Wed Apr 16 19:11:10 2014 -0400 @@ -862,6 +862,7 @@ PyObject_GetAttr(PyObject *v, PyObject *name) { PyTypeObject *tp = Py_TYPE(v); + PyObject *repr = NULL; if (!PyUnicode_Check(name)) { PyErr_Format(PyExc_TypeError, @@ -877,9 +878,16 @@ return NULL; return (*tp->tp_getattr)(v, name_str); } + + repr = PyObject_SafeRepr(v); + if (repr == NULL) + return NULL; + PyErr_Format(PyExc_AttributeError, - "'%.50s' object has no attribute '%U'", - tp->tp_name, name); + "%U has no attribute '%U'", + repr, name); + Py_DECREF(repr); + return NULL; } @@ -899,6 +907,7 @@ PyObject_SetAttr(PyObject *v, PyObject *name, PyObject *value) { PyTypeObject *tp = Py_TYPE(v); + PyObject *repr; int err; if (!PyUnicode_Check(name)) { @@ -925,23 +934,52 @@ } Py_DECREF(name); assert(name->ob_refcnt >= 1); + + repr = PyObject_SafeRepr(v); + if (repr == NULL) + return -1; + if (tp->tp_getattr == NULL && tp->tp_getattro == NULL) PyErr_Format(PyExc_TypeError, - "'%.100s' object has no attributes " + "%U has no attributes " "(%s .%U)", - tp->tp_name, + repr, value==NULL ? "del" : "assign to", name); + else PyErr_Format(PyExc_TypeError, - "'%.100s' object has only read-only attributes " + "%U has only read-only attributes " "(%s .%U)", - tp->tp_name, + repr, value==NULL ? "del" : "assign to", name); + Py_DECREF(repr); + return -1; } +PyObject* +PyObject_SafeRepr(PyObject *obj) +{ + PyTypeObject *tp = Py_TYPE(obj); + PyObject *repr = NULL; + int enter; + + assert(obj); + + if (!Py_ReprEnter(obj)) { + repr = PyObject_Repr(obj); + Py_ReprLeave(obj); + } + + if (repr == NULL) { + repr = PyUnicode_FromFormat("<%.100s object>", tp->tp_name); + } + + return repr; +} + /* Helper to get a pointer to an object's __dict__ slot, if any */ PyObject ** @@ -1018,6 +1056,7 @@ descrgetfunc f; Py_ssize_t dictoffset; PyObject **dictptr; + PyObject *repr = NULL; if (!PyUnicode_Check(name)){ PyErr_Format(PyExc_TypeError, @@ -1088,9 +1127,14 @@ goto done; } + repr = PyObject_SafeRepr(obj); + if (repr == NULL) + goto done; PyErr_Format(PyExc_AttributeError, - "'%.50s' object has no attribute '%U'", - tp->tp_name, name); + "%U has no attribute '%U'", + repr, name); + Py_DECREF(repr); + done: Py_XDECREF(descr); Py_DECREF(name); @@ -1111,6 +1155,7 @@ PyObject *descr; descrsetfunc f; PyObject **dictptr; + PyObject *repr = NULL; int res = -1; if (!PyUnicode_Check(name)){ @@ -1163,16 +1208,22 @@ goto done; } + repr = PyObject_SafeRepr(obj); + if (repr == NULL) + goto done; + if (descr == NULL) { PyErr_Format(PyExc_AttributeError, - "'%.100s' object has no attribute '%U'", - tp->tp_name, name); + "%U has no attribute '%U'", + repr, name); goto done; } PyErr_Format(PyExc_AttributeError, - "'%.50s' object attribute '%U' is read-only", - tp->tp_name, name); + "%U attribute '%U' is read-only", + repr, name); + Py_DECREF(repr); + done: Py_XDECREF(descr); Py_DECREF(name); diff -r d6501421b86b -r 4ae151db1bd9 repr.py --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/repr.py Wed Apr 16 19:11:10 2014 -0400 @@ -0,0 +1,21 @@ +import _pyio + + +x = _pyio.TextIOWrapper() + +repr(x) + + +class Foo(object): + + x = 10 + + # def __repr__(self): + # # self.f + # return '<%r>' % self + + +f = Foo() +#print(repr(f)) + +f.a