diff --git a/Objects/object.c b/Objects/object.c --- a/Objects/object.c +++ b/Objects/object.c @@ -1057,6 +1057,29 @@ /* Generic GetAttr functions - put these in your tp_[gs]etattro slot */ +/* XXX Add generic from_current_raise() and chain_exception()? */ +void +from_current_raise(PyObject *name) +{ + PyObject *cause_tp, *cause_exc, *cause_tb, *tp, *exc, *arg, *msg; + + msg = PyUnicode_FromFormat("getter failed for descriptor '%U'", name); + if (!msg) + return; + exc = PyObject_CallFunctionObjArgs(PyExc_TypeError, msg, NULL); + Py_DECREF(msg); + if (!exc) + return; + + // XXX why does cause_exc lose it's traceback? + PyErr_Fetch(&cause_tp, &cause_exc, &cause_tb); + PyException_SetCause(exc, cause_exc); + PyErr_SetObject(PyExceptionInstance_Class(exc), exc); + Py_XDECREF(cause_tp); + Py_XDECREF(cause_tb); + Py_DECREF(exc); +} + PyObject * _PyObject_GenericGetAttrWithDict(PyObject *obj, PyObject *name, PyObject *dict) { @@ -1089,6 +1112,9 @@ f = descr->ob_type->tp_descr_get; if (f != NULL && PyDescr_IsData(descr)) { res = f(descr, obj, (PyObject *)obj->ob_type); + if (!res && PyErr_ExceptionMatches(PyExc_AttributeError)) { + from_current_raise(name); + } goto done; } } @@ -1127,6 +1153,9 @@ if (f != NULL) { res = f(descr, obj, (PyObject *)Py_TYPE(obj)); + if (!res && PyErr_ExceptionMatches(PyExc_AttributeError)) { + from_current_raise(name); + } goto done; }