Skip to content

Commit 835f14f

Browse files
authored
bpo-43017: Improve error message for unparenthesised tuples in comprehensions (GH24314)
1 parent 4090151 commit 835f14f

File tree

5 files changed

+343
-251
lines changed

5 files changed

+343
-251
lines changed

Grammar/python.gram

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -507,7 +507,7 @@ strings[expr_ty] (memo): a=STRING+ { _PyPegen_concatenate_strings(p, a) }
507507
list[expr_ty]:
508508
| '[' a=[star_named_expressions] ']' { _Py_List(a, Load, EXTRA) }
509509
listcomp[expr_ty]:
510-
| '[' a=named_expression ~ b=for_if_clauses ']' { _Py_ListComp(a, b, EXTRA) }
510+
| '[' a=named_expression b=for_if_clauses ']' { _Py_ListComp(a, b, EXTRA) }
511511
| invalid_comprehension
512512
tuple[expr_ty]:
513513
| '(' a=[y=star_named_expression ',' z=[star_named_expressions] { _PyPegen_seq_insert_in_front(p, y, z) } ] ')' {
@@ -516,11 +516,11 @@ group[expr_ty]:
516516
| '(' a=(yield_expr | named_expression) ')' { a }
517517
| invalid_group
518518
genexp[expr_ty]:
519-
| '(' a=named_expression ~ b=for_if_clauses ')' { _Py_GeneratorExp(a, b, EXTRA) }
519+
| '(' a=named_expression b=for_if_clauses ')' { _Py_GeneratorExp(a, b, EXTRA) }
520520
| invalid_comprehension
521521
set[expr_ty]: '{' a=star_named_expressions '}' { _Py_Set(a, EXTRA) }
522522
setcomp[expr_ty]:
523-
| '{' a=named_expression ~ b=for_if_clauses '}' { _Py_SetComp(a, b, EXTRA) }
523+
| '{' a=named_expression b=for_if_clauses '}' { _Py_SetComp(a, b, EXTRA) }
524524
| invalid_comprehension
525525
dict[expr_ty]:
526526
| '{' a=[double_starred_kvpairs] '}' {
@@ -692,6 +692,8 @@ invalid_primary:
692692
invalid_comprehension:
693693
| ('[' | '(' | '{') a=starred_expression for_if_clauses {
694694
RAISE_SYNTAX_ERROR_KNOWN_LOCATION(a, "iterable unpacking cannot be used in comprehension") }
695+
| ('[' | '{') a=star_named_expression ',' [star_named_expressions] {
696+
RAISE_SYNTAX_ERROR_KNOWN_LOCATION(a, "did you forget parentheses around the comprehension target?") }
695697
invalid_dict_comprehension:
696698
| '{' a='**' bitwise_or for_if_clauses '}' {
697699
RAISE_SYNTAX_ERROR_KNOWN_LOCATION(a, "dict unpacking cannot be used in dict comprehension") }

Lib/test/test_named_expressions.py

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -101,7 +101,8 @@ def test_named_expression_invalid_16(self):
101101
def test_named_expression_invalid_17(self):
102102
code = "[i := 0, j := 1 for i, j in [(1, 2), (3, 4)]]"
103103

104-
with self.assertRaisesRegex(SyntaxError, "invalid syntax"):
104+
with self.assertRaisesRegex(SyntaxError,
105+
"did you forget parentheses around the comprehension target?"):
105106
exec(code, {}, {})
106107

107108
def test_named_expression_invalid_in_class_body(self):

Lib/test/test_syntax.py

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -235,6 +235,21 @@
235235
Traceback (most recent call last):
236236
SyntaxError: invalid syntax
237237
238+
Comprehensions creating tuples without parentheses
239+
should produce a specialized error message:
240+
241+
>>> [x,y for x,y in range(100)]
242+
Traceback (most recent call last):
243+
SyntaxError: did you forget parentheses around the comprehension target?
244+
245+
>>> {x,y for x,y in range(100)}
246+
Traceback (most recent call last):
247+
SyntaxError: did you forget parentheses around the comprehension target?
248+
249+
>>> {x,y: None for x,y in range(100)}
250+
Traceback (most recent call last):
251+
SyntaxError: did you forget parentheses around the comprehension target?
252+
238253
From compiler_complex_args():
239254
240255
>>> def f(None=1):
Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
Improve error message in the parser when using un-parenthesised tuples in
2+
comprehensions. Patch by Pablo Galindo.

0 commit comments

Comments
 (0)