summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorPablo Galindo Salgado <Pablogsal@gmail.com>2024-01-08 15:10:45 (GMT)
committerGitHub <noreply@github.com>2024-01-08 15:10:45 (GMT)
commita03ec20bcdf757138557127689405b3a525b3c44 (patch)
treef412c780e0fbf5fd0eaeb0aa48ad52953c461900
parent802d4954f12541ba28dd7f18bf4a65054941a80d (diff)
downloadcpython-a03ec20bcdf757138557127689405b3a525b3c44.zip
cpython-a03ec20bcdf757138557127689405b3a525b3c44.tar.gz
cpython-a03ec20bcdf757138557127689405b3a525b3c44.tar.bz2
gh-110721: Remove unused code from suggestions.c after moving PyErr_Display to use the traceback module (#113712)
-rw-r--r--Include/internal/pycore_global_objects_fini_generated.h1
-rw-r--r--Include/internal/pycore_global_strings.h1
-rw-r--r--Include/internal/pycore_runtime_init_generated.h1
-rw-r--r--Include/internal/pycore_unicodeobject_generated.h3
-rw-r--r--Lib/traceback.py7
-rw-r--r--Modules/Setup.bootstrap.in1
-rw-r--r--Modules/_suggestions.c63
-rw-r--r--Modules/clinic/_suggestions.c.h41
-rw-r--r--PCbuild/pythoncore.vcxproj1
-rw-r--r--PCbuild/pythoncore.vcxproj.filters3
-rw-r--r--Python/stdlib_module_names.h1
-rw-r--r--Python/suggestions.c219
12 files changed, 117 insertions, 225 deletions
diff --git a/Include/internal/pycore_global_objects_fini_generated.h b/Include/internal/pycore_global_objects_fini_generated.h
index 89ec8cb..8dbdc39 100644
--- a/Include/internal/pycore_global_objects_fini_generated.h
+++ b/Include/internal/pycore_global_objects_fini_generated.h
@@ -1164,7 +1164,6 @@ _PyStaticObjects_CheckRefcnt(PyInterpreterState *interp) {
_PyStaticObject_CheckRefcnt((PyObject *)&_Py_ID(seek));
_PyStaticObject_CheckRefcnt((PyObject *)&_Py_ID(seekable));
_PyStaticObject_CheckRefcnt((PyObject *)&_Py_ID(selectors));
- _PyStaticObject_CheckRefcnt((PyObject *)&_Py_ID(self));
_PyStaticObject_CheckRefcnt((PyObject *)&_Py_ID(send));
_PyStaticObject_CheckRefcnt((PyObject *)&_Py_ID(sep));
_PyStaticObject_CheckRefcnt((PyObject *)&_Py_ID(sequence));
diff --git a/Include/internal/pycore_global_strings.h b/Include/internal/pycore_global_strings.h
index 62c3ee3..1fa2d1d 100644
--- a/Include/internal/pycore_global_strings.h
+++ b/Include/internal/pycore_global_strings.h
@@ -653,7 +653,6 @@ struct _Py_global_strings {
STRUCT_FOR_ID(seek)
STRUCT_FOR_ID(seekable)
STRUCT_FOR_ID(selectors)
- STRUCT_FOR_ID(self)
STRUCT_FOR_ID(send)
STRUCT_FOR_ID(sep)
STRUCT_FOR_ID(sequence)
diff --git a/Include/internal/pycore_runtime_init_generated.h b/Include/internal/pycore_runtime_init_generated.h
index 1defa39..8fd922a 100644
--- a/Include/internal/pycore_runtime_init_generated.h
+++ b/Include/internal/pycore_runtime_init_generated.h
@@ -1162,7 +1162,6 @@ extern "C" {
INIT_ID(seek), \
INIT_ID(seekable), \
INIT_ID(selectors), \
- INIT_ID(self), \
INIT_ID(send), \
INIT_ID(sep), \
INIT_ID(sequence), \
diff --git a/Include/internal/pycore_unicodeobject_generated.h b/Include/internal/pycore_unicodeobject_generated.h
index be9baa3..0b5fb73 100644
--- a/Include/internal/pycore_unicodeobject_generated.h
+++ b/Include/internal/pycore_unicodeobject_generated.h
@@ -1800,9 +1800,6 @@ _PyUnicode_InitStaticStrings(PyInterpreterState *interp) {
string = &_Py_ID(selectors);
assert(_PyUnicode_CheckConsistency(string, 1));
_PyUnicode_InternInPlace(interp, &string);
- string = &_Py_ID(self);
- assert(_PyUnicode_CheckConsistency(string, 1));
- _PyUnicode_InternInPlace(interp, &string);
string = &_Py_ID(send);
assert(_PyUnicode_CheckConsistency(string, 1));
_PyUnicode_InternInPlace(interp, &string);
diff --git a/Lib/traceback.py b/Lib/traceback.py
index 1cf008c..30b42a4 100644
--- a/Lib/traceback.py
+++ b/Lib/traceback.py
@@ -1497,6 +1497,13 @@ def _compute_suggestion_error(exc_value, tb, wrong_name):
if hasattr(self, wrong_name):
return f"self.{wrong_name}"
+ try:
+ import _suggestions
+ except ImportError:
+ pass
+ else:
+ return _suggestions._generate_suggestions(d, wrong_name)
+
# Compute closest match
if len(d) > _MAX_CANDIDATE_ITEMS:
diff --git a/Modules/Setup.bootstrap.in b/Modules/Setup.bootstrap.in
index cd12c1b..aa4e60e 100644
--- a/Modules/Setup.bootstrap.in
+++ b/Modules/Setup.bootstrap.in
@@ -11,6 +11,7 @@ faulthandler faulthandler.c
posix posixmodule.c
_signal signalmodule.c
_tracemalloc _tracemalloc.c
+_suggestions _suggestions.c
# modules used by importlib, deepfreeze, freeze, runpy, and sysconfig
_codecs _codecsmodule.c
diff --git a/Modules/_suggestions.c b/Modules/_suggestions.c
new file mode 100644
index 0000000..30b524d
--- /dev/null
+++ b/Modules/_suggestions.c
@@ -0,0 +1,63 @@
+#include "Python.h"
+#include "pycore_pyerrors.h"
+#include "clinic/_suggestions.c.h"
+
+/*[clinic input]
+module _suggestions
+[clinic start generated code]*/
+/*[clinic end generated code: output=da39a3ee5e6b4b0d input=e58d81fafad5637b]*/
+
+/*[clinic input]
+_suggestions._generate_suggestions
+ candidates: object
+ item: unicode
+ /
+Returns the candidate in candidates that's closest to item
+[clinic start generated code]*/
+
+static PyObject *
+_suggestions__generate_suggestions_impl(PyObject *module,
+ PyObject *candidates, PyObject *item)
+/*[clinic end generated code: output=79be7b653ae5e7ca input=ba2a8dddc654e33a]*/
+{
+ // Check if dir is a list
+ if (!PyList_Check(candidates)) {
+ PyErr_SetString(PyExc_TypeError, "candidates must be a list");
+ return NULL;
+ }
+
+ // Check if all elements in the list are Unicode
+ Py_ssize_t size = PyList_Size(candidates);
+ for (Py_ssize_t i = 0; i < size; ++i) {
+ PyObject *elem = PyList_GetItem(candidates, i);
+ if (!PyUnicode_Check(elem)) {
+ PyErr_SetString(PyExc_TypeError, "all elements in 'candidates' must be strings");
+ return NULL;
+ }
+ }
+
+ PyObject* result = _Py_CalculateSuggestions(candidates, item);
+ if (!result && !PyErr_Occurred()) {
+ Py_RETURN_NONE;
+ }
+ return result;
+}
+
+
+static PyMethodDef module_methods[] = {
+ _SUGGESTIONS__GENERATE_SUGGESTIONS_METHODDEF
+ {NULL, NULL, 0, NULL} // Sentinel
+};
+
+static struct PyModuleDef suggestions_module = {
+ PyModuleDef_HEAD_INIT,
+ "_suggestions",
+ NULL,
+ -1,
+ module_methods
+};
+
+PyMODINIT_FUNC PyInit__suggestions(void) {
+ return PyModule_Create(&suggestions_module);
+}
+
diff --git a/Modules/clinic/_suggestions.c.h b/Modules/clinic/_suggestions.c.h
new file mode 100644
index 0000000..51484b1
--- /dev/null
+++ b/Modules/clinic/_suggestions.c.h
@@ -0,0 +1,41 @@
+/*[clinic input]
+preserve
+[clinic start generated code]*/
+
+#include "pycore_modsupport.h" // _PyArg_CheckPositional()
+
+PyDoc_STRVAR(_suggestions__generate_suggestions__doc__,
+"_generate_suggestions($module, candidates, item, /)\n"
+"--\n"
+"\n"
+"Returns the candidate in candidates that\'s closest to item");
+
+#define _SUGGESTIONS__GENERATE_SUGGESTIONS_METHODDEF \
+ {"_generate_suggestions", _PyCFunction_CAST(_suggestions__generate_suggestions), METH_FASTCALL, _suggestions__generate_suggestions__doc__},
+
+static PyObject *
+_suggestions__generate_suggestions_impl(PyObject *module,
+ PyObject *candidates, PyObject *item);
+
+static PyObject *
+_suggestions__generate_suggestions(PyObject *module, PyObject *const *args, Py_ssize_t nargs)
+{
+ PyObject *return_value = NULL;
+ PyObject *candidates;
+ PyObject *item;
+
+ if (!_PyArg_CheckPositional("_generate_suggestions", nargs, 2, 2)) {
+ goto exit;
+ }
+ candidates = args[0];
+ if (!PyUnicode_Check(args[1])) {
+ _PyArg_BadArgument("_generate_suggestions", "argument 2", "str", args[1]);
+ goto exit;
+ }
+ item = args[1];
+ return_value = _suggestions__generate_suggestions_impl(module, candidates, item);
+
+exit:
+ return return_value;
+}
+/*[clinic end generated code: output=1d8e963cdae30b13 input=a9049054013a1b77]*/
diff --git a/PCbuild/pythoncore.vcxproj b/PCbuild/pythoncore.vcxproj
index 163adfd..c599b68 100644
--- a/PCbuild/pythoncore.vcxproj
+++ b/PCbuild/pythoncore.vcxproj
@@ -424,6 +424,7 @@
<ClInclude Include="..\Modules\_sre\sre_lib.h" />
<ClCompile Include="..\Modules\_stat.c" />
<ClCompile Include="..\Modules\_struct.c" />
+ <ClCompile Include="..\Modules\_suggestions.c" />
<ClCompile Include="..\Modules\_weakref.c" />
<ClCompile Include="..\Modules\arraymodule.c" />
<ClCompile Include="..\Modules\atexitmodule.c" />
diff --git a/PCbuild/pythoncore.vcxproj.filters b/PCbuild/pythoncore.vcxproj.filters
index a45a088..13582df 100644
--- a/PCbuild/pythoncore.vcxproj.filters
+++ b/PCbuild/pythoncore.vcxproj.filters
@@ -932,6 +932,9 @@
<ClCompile Include="..\Modules\_struct.c">
<Filter>Modules</Filter>
</ClCompile>
+ <ClCompile Include="..\Modules\_suggestions.c">
+ <Filter>Modules</Filter>
+ </ClCompile>
<ClCompile Include="..\Modules\_weakref.c">
<Filter>Modules</Filter>
</ClCompile>
diff --git a/Python/stdlib_module_names.h b/Python/stdlib_module_names.h
index 701bfc3..2445a5c 100644
--- a/Python/stdlib_module_names.h
+++ b/Python/stdlib_module_names.h
@@ -76,6 +76,7 @@ static const char* _Py_stdlib_module_names[] = {
"_string",
"_strptime",
"_struct",
+"_suggestions",
"_symtable",
"_sysconfig",
"_thread",
diff --git a/Python/suggestions.c b/Python/suggestions.c
index 1ad359b..69c3e4f 100644
--- a/Python/suggestions.c
+++ b/Python/suggestions.c
@@ -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)
{