]> git.ipfire.org Git - thirdparty/Python/cpython.git/commitdiff
gh-110721: Remove unused code from suggestions.c after moving PyErr_Display to use...
authorPablo Galindo Salgado <Pablogsal@gmail.com>
Mon, 8 Jan 2024 15:10:45 +0000 (15:10 +0000)
committerGitHub <noreply@github.com>
Mon, 8 Jan 2024 15:10:45 +0000 (15:10 +0000)
12 files changed:
Include/internal/pycore_global_objects_fini_generated.h
Include/internal/pycore_global_strings.h
Include/internal/pycore_runtime_init_generated.h
Include/internal/pycore_unicodeobject_generated.h
Lib/traceback.py
Modules/Setup.bootstrap.in
Modules/_suggestions.c [new file with mode: 0644]
Modules/clinic/_suggestions.c.h [new file with mode: 0644]
PCbuild/pythoncore.vcxproj
PCbuild/pythoncore.vcxproj.filters
Python/stdlib_module_names.h
Python/suggestions.c

index 89ec8cbbbcd649022feefe579e04c86021f7cae3..8dbdc399d77f57ca6a44520a9738a93d481a9974 100644 (file)
@@ -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));
index 62c3ee3ae2a0bd8f53239be7740ce5776a994601..1fa2d1d49cbb4983b5f2ea0d8986066f8867123d 100644 (file)
@@ -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)
index 1defa39f816e78297ded144d0be88b026b636868..8fd922af2654e00eb8c07c33c14040e731e6f0f4 100644 (file)
@@ -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), \
index be9baa3eebecfcf0c8b206fac1af5908ba6280f0..0b5fb7363b4f4edd25d80482af88f9679abdf298 100644 (file)
@@ -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);
index 1cf008c7e9da9796b1388ef67840861ea1cdb327..30b42a4f693d95a6e66d185b6370fad5afe23cb7 100644 (file)
@@ -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:
index cd12c1bd0df8f9050fc814b8857cf1bdebca8a9e..aa4e60e272653b6f14e52263ec10f9889e3f0b7c 100644 (file)
@@ -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 (file)
index 0000000..30b524d
--- /dev/null
@@ -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 (file)
index 0000000..51484b1
--- /dev/null
@@ -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]*/
index 163adfdc51c6a8ff8330fe96869398a583e5a383..c599b68e0d8e66d7a49ddfeacdb72459749dca91 100644 (file)
     <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" />
index a45a0881f7113d0461f1731cdddc0c557022b42f..13582dff3f40c46cece9828c861ca750e767c0ab 100644 (file)
     <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>
index 701bfc35cc81822dc573bb76b8890bbff2c7c45e..2445a5c838a7d709d744c929c31e4da060523025 100644 (file)
@@ -76,6 +76,7 @@ static const char* _Py_stdlib_module_names[] = {
 "_string",
 "_strptime",
 "_struct",
+"_suggestions",
 "_symtable",
 "_sysconfig",
 "_thread",
index 1ad359b18923f31e912dc59098af61cbf123e22b..69c3e4fe4d2146127d022de5f618cf35b5f9d5c7 100644 (file)
@@ -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)
 {