From 30ed93bfec5dfa7ee05982e2df8fd810f3f49305 Mon Sep 17 00:00:00 2001 From: Pablo Galindo Date: Tue, 13 Apr 2021 17:51:21 +0100 Subject: [PATCH] bpo-43797: Handle correctly invalid assignments inside function calls and generators (GH-25390) --- Grammar/python.gram | 2 +- Lib/test/test_genexps.py | 2 +- Lib/test/test_syntax.py | 14 +++++++++++++- Parser/parser.c | 12 ++++++------ 4 files changed, 21 insertions(+), 9 deletions(-) diff --git a/Grammar/python.gram b/Grammar/python.gram index 8524a1206b0..180d952b57a 100644 --- a/Grammar/python.gram +++ b/Grammar/python.gram @@ -638,7 +638,7 @@ group[expr_ty]: | '(' a=(yield_expr | named_expression) ')' { a } | invalid_group genexp[expr_ty]: - | '(' a=named_expression b=for_if_clauses ')' { _PyAST_GeneratorExp(a, b, EXTRA) } + | '(' a=direct_named_expression b=for_if_clauses ')' { _PyAST_GeneratorExp(a, b, EXTRA) } | invalid_comprehension set[expr_ty]: '{' a=star_named_expressions '}' { _PyAST_Set(a, EXTRA) } setcomp[expr_ty]: diff --git a/Lib/test/test_genexps.py b/Lib/test/test_genexps.py index 70fe2bba3a6..5c1a209b0e9 100644 --- a/Lib/test/test_genexps.py +++ b/Lib/test/test_genexps.py @@ -103,7 +103,7 @@ Verify that parenthesis are required when used as a keyword argument value >>> dict(a = i for i in range(10)) Traceback (most recent call last): ... - SyntaxError: invalid syntax. Maybe you meant '==' or ':=' instead of '='? + SyntaxError: invalid syntax Verify that parenthesis are required when used as a keyword argument value diff --git a/Lib/test/test_syntax.py b/Lib/test/test_syntax.py index 0e6942f6a6f..bd6a4d339e7 100644 --- a/Lib/test/test_syntax.py +++ b/Lib/test/test_syntax.py @@ -868,6 +868,18 @@ Ensure that early = are not matched by the parser as invalid comparisons Traceback (most recent call last): SyntaxError: invalid syntax + >>> dict(x=34); x $ y + Traceback (most recent call last): + SyntaxError: invalid syntax + + >>> dict(x=34, (x for x in range 10), 1); x $ y + Traceback (most recent call last): + SyntaxError: invalid syntax + + >>> dict(x=34, x=1, y=2); x $ y + Traceback (most recent call last): + SyntaxError: invalid syntax + Make sure that the old "raise X, Y[, Z]" form is gone: >>> raise X, Y Traceback (most recent call last): @@ -1013,7 +1025,7 @@ class SyntaxTestCase(unittest.TestCase): def test_expression_with_assignment(self): self._check_error( "print(end1 + end2 = ' ')", - "cannot assign to expression here. Maybe you meant '==' instead of '='?", + 'expression cannot contain assignment, perhaps you meant "=="?', offset=19 ) diff --git a/Parser/parser.c b/Parser/parser.c index 38bab96ae39..d158b2952ba 100644 --- a/Parser/parser.c +++ b/Parser/parser.c @@ -14015,7 +14015,7 @@ group_rule(Parser *p) return _res; } -// genexp: '(' named_expression for_if_clauses ')' | invalid_comprehension +// genexp: '(' direct_named_expression for_if_clauses ')' | invalid_comprehension static expr_ty genexp_rule(Parser *p) { @@ -14035,12 +14035,12 @@ genexp_rule(Parser *p) UNUSED(_start_lineno); // Only used by EXTRA macro int _start_col_offset = p->tokens[_mark]->col_offset; UNUSED(_start_col_offset); // Only used by EXTRA macro - { // '(' named_expression for_if_clauses ')' + { // '(' direct_named_expression for_if_clauses ')' if (p->error_indicator) { D(p->level--); return NULL; } - D(fprintf(stderr, "%*c> genexp[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'(' named_expression for_if_clauses ')'")); + D(fprintf(stderr, "%*c> genexp[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'(' direct_named_expression for_if_clauses ')'")); Token * _literal; Token * _literal_1; expr_ty a; @@ -14048,14 +14048,14 @@ genexp_rule(Parser *p) if ( (_literal = _PyPegen_expect_token(p, 7)) // token='(' && - (a = named_expression_rule(p)) // named_expression + (a = direct_named_expression_rule(p)) // direct_named_expression && (b = for_if_clauses_rule(p)) // for_if_clauses && (_literal_1 = _PyPegen_expect_token(p, 8)) // token=')' ) { - D(fprintf(stderr, "%*c+ genexp[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'(' named_expression for_if_clauses ')'")); + D(fprintf(stderr, "%*c+ genexp[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'(' direct_named_expression for_if_clauses ')'")); Token *_token = _PyPegen_get_last_nonnwhitespace_token(p); if (_token == NULL) { D(p->level--); @@ -14075,7 +14075,7 @@ genexp_rule(Parser *p) } p->mark = _mark; D(fprintf(stderr, "%*c%s genexp[%d-%d]: %s failed!\n", p->level, ' ', - p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "'(' named_expression for_if_clauses ')'")); + p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "'(' direct_named_expression for_if_clauses ')'")); } if (p->call_invalid_rules) { // invalid_comprehension if (p->error_indicator) {