diff options
-rw-r--r-- | Lib/test/test_exceptions.py | 14 | ||||
-rw-r--r-- | Python/pythonrun.c | 2 | ||||
-rw-r--r-- | Python/suggestions.c | 10 |
3 files changed, 19 insertions, 7 deletions
diff --git a/Lib/test/test_exceptions.py b/Lib/test/test_exceptions.py index 4f3c9ab..ebeb67b 100644 --- a/Lib/test/test_exceptions.py +++ b/Lib/test/test_exceptions.py @@ -1695,6 +1695,20 @@ class AttributeErrorTests(unittest.TestCase): self.assertIn("blech", err.getvalue()) + def test_attribute_error_with_failing_dict(self): + class T: + bluch = 1 + def __dir__(self): + raise AttributeError("oh no!") + + try: + T().blich + except AttributeError as exc: + with support.captured_stderr() as err: + sys.__excepthook__(*sys.exc_info()) + + self.assertNotIn("blech", err.getvalue()) + self.assertNotIn("oh no!", err.getvalue()) class ImportErrorTests(unittest.TestCase): diff --git a/Python/pythonrun.c b/Python/pythonrun.c index 321b04e..6f84cab 100644 --- a/Python/pythonrun.c +++ b/Python/pythonrun.c @@ -962,6 +962,8 @@ print_exception(PyObject *f, PyObject *value) err += PyFile_WriteString("?", f); } Py_DECREF(suggestions); + } else if (PyErr_Occurred()) { + PyErr_Clear(); } err += PyFile_WriteString("\n", f); Py_XDECREF(tb); diff --git a/Python/suggestions.c b/Python/suggestions.c index 058294f..bdc8e2f 100644 --- a/Python/suggestions.c +++ b/Python/suggestions.c @@ -89,14 +89,12 @@ calculate_suggestions(PyObject *dir, PyObject *suggestion = NULL; const char *name_str = PyUnicode_AsUTF8(name); if (name_str == NULL) { - PyErr_Clear(); return NULL; } for (int i = 0; i < dir_size; ++i) { PyObject *item = PyList_GET_ITEM(dir, i); const char *item_str = PyUnicode_AsUTF8(item); if (item_str == NULL) { - PyErr_Clear(); return NULL; } Py_ssize_t current_distance = levenshtein_distance(name_str, item_str); @@ -156,7 +154,6 @@ offer_suggestions_for_name_error(PyNameErrorObject *exc) { assert(code != NULL && code->co_varnames != NULL); PyObject *dir = PySequence_List(code->co_varnames); if (dir == NULL) { - PyErr_Clear(); return NULL; } @@ -168,7 +165,6 @@ offer_suggestions_for_name_error(PyNameErrorObject *exc) { dir = PySequence_List(frame->f_globals); if (dir == NULL) { - PyErr_Clear(); return NULL; } suggestions = calculate_suggestions(dir, name); @@ -178,16 +174,16 @@ offer_suggestions_for_name_error(PyNameErrorObject *exc) { } // Offer suggestions for a given exception. Returns a python string object containing the -// suggestions. This function does not raise exceptions and returns NULL if no suggestion was found. +// suggestions. This function returns NULL if no suggestion was found or if an exception happened, +// users must call PyErr_Occurred() to disambiguate. PyObject *_Py_Offer_Suggestions(PyObject *exception) { PyObject *result = NULL; - assert(!PyErr_Occurred()); // Check that we are not going to clean any existing exception + assert(!PyErr_Occurred()); if (PyErr_GivenExceptionMatches(exception, PyExc_AttributeError)) { result = offer_suggestions_for_attribute_error((PyAttributeErrorObject *) exception); } else if (PyErr_GivenExceptionMatches(exception, PyExc_NameError)) { result = offer_suggestions_for_name_error((PyNameErrorObject *) exception); } - assert(!PyErr_Occurred()); return result; } |