mirror of
https://github.com/python/cpython.git
synced 2025-09-27 10:50:04 +00:00
bpo-38530: Make sure that failing to generate suggestions on failure will not propagate exceptions (GH-25408)
This commit is contained in:
parent
0c4c436325
commit
e07f4ab26a
3 changed files with 19 additions and 7 deletions
|
@ -1695,6 +1695,20 @@ class AttributeErrorTests(unittest.TestCase):
|
||||||
|
|
||||||
self.assertIn("blech", err.getvalue())
|
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):
|
class ImportErrorTests(unittest.TestCase):
|
||||||
|
|
||||||
|
|
|
@ -962,6 +962,8 @@ print_exception(PyObject *f, PyObject *value)
|
||||||
err += PyFile_WriteString("?", f);
|
err += PyFile_WriteString("?", f);
|
||||||
}
|
}
|
||||||
Py_DECREF(suggestions);
|
Py_DECREF(suggestions);
|
||||||
|
} else if (PyErr_Occurred()) {
|
||||||
|
PyErr_Clear();
|
||||||
}
|
}
|
||||||
err += PyFile_WriteString("\n", f);
|
err += PyFile_WriteString("\n", f);
|
||||||
Py_XDECREF(tb);
|
Py_XDECREF(tb);
|
||||||
|
|
|
@ -89,14 +89,12 @@ calculate_suggestions(PyObject *dir,
|
||||||
PyObject *suggestion = NULL;
|
PyObject *suggestion = NULL;
|
||||||
const char *name_str = PyUnicode_AsUTF8(name);
|
const char *name_str = PyUnicode_AsUTF8(name);
|
||||||
if (name_str == NULL) {
|
if (name_str == NULL) {
|
||||||
PyErr_Clear();
|
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
for (int i = 0; i < dir_size; ++i) {
|
for (int i = 0; i < dir_size; ++i) {
|
||||||
PyObject *item = PyList_GET_ITEM(dir, i);
|
PyObject *item = PyList_GET_ITEM(dir, i);
|
||||||
const char *item_str = PyUnicode_AsUTF8(item);
|
const char *item_str = PyUnicode_AsUTF8(item);
|
||||||
if (item_str == NULL) {
|
if (item_str == NULL) {
|
||||||
PyErr_Clear();
|
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
Py_ssize_t current_distance = levenshtein_distance(name_str, item_str);
|
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);
|
assert(code != NULL && code->co_varnames != NULL);
|
||||||
PyObject *dir = PySequence_List(code->co_varnames);
|
PyObject *dir = PySequence_List(code->co_varnames);
|
||||||
if (dir == NULL) {
|
if (dir == NULL) {
|
||||||
PyErr_Clear();
|
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -168,7 +165,6 @@ offer_suggestions_for_name_error(PyNameErrorObject *exc) {
|
||||||
|
|
||||||
dir = PySequence_List(frame->f_globals);
|
dir = PySequence_List(frame->f_globals);
|
||||||
if (dir == NULL) {
|
if (dir == NULL) {
|
||||||
PyErr_Clear();
|
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
suggestions = calculate_suggestions(dir, name);
|
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
|
// 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 *_Py_Offer_Suggestions(PyObject *exception) {
|
||||||
PyObject *result = NULL;
|
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)) {
|
if (PyErr_GivenExceptionMatches(exception, PyExc_AttributeError)) {
|
||||||
result = offer_suggestions_for_attribute_error((PyAttributeErrorObject *) exception);
|
result = offer_suggestions_for_attribute_error((PyAttributeErrorObject *) exception);
|
||||||
} else if (PyErr_GivenExceptionMatches(exception, PyExc_NameError)) {
|
} else if (PyErr_GivenExceptionMatches(exception, PyExc_NameError)) {
|
||||||
result = offer_suggestions_for_name_error((PyNameErrorObject *) exception);
|
result = offer_suggestions_for_name_error((PyNameErrorObject *) exception);
|
||||||
}
|
}
|
||||||
assert(!PyErr_Occurred());
|
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue