summaryrefslogtreecommitdiffstats
path: root/Python/getargs.c
diff options
context:
space:
mode:
authorShantanu <12621235+hauntsaninja@users.noreply.github.com>2024-02-08 09:04:41 (GMT)
committerGitHub <noreply@github.com>2024-02-08 09:04:41 (GMT)
commit17689e3c41d9f61bcd1928b24d3c50c37ceaf3f2 (patch)
tree7b7bd7681ee4810ba68527324a96093e2a21fb24 /Python/getargs.c
parent9e90313320a2af2d9ff7049ed3842344ed236630 (diff)
downloadcpython-17689e3c41d9f61bcd1928b24d3c50c37ceaf3f2.zip
cpython-17689e3c41d9f61bcd1928b24d3c50c37ceaf3f2.tar.gz
cpython-17689e3c41d9f61bcd1928b24d3c50c37ceaf3f2.tar.bz2
gh-107944: Improve error message for getargs with bad keyword arguments (#114792)
Diffstat (limited to 'Python/getargs.c')
-rw-r--r--Python/getargs.c70
1 files changed, 58 insertions, 12 deletions
diff --git a/Python/getargs.c b/Python/getargs.c
index 0c4ce28..08e97ee 100644
--- a/Python/getargs.c
+++ b/Python/getargs.c
@@ -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);
}
}