Skip to content

Commit bf9075a

Browse files
orenmnserhiy-storchaka
authored andcommitted
bpo-31229: Fixed wrong error messages when too many keyword arguments are received. (#3180)
1 parent 772d809 commit bf9075a

File tree

2 files changed

+29
-2
lines changed

2 files changed

+29
-2
lines changed

Lib/test/test_call.py

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@
77
_testcapi = None
88
import struct
99
import collections
10+
import itertools
1011

1112
# The test cases here cover several paths through the function calling
1213
# code. They depend on the METH_XXX flag that is used to define a C
@@ -194,6 +195,26 @@ def test_varargs13_kw(self):
194195
msg = r"^classmethod\(\) takes no keyword arguments$"
195196
self.assertRaisesRegex(TypeError, msg, classmethod, func=id)
196197

198+
def test_varargs14_kw(self):
199+
msg = r"^product\(\) takes at most 1 keyword argument \(2 given\)$"
200+
self.assertRaisesRegex(TypeError, msg,
201+
itertools.product, 0, repeat=1, foo=2)
202+
203+
def test_varargs15_kw(self):
204+
msg = r"^ImportError\(\) takes at most 2 keyword arguments \(3 given\)$"
205+
self.assertRaisesRegex(TypeError, msg,
206+
ImportError, 0, name=1, path=2, foo=3)
207+
208+
def test_varargs16_kw(self):
209+
msg = r"^min\(\) takes at most 2 keyword arguments \(3 given\)$"
210+
self.assertRaisesRegex(TypeError, msg,
211+
min, 0, default=1, key=2, foo=3)
212+
213+
def test_varargs17_kw(self):
214+
msg = r"^print\(\) takes at most 4 keyword arguments \(5 given\)$"
215+
self.assertRaisesRegex(TypeError, msg,
216+
print, 0, sep=1, end=2, file=3, flush=4, foo=5)
217+
197218
def test_oldargs0_1(self):
198219
msg = r"keys\(\) takes no arguments \(1 given\)"
199220
self.assertRaisesRegex(TypeError, msg, {}.keys, 0)

Python/getargs.c

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1654,11 +1654,14 @@ vgetargskeywords(PyObject *args, PyObject *kwargs, const char *format,
16541654
nargs = PyTuple_GET_SIZE(args);
16551655
nkwargs = (kwargs == NULL) ? 0 : PyDict_GET_SIZE(kwargs);
16561656
if (nargs + nkwargs > len) {
1657+
/* Adding "keyword" (when nargs == 0) prevents producing wrong error
1658+
messages in some special cases (see bpo-31229). */
16571659
PyErr_Format(PyExc_TypeError,
1658-
"%.200s%s takes at most %d argument%s (%zd given)",
1660+
"%.200s%s takes at most %d %sargument%s (%zd given)",
16591661
(fname == NULL) ? "function" : fname,
16601662
(fname == NULL) ? "" : "()",
16611663
len,
1664+
(nargs == 0) ? "keyword " : "",
16621665
(len == 1) ? "" : "s",
16631666
nargs + nkwargs);
16641667
return cleanreturn(0, &freelist);
@@ -2077,11 +2080,14 @@ vgetargskeywordsfast_impl(PyObject **args, Py_ssize_t nargs,
20772080
nkwargs = 0;
20782081
}
20792082
if (nargs + nkwargs > len) {
2083+
/* Adding "keyword" (when nargs == 0) prevents producing wrong error
2084+
messages in some special cases (see bpo-31229). */
20802085
PyErr_Format(PyExc_TypeError,
2081-
"%.200s%s takes at most %d argument%s (%zd given)",
2086+
"%.200s%s takes at most %d %sargument%s (%zd given)",
20822087
(parser->fname == NULL) ? "function" : parser->fname,
20832088
(parser->fname == NULL) ? "" : "()",
20842089
len,
2090+
(nargs == 0) ? "keyword " : "",
20852091
(len == 1) ? "" : "s",
20862092
nargs + nkwargs);
20872093
return cleanreturn(0, &freelist);

0 commit comments

Comments
 (0)