]> git.ipfire.org Git - thirdparty/Python/cpython.git/commitdiff
bpo-40147: Move the check for duplicate keywords to the compiler (GH-19289)
authorPablo Galindo <Pablogsal@gmail.com>
Fri, 3 Apr 2020 19:37:13 +0000 (20:37 +0100)
committerGitHub <noreply@github.com>
Fri, 3 Apr 2020 19:37:13 +0000 (20:37 +0100)
Lib/test/test_metaclass.py
Lib/test/test_syntax.py
Python/ast.c
Python/compile.c

index e6fe20a107c239a64fc1e8bedfda2b159134f56f..6edd899b0d21328655263fb0450812ef6bc13560 100644 (file)
@@ -128,7 +128,7 @@ Check for duplicate keywords.
     ...
     Traceback (most recent call last):
     [...]
-    SyntaxError: keyword argument repeated
+    SyntaxError: keyword argument repeated: metaclass
     >>>
 
 Another way.
index 128c4da14384143f8d133705e6b2807ab7864a89..a7e7e2c9e6f02709a6acef1bcc22de7f68d71962 100644 (file)
@@ -588,7 +588,7 @@ Make sure that the old "raise X, Y[, Z]" form is gone:
 >>> f(a=23, a=234)
 Traceback (most recent call last):
    ...
-SyntaxError: keyword argument repeated
+SyntaxError: keyword argument repeated: a
 
 >>> {1, 2, 3} = 42
 Traceback (most recent call last):
index 550ee03b1ac384d7f521601731c0c62b48583c6f..6ba62fb479f993f13c12993bc43b6db3144dde9f 100644 (file)
@@ -3048,8 +3048,7 @@ ast_for_call(struct compiling *c, const node *n, expr_ty func,
             else {
                 /* a keyword argument */
                 keyword_ty kw;
-                identifier key, tmp;
-                int k;
+                identifier key;
 
                 // To remain LL(1), the grammar accepts any test (basically, any
                 // expression) in the keyword slot of a call site.  So, we need
@@ -3093,14 +3092,6 @@ ast_for_call(struct compiling *c, const node *n, expr_ty func,
                 if (forbidden_name(c, key, chch, 1)) {
                     return NULL;
                 }
-                for (k = 0; k < nkeywords; k++) {
-                    tmp = ((keyword_ty)asdl_seq_GET(keywords, k))->arg;
-                    if (tmp && !PyUnicode_Compare(tmp, key)) {
-                        ast_error(c, chch,
-                                  "keyword argument repeated");
-                        return NULL;
-                    }
-                }
                 e = ast_for_expr(c, CHILD(ch, 2));
                 if (!e)
                     return NULL;
index 01700e0e78cc9c78493bf13081f1246904342315..b1c1982fd2c4aeccb93aaadd309b4a63840a6272 100644 (file)
@@ -4049,6 +4049,31 @@ maybe_optimize_method_call(struct compiler *c, expr_ty e)
     return 1;
 }
 
+static int
+validate_keywords(struct compiler *c, asdl_seq* keywords) {
+    int nkeywords = asdl_seq_LEN(keywords);
+    for (int i = 0; i < nkeywords; i++) {
+        keyword_ty key = ((keyword_ty)asdl_seq_GET(keywords, i));
+        if (key->arg == NULL) {
+            continue;
+        }
+        for (int j = i+1; j < nkeywords; j++) {
+            keyword_ty other = ((keyword_ty)asdl_seq_GET(keywords, j));
+            if (other->arg && !PyUnicode_Compare(key->arg, other->arg)) {
+                PyObject *msg = PyUnicode_FromFormat("keyword argument repeated: %U", key->arg);
+                if (msg == NULL) {
+                    return -1;
+                }
+                c->u->u_col_offset = other->col_offset;
+                compiler_error(c, PyUnicode_AsUTF8(msg));
+                Py_DECREF(msg);
+                return -1;
+            }
+        }
+    }
+    return 0;
+}
+
 static int
 compiler_call(struct compiler *c, expr_ty e)
 {
@@ -4165,6 +4190,10 @@ compiler_call_helper(struct compiler *c,
 {
     Py_ssize_t i, nseen, nelts, nkwelts;
 
+    if (validate_keywords(c, keywords) == -1) {
+        return 0;
+    }
+
     nelts = asdl_seq_LEN(args);
     nkwelts = asdl_seq_LEN(keywords);