gh-107944: Improve error message for getargs with bad keyword arguments (#114792)

This commit is contained in:
Shantanu 2024-02-08 01:04:41 -08:00 committed by GitHub
parent 9e90313320
commit 17689e3c41
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
6 changed files with 113 additions and 29 deletions

View file

@ -8,6 +8,7 @@
#include "pycore_modsupport.h" // export _PyArg_NoKeywords()
#include "pycore_pylifecycle.h" // _PyArg_Fini
#include "pycore_tuple.h" // _PyTuple_ITEMS()
#include "pycore_pyerrors.h" // _Py_CalculateSuggestions()
/* Export Stable ABIs (abi only) */
PyAPI_FUNC(int) _PyArg_Parse_SizeT(PyObject *, const char *, ...);
@ -1424,12 +1425,31 @@ error_unexpected_keyword_arg(PyObject *kwargs, PyObject *kwnames, PyObject *kwtu
int match = PySequence_Contains(kwtuple, keyword);
if (match <= 0) {
if (!match) {
PyErr_Format(PyExc_TypeError,
"'%S' is an invalid keyword "
"argument for %.200s%s",
keyword,
(fname == NULL) ? "this function" : fname,
(fname == NULL) ? "" : "()");
PyObject *kwlist = PySequence_List(kwtuple);
if (!kwlist) {
return;
}
PyObject *suggestion_keyword = _Py_CalculateSuggestions(kwlist, keyword);
Py_DECREF(kwlist);
if (suggestion_keyword) {
PyErr_Format(PyExc_TypeError,
"%.200s%s got an unexpected keyword argument '%S'."
" Did you mean '%S'?",
(fname == NULL) ? "this function" : fname,
(fname == NULL) ? "" : "()",
keyword,
suggestion_keyword);
Py_DECREF(suggestion_keyword);
}
else {
PyErr_Format(PyExc_TypeError,
"%.200s%s got an unexpected keyword argument '%S'",
(fname == NULL) ? "this function" : fname,
(fname == NULL) ? "" : "()",
keyword);
}
}
return;
}
@ -1457,6 +1477,9 @@ PyArg_ValidateKeywordArguments(PyObject *kwargs)
return 1;
}
static PyObject *
new_kwtuple(const char * const *keywords, int total, int pos);
#define IS_END_OF_FORMAT(c) (c == '\0' || c == ';' || c == ':')
static int
@ -1722,12 +1745,35 @@ vgetargskeywords(PyObject *args, PyObject *kwargs, const char *format,
}
}
if (!match) {
PyErr_Format(PyExc_TypeError,
"'%U' is an invalid keyword "
"argument for %.200s%s",
key,
(fname == NULL) ? "this function" : fname,
(fname == NULL) ? "" : "()");
PyObject *_pykwtuple = new_kwtuple(kwlist, len, pos);
if (!_pykwtuple) {
return cleanreturn(0, &freelist);
}
PyObject *pykwlist = PySequence_List(_pykwtuple);
Py_DECREF(_pykwtuple);
if (!pykwlist) {
return cleanreturn(0, &freelist);
}
PyObject *suggestion_keyword = _Py_CalculateSuggestions(pykwlist, key);
Py_DECREF(pykwlist);
if (suggestion_keyword) {
PyErr_Format(PyExc_TypeError,
"%.200s%s got an unexpected keyword argument '%S'."
" Did you mean '%S'?",
(fname == NULL) ? "this function" : fname,
(fname == NULL) ? "" : "()",
key,
suggestion_keyword);
Py_DECREF(suggestion_keyword);
}
else {
PyErr_Format(PyExc_TypeError,
"%.200s%s got an unexpected keyword argument '%S'",
(fname == NULL) ? "this function" : fname,
(fname == NULL) ? "" : "()",
key);
}
return cleanreturn(0, &freelist);
}
}