]> granicus.if.org Git - python/commitdiff
bpo-31229: Fixed wrong error messages when too many keyword arguments are received...
authorOren Milman <orenmn@gmail.com>
Wed, 23 Aug 2017 18:16:48 +0000 (21:16 +0300)
committerSerhiy Storchaka <storchaka@gmail.com>
Wed, 23 Aug 2017 18:16:48 +0000 (21:16 +0300)
Lib/test/test_call.py
Python/getargs.c

index b004b5803c30bf6e6f8e61bed497560610eaec85..3f9987c9e777f177db20c2c91751958110b5e3a8 100644 (file)
@@ -7,6 +7,7 @@ except ImportError:
     _testcapi = None
 import struct
 import collections
+import itertools
 
 # The test cases here cover several paths through the function calling
 # code.  They depend on the METH_XXX flag that is used to define a C
@@ -194,6 +195,26 @@ class CFunctionCallsErrorMessages(unittest.TestCase):
         msg = r"^classmethod\(\) takes no keyword arguments$"
         self.assertRaisesRegex(TypeError, msg, classmethod, func=id)
 
+    def test_varargs14_kw(self):
+        msg = r"^product\(\) takes at most 1 keyword argument \(2 given\)$"
+        self.assertRaisesRegex(TypeError, msg,
+                               itertools.product, 0, repeat=1, foo=2)
+
+    def test_varargs15_kw(self):
+        msg = r"^ImportError\(\) takes at most 2 keyword arguments \(3 given\)$"
+        self.assertRaisesRegex(TypeError, msg,
+                               ImportError, 0, name=1, path=2, foo=3)
+
+    def test_varargs16_kw(self):
+        msg = r"^min\(\) takes at most 2 keyword arguments \(3 given\)$"
+        self.assertRaisesRegex(TypeError, msg,
+                               min, 0, default=1, key=2, foo=3)
+
+    def test_varargs17_kw(self):
+        msg = r"^print\(\) takes at most 4 keyword arguments \(5 given\)$"
+        self.assertRaisesRegex(TypeError, msg,
+                               print, 0, sep=1, end=2, file=3, flush=4, foo=5)
+
     def test_oldargs0_1(self):
         msg = r"keys\(\) takes no arguments \(1 given\)"
         self.assertRaisesRegex(TypeError, msg, {}.keys, 0)
index 4645b0f20061f814a97f192324aba21f6fc6e6e1..4b969d924a96da6071feb2c5d1cbbd4c938f08ab 100644 (file)
@@ -1654,11 +1654,14 @@ vgetargskeywords(PyObject *args, PyObject *kwargs, const char *format,
     nargs = PyTuple_GET_SIZE(args);
     nkwargs = (kwargs == NULL) ? 0 : PyDict_GET_SIZE(kwargs);
     if (nargs + nkwargs > len) {
+        /* Adding "keyword" (when nargs == 0) prevents producing wrong error
+           messages in some special cases (see bpo-31229). */
         PyErr_Format(PyExc_TypeError,
-                     "%.200s%s takes at most %d argument%s (%zd given)",
+                     "%.200s%s takes at most %d %sargument%s (%zd given)",
                      (fname == NULL) ? "function" : fname,
                      (fname == NULL) ? "" : "()",
                      len,
+                     (nargs == 0) ? "keyword " : "",
                      (len == 1) ? "" : "s",
                      nargs + nkwargs);
         return cleanreturn(0, &freelist);
@@ -2077,11 +2080,14 @@ vgetargskeywordsfast_impl(PyObject **args, Py_ssize_t nargs,
         nkwargs = 0;
     }
     if (nargs + nkwargs > len) {
+        /* Adding "keyword" (when nargs == 0) prevents producing wrong error
+           messages in some special cases (see bpo-31229). */
         PyErr_Format(PyExc_TypeError,
-                     "%.200s%s takes at most %d argument%s (%zd given)",
+                     "%.200s%s takes at most %d %sargument%s (%zd given)",
                      (parser->fname == NULL) ? "function" : parser->fname,
                      (parser->fname == NULL) ? "" : "()",
                      len,
+                     (nargs == 0) ? "keyword " : "",
                      (len == 1) ? "" : "s",
                      nargs + nkwargs);
         return cleanreturn(0, &freelist);