gh-107944: Improve error message for function calls with bad keyword arguments (#107969)

This commit is contained in:
Pablo Galindo Salgado 2023-08-17 19:39:42 +01:00 committed by GitHub
parent 61c7249759
commit 75b3db8445
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
5 changed files with 106 additions and 11 deletions

View file

@ -26,6 +26,7 @@
#include "pycore_tuple.h" // _PyTuple_ITEMS()
#include "pycore_typeobject.h" // _PySuper_Lookup()
#include "pycore_uops.h" // _PyUOpExecutorObject
#include "pycore_pyerrors.h"
#include "pycore_dict.h"
#include "dictobject.h"
@ -1337,9 +1338,33 @@ initialize_locals(PyThreadState *tstate, PyFunctionObject *func,
goto kw_fail;
}
_PyErr_Format(tstate, PyExc_TypeError,
"%U() got an unexpected keyword argument '%S'",
func->func_qualname, keyword);
PyObject* suggestion_keyword = NULL;
if (total_args > co->co_posonlyargcount) {
PyObject* possible_keywords = PyList_New(total_args - co->co_posonlyargcount);
if (!possible_keywords) {
PyErr_Clear();
} else {
for (Py_ssize_t k = co->co_posonlyargcount; k < total_args; k++) {
PyList_SET_ITEM(possible_keywords, k - co->co_posonlyargcount, co_varnames[k]);
}
suggestion_keyword = _Py_CalculateSuggestions(possible_keywords, keyword);
Py_DECREF(possible_keywords);
}
}
if (suggestion_keyword) {
_PyErr_Format(tstate, PyExc_TypeError,
"%U() got an unexpected keyword argument '%S'. Did you mean '%S'?",
func->func_qualname, keyword, suggestion_keyword);
Py_DECREF(suggestion_keyword);
} else {
_PyErr_Format(tstate, PyExc_TypeError,
"%U() got an unexpected keyword argument '%S'",
func->func_qualname, keyword);
}
goto kw_fail;
}

View file

@ -126,8 +126,8 @@ levenshtein_distance(const char *a, size_t a_size,
return result;
}
static inline PyObject *
calculate_suggestions(PyObject *dir,
PyObject *
_Py_CalculateSuggestions(PyObject *dir,
PyObject *name)
{
assert(!PyErr_Occurred());
@ -195,7 +195,7 @@ get_suggestions_for_attribute_error(PyAttributeErrorObject *exc)
return NULL;
}
PyObject *suggestions = calculate_suggestions(dir, name);
PyObject *suggestions = _Py_CalculateSuggestions(dir, name);
Py_DECREF(dir);
return suggestions;
}
@ -259,7 +259,7 @@ get_suggestions_for_name_error(PyObject* name, PyFrameObject* frame)
}
}
PyObject *suggestions = calculate_suggestions(dir, name);
PyObject *suggestions = _Py_CalculateSuggestions(dir, name);
Py_DECREF(dir);
if (suggestions != NULL || PyErr_Occurred()) {
return suggestions;
@ -269,7 +269,7 @@ get_suggestions_for_name_error(PyObject* name, PyFrameObject* frame)
if (dir == NULL) {
return NULL;
}
suggestions = calculate_suggestions(dir, name);
suggestions = _Py_CalculateSuggestions(dir, name);
Py_DECREF(dir);
if (suggestions != NULL || PyErr_Occurred()) {
return suggestions;
@ -279,7 +279,7 @@ get_suggestions_for_name_error(PyObject* name, PyFrameObject* frame)
if (dir == NULL) {
return NULL;
}
suggestions = calculate_suggestions(dir, name);
suggestions = _Py_CalculateSuggestions(dir, name);
Py_DECREF(dir);
return suggestions;
@ -371,7 +371,7 @@ offer_suggestions_for_import_error(PyImportErrorObject *exc)
return NULL;
}
PyObject *suggestion = calculate_suggestions(dir, name);
PyObject *suggestion = _Py_CalculateSuggestions(dir, name);
Py_DECREF(dir);
if (!suggestion) {
return NULL;