mirror of
https://github.com/astral-sh/ruff.git
synced 2025-07-25 05:53:51 +00:00
![]() ## Summary This PR fixes a bug to raise a syntax error when an unparenthesized generator expression is used as an argument to a call when there are more than one argument. For reference, the grammar is: ``` primary: | ... | primary genexp | primary '(' [arguments] ')' | ... genexp: | '(' ( assignment_expression | expression !':=') for_if_clauses ')' ``` The `genexp` requires the parenthesis as mentioned in the grammar. So, the grammar for a call expression is either a name followed by a generator expression or a name followed by a list of argument. In the former case, the parenthesis are excluded because the generator expression provides them while in the later case, the parenthesis are explicitly provided for a list of arguments which means that the generator expression requires it's own parenthesis. This was discovered in https://github.com/astral-sh/ruff/issues/12420. ## Test Plan Add test cases for valid and invalid syntax. Make sure that the parser from CPython also raises this at the parsing step: ```console $ python3.13 -m ast parser/_.py File "parser/_.py", line 1 total(1, 2, x for x in range(5), 6) ^^^^^^^^^^^^^^^^^^^ SyntaxError: Generator expression must be parenthesized $ python3.13 -m ast parser/_.py File "parser/_.py", line 1 sum(x for x in range(10), 10) ^^^^^^^^^^^^^^^^^^^^ SyntaxError: Generator expression must be parenthesized ``` |
||
---|---|---|
.. | ||
ambiguous_lpar_with_items_binary_expr.py | ||
ambiguous_lpar_with_items_if_expr.py | ||
ann_assign_stmt_simple_target.py | ||
args_unparenthesized_generator.py | ||
assign_targets_terminator.py | ||
async_for_statement.py | ||
async_function_definition.py | ||
async_with_statement.py | ||
class_def_arguments.py | ||
comma_separated_regular_list_terminator.py | ||
decorator_async_function.py | ||
del_targets_terminator.py | ||
dotted_name_normalized_spaces.py | ||
except_stmt_as_name_soft_keyword.py | ||
for_in_target_valid_expr.py | ||
from_import_no_space.py | ||
from_import_soft_keyword_module_name.py | ||
from_import_stmt_terminator.py | ||
fstring_format_spec_terminator.py | ||
function_def_parameter_range.py | ||
function_def_parenthesized_return_types.py | ||
function_def_valid_return_expr.py | ||
global_stmt.py | ||
import_as_name_soft_keyword.py | ||
import_stmt_terminator.py | ||
lambda_with_no_parameters.py | ||
lambda_with_valid_body.py | ||
match_as_pattern.py | ||
match_as_pattern_soft_keyword.py | ||
match_attr_pattern_soft_keyword.py | ||
match_classify_as_identifier_1.py | ||
match_classify_as_identifier_2.py | ||
match_classify_as_keyword_1.py | ||
match_classify_as_keyword_2.py | ||
match_classify_as_keyword_or_identifier.py | ||
match_sequence_pattern_parentheses_terminator.py | ||
match_sequence_pattern_terminator.py | ||
match_stmt_subject_expr.py | ||
match_stmt_valid_guard_expr.py | ||
nonlocal_stmt.py | ||
param_with_annotation.py | ||
param_with_default.py | ||
param_with_star_annotation.py | ||
params_non_default_after_star.py | ||
params_seen_keyword_only_param_after_star.py | ||
simple_stmts_in_block.py | ||
simple_stmts_with_semicolons.py | ||
type_param_param_spec.py | ||
type_param_type_var.py | ||
type_param_type_var_tuple.py |