bpo-40147: Move the check for duplicate keywords to the compiler (GH-19289)

This commit is contained in:
Pablo Galindo 2020-04-03 20:37:13 +01:00 committed by GitHub
parent bd6a4c3d72
commit 254ec78341
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
4 changed files with 32 additions and 12 deletions

View File

@ -128,7 +128,7 @@ Check for duplicate keywords.
... ...
Traceback (most recent call last): Traceback (most recent call last):
[...] [...]
SyntaxError: keyword argument repeated SyntaxError: keyword argument repeated: metaclass
>>> >>>
Another way. Another way.

View File

@ -588,7 +588,7 @@ Make sure that the old "raise X, Y[, Z]" form is gone:
>>> f(a=23, a=234) >>> f(a=23, a=234)
Traceback (most recent call last): Traceback (most recent call last):
... ...
SyntaxError: keyword argument repeated SyntaxError: keyword argument repeated: a
>>> {1, 2, 3} = 42 >>> {1, 2, 3} = 42
Traceback (most recent call last): Traceback (most recent call last):

View File

@ -3048,8 +3048,7 @@ ast_for_call(struct compiling *c, const node *n, expr_ty func,
else { else {
/* a keyword argument */ /* a keyword argument */
keyword_ty kw; keyword_ty kw;
identifier key, tmp; identifier key;
int k;
// To remain LL(1), the grammar accepts any test (basically, any // To remain LL(1), the grammar accepts any test (basically, any
// expression) in the keyword slot of a call site. So, we need // 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)) { if (forbidden_name(c, key, chch, 1)) {
return NULL; 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)); e = ast_for_expr(c, CHILD(ch, 2));
if (!e) if (!e)
return NULL; return NULL;

View File

@ -4049,6 +4049,31 @@ maybe_optimize_method_call(struct compiler *c, expr_ty e)
return 1; 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 static int
compiler_call(struct compiler *c, expr_ty e) 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; Py_ssize_t i, nseen, nelts, nkwelts;
if (validate_keywords(c, keywords) == -1) {
return 0;
}
nelts = asdl_seq_LEN(args); nelts = asdl_seq_LEN(args);
nkwelts = asdl_seq_LEN(keywords); nkwelts = asdl_seq_LEN(keywords);