I'm working on issue 1615 [1] and came up with this tidbit, which works [2], but not well enough: slot_tp_getattr_hook(PyObject *self, PyObject *name) { ... + PyObject *error_type, *error_value, *error_traceback; ... + /* if an AttributeError is set, save it and call getattr; if getattr + sets an AttributeError, discard it and return the original + AttributeError */ if (res == NULL && PyErr_ExceptionMatches(PyExc_AttributeError)) { + PyErr_Fetch(&error_type, &error_value, &error_traceback); res = call_attribute(self, getattr, name); + if (res == NULL && PyErr_ExceptionMatches(PyExc_AttributeError)) + PyErr_Restore(error_type, error_value, error_traceback); } So I tried adding in a second call to PyErr_Fetch and adding the original error as context, like so: if (res == NULL && PyErr_ExceptionMatches(PyExc_AttributeError)) { PyErr_Fetch(&ctx_error_type, &ctx_error_value, &ctx_error_traceback); res = call_attribute(self, getattr, name); if (res == NULL && PyErr_ExceptionMatches(PyExc_AttributeError)) { PyErr_Fetch(&error_type, &error_value, &error_traceback); PyException_SetContext(error_value, ctx_error_value); PyErr_Restore(error_type, error_value, error_traceback); } else { Py_DECREF(ctx_error_value); } Py_DECREF(ctx_error_type); Py_DECREF(ctx_error_traceback); } This bit of code won't even finish compiling. I am not sure if my understanding of references (and how these functions create/consume them) or my understanding of when and where to call PyErr_Fetch|Restore or PyException_SetContext is at fault, but I would greatly appreciate somebody correcting my understanding. :) -- ~Ethan~ [1] http://http://bugs.python.org/issue1615 [2] works as in everything compiles, but the resulting behavior introduces a new bug (the message of a 'raise AttributeError' in a __getattr__ is ignored).
RetroSearch is an open source project built by @garambo | Open a GitHub Issue
Search and Browse the WWW like it's 1997 | Search results from DuckDuckGo
HTML:
3.2
| Encoding:
UTF-8
| Version:
0.7.4