mirror of
https://github.com/python/cpython.git
synced 2025-07-19 09:15:34 +00:00
gh-110721: Remove unused code from suggestions.c after moving PyErr_Display to use the traceback module (#113712)
This commit is contained in:
parent
802d4954f1
commit
a03ec20bcd
12 changed files with 117 additions and 225 deletions
1
Python/stdlib_module_names.h
generated
1
Python/stdlib_module_names.h
generated
|
@ -76,6 +76,7 @@ static const char* _Py_stdlib_module_names[] = {
|
|||
"_string",
|
||||
"_strptime",
|
||||
"_struct",
|
||||
"_suggestions",
|
||||
"_symtable",
|
||||
"_sysconfig",
|
||||
"_thread",
|
||||
|
|
|
@ -178,225 +178,6 @@ _Py_CalculateSuggestions(PyObject *dir,
|
|||
return Py_XNewRef(suggestion);
|
||||
}
|
||||
|
||||
static PyObject *
|
||||
get_suggestions_for_attribute_error(PyAttributeErrorObject *exc)
|
||||
{
|
||||
PyObject *name = exc->name; // borrowed reference
|
||||
PyObject *obj = exc->obj; // borrowed reference
|
||||
|
||||
// Abort if we don't have an attribute name or we have an invalid one
|
||||
if (name == NULL || obj == NULL || !PyUnicode_CheckExact(name)) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
PyObject *dir = PyObject_Dir(obj);
|
||||
if (dir == NULL) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
PyObject *suggestions = _Py_CalculateSuggestions(dir, name);
|
||||
Py_DECREF(dir);
|
||||
return suggestions;
|
||||
}
|
||||
|
||||
static PyObject *
|
||||
offer_suggestions_for_attribute_error(PyAttributeErrorObject *exc)
|
||||
{
|
||||
PyObject* suggestion = get_suggestions_for_attribute_error(exc);
|
||||
if (suggestion == NULL) {
|
||||
return NULL;
|
||||
}
|
||||
// Add a trailer ". Did you mean: (...)?"
|
||||
PyObject* result = PyUnicode_FromFormat(". Did you mean: %R?", suggestion);
|
||||
Py_DECREF(suggestion);
|
||||
return result;
|
||||
}
|
||||
|
||||
static PyObject *
|
||||
get_suggestions_for_name_error(PyObject* name, PyFrameObject* frame)
|
||||
{
|
||||
PyCodeObject *code = PyFrame_GetCode(frame);
|
||||
assert(code != NULL && code->co_localsplusnames != NULL);
|
||||
|
||||
PyObject *varnames = _PyCode_GetVarnames(code);
|
||||
Py_DECREF(code);
|
||||
if (varnames == NULL) {
|
||||
return NULL;
|
||||
}
|
||||
PyObject *dir = PySequence_List(varnames);
|
||||
Py_DECREF(varnames);
|
||||
if (dir == NULL) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
// Are we inside a method and the instance has an attribute called 'name'?
|
||||
int res = PySequence_Contains(dir, &_Py_ID(self));
|
||||
if (res < 0) {
|
||||
goto error;
|
||||
}
|
||||
if (res > 0) {
|
||||
PyObject* locals = PyFrame_GetLocals(frame);
|
||||
if (!locals) {
|
||||
goto error;
|
||||
}
|
||||
PyObject* self = PyDict_GetItemWithError(locals, &_Py_ID(self)); /* borrowed */
|
||||
if (!self) {
|
||||
Py_DECREF(locals);
|
||||
goto error;
|
||||
}
|
||||
|
||||
res = PyObject_HasAttrWithError(self, name);
|
||||
Py_DECREF(locals);
|
||||
if (res < 0) {
|
||||
goto error;
|
||||
}
|
||||
if (res) {
|
||||
Py_DECREF(dir);
|
||||
return PyUnicode_FromFormat("self.%U", name);
|
||||
}
|
||||
}
|
||||
|
||||
PyObject *suggestions = _Py_CalculateSuggestions(dir, name);
|
||||
Py_DECREF(dir);
|
||||
if (suggestions != NULL || PyErr_Occurred()) {
|
||||
return suggestions;
|
||||
}
|
||||
|
||||
dir = PySequence_List(frame->f_frame->f_globals);
|
||||
if (dir == NULL) {
|
||||
return NULL;
|
||||
}
|
||||
suggestions = _Py_CalculateSuggestions(dir, name);
|
||||
Py_DECREF(dir);
|
||||
if (suggestions != NULL || PyErr_Occurred()) {
|
||||
return suggestions;
|
||||
}
|
||||
|
||||
dir = PySequence_List(frame->f_frame->f_builtins);
|
||||
if (dir == NULL) {
|
||||
return NULL;
|
||||
}
|
||||
suggestions = _Py_CalculateSuggestions(dir, name);
|
||||
Py_DECREF(dir);
|
||||
|
||||
return suggestions;
|
||||
|
||||
error:
|
||||
Py_DECREF(dir);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static bool
|
||||
is_name_stdlib_module(PyObject* name)
|
||||
{
|
||||
const char* the_name = PyUnicode_AsUTF8(name);
|
||||
Py_ssize_t len = Py_ARRAY_LENGTH(_Py_stdlib_module_names);
|
||||
for (Py_ssize_t i = 0; i < len; i++) {
|
||||
if (strcmp(the_name, _Py_stdlib_module_names[i]) == 0) {
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static PyObject *
|
||||
offer_suggestions_for_name_error(PyNameErrorObject *exc)
|
||||
{
|
||||
PyObject *name = exc->name; // borrowed reference
|
||||
PyTracebackObject *traceback = (PyTracebackObject *) exc->traceback; // borrowed reference
|
||||
// Abort if we don't have a variable name or we have an invalid one
|
||||
// or if we don't have a traceback to work with
|
||||
if (name == NULL || !PyUnicode_CheckExact(name) ||
|
||||
traceback == NULL || !Py_IS_TYPE(traceback, &PyTraceBack_Type)
|
||||
) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
// Move to the traceback of the exception
|
||||
while (1) {
|
||||
PyTracebackObject *next = traceback->tb_next;
|
||||
if (next == NULL || !Py_IS_TYPE(next, &PyTraceBack_Type)) {
|
||||
break;
|
||||
}
|
||||
else {
|
||||
traceback = next;
|
||||
}
|
||||
}
|
||||
|
||||
PyFrameObject *frame = traceback->tb_frame;
|
||||
assert(frame != NULL);
|
||||
|
||||
PyObject* suggestion = get_suggestions_for_name_error(name, frame);
|
||||
if (suggestion == NULL && PyErr_Occurred()) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
// Add a trailer ". Did you mean: (...)?"
|
||||
PyObject* result = NULL;
|
||||
if (!is_name_stdlib_module(name)) {
|
||||
if (suggestion == NULL) {
|
||||
return NULL;
|
||||
}
|
||||
result = PyUnicode_FromFormat(". Did you mean: %R?", suggestion);
|
||||
} else if (suggestion == NULL) {
|
||||
result = PyUnicode_FromFormat(". Did you forget to import %R?", name);
|
||||
} else {
|
||||
result = PyUnicode_FromFormat(". Did you mean: %R? Or did you forget to import %R?", suggestion, name);
|
||||
}
|
||||
Py_XDECREF(suggestion);
|
||||
return result;
|
||||
}
|
||||
|
||||
static PyObject *
|
||||
offer_suggestions_for_import_error(PyImportErrorObject *exc)
|
||||
{
|
||||
PyObject *mod_name = exc->name; // borrowed reference
|
||||
PyObject *name = exc->name_from; // borrowed reference
|
||||
if (name == NULL || mod_name == NULL || name == Py_None ||
|
||||
!PyUnicode_CheckExact(name) || !PyUnicode_CheckExact(mod_name)) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
PyObject* mod = PyImport_GetModule(mod_name);
|
||||
if (mod == NULL) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
PyObject *dir = PyObject_Dir(mod);
|
||||
Py_DECREF(mod);
|
||||
if (dir == NULL) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
PyObject *suggestion = _Py_CalculateSuggestions(dir, name);
|
||||
Py_DECREF(dir);
|
||||
if (!suggestion) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
PyObject* result = PyUnicode_FromFormat(". Did you mean: %R?", suggestion);
|
||||
Py_DECREF(suggestion);
|
||||
return result;
|
||||
}
|
||||
|
||||
// Offer suggestions for a given exception. Returns a python string object containing the
|
||||
// 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());
|
||||
if (Py_IS_TYPE(exception, (PyTypeObject*)PyExc_AttributeError)) {
|
||||
result = offer_suggestions_for_attribute_error((PyAttributeErrorObject *) exception);
|
||||
} else if (Py_IS_TYPE(exception, (PyTypeObject*)PyExc_NameError)) {
|
||||
result = offer_suggestions_for_name_error((PyNameErrorObject *) exception);
|
||||
} else if (Py_IS_TYPE(exception, (PyTypeObject*)PyExc_ImportError)) {
|
||||
result = offer_suggestions_for_import_error((PyImportErrorObject *) exception);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
Py_ssize_t
|
||||
_Py_UTF8_Edit_Cost(PyObject *a, PyObject *b, Py_ssize_t max_cost)
|
||||
{
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue