From fa239f76ea052cd4dec14ebe4ab83c499f50f23b Mon Sep 17 00:00:00 2001 From: InSync Date: Fri, 17 Jan 2025 08:13:50 +0700 Subject: [PATCH] [`pyupgrade`] Avoid syntax error when the iterable is an non-parenthesized tuple (`UP028`) (#15543) ## Summary Resolves #15540. ## Test Plan `cargo nextest run` and `cargo insta test`. --- .../test/fixtures/pyupgrade/UP028_1.py | 6 ++++++ .../rules/pyupgrade/rules/yield_in_for_loop.rs | 8 +++++++- ...er__rules__pyupgrade__tests__UP028_1.py.snap | 17 ++++++++++++++++- 3 files changed, 29 insertions(+), 2 deletions(-) diff --git a/crates/ruff_linter/resources/test/fixtures/pyupgrade/UP028_1.py b/crates/ruff_linter/resources/test/fixtures/pyupgrade/UP028_1.py index 66675da186..2f602211f9 100644 --- a/crates/ruff_linter/resources/test/fixtures/pyupgrade/UP028_1.py +++ b/crates/ruff_linter/resources/test/fixtures/pyupgrade/UP028_1.py @@ -121,3 +121,9 @@ def f(): def f(): for x, y in z: yield x, y, x + y + + +# https://github.com/astral-sh/ruff/issues/15540 +def f(): + for a in 1,: + yield a diff --git a/crates/ruff_linter/src/rules/pyupgrade/rules/yield_in_for_loop.rs b/crates/ruff_linter/src/rules/pyupgrade/rules/yield_in_for_loop.rs index 02c96754be..922122d481 100644 --- a/crates/ruff_linter/src/rules/pyupgrade/rules/yield_in_for_loop.rs +++ b/crates/ruff_linter/src/rules/pyupgrade/rules/yield_in_for_loop.rs @@ -114,6 +114,7 @@ pub(crate) fn yield_in_for_loop(checker: &mut Checker, stmt_for: &ast::StmtFor) } let mut diagnostic = Diagnostic::new(YieldInForLoop, stmt_for.range()); + let contents = checker.locator().slice( parenthesized_range( iter.as_ref().into(), @@ -123,7 +124,12 @@ pub(crate) fn yield_in_for_loop(checker: &mut Checker, stmt_for: &ast::StmtFor) ) .unwrap_or(iter.range()), ); - let contents = format!("yield from {contents}"); + let contents = if iter.as_tuple_expr().is_some_and(|it| !it.parenthesized) { + format!("yield from ({contents})") + } else { + format!("yield from {contents}") + }; + diagnostic.set_fix(Fix::unsafe_edit(Edit::range_replacement( contents, stmt_for.range(), diff --git a/crates/ruff_linter/src/rules/pyupgrade/snapshots/ruff_linter__rules__pyupgrade__tests__UP028_1.py.snap b/crates/ruff_linter/src/rules/pyupgrade/snapshots/ruff_linter__rules__pyupgrade__tests__UP028_1.py.snap index c996a51d38..c08796dfe7 100644 --- a/crates/ruff_linter/src/rules/pyupgrade/snapshots/ruff_linter__rules__pyupgrade__tests__UP028_1.py.snap +++ b/crates/ruff_linter/src/rules/pyupgrade/snapshots/ruff_linter__rules__pyupgrade__tests__UP028_1.py.snap @@ -1,5 +1,20 @@ --- source: crates/ruff_linter/src/rules/pyupgrade/mod.rs -snapshot_kind: text --- +UP028_1.py:128:5: UP028 [*] Replace `yield` over `for` loop with `yield from` + | +126 | # https://github.com/astral-sh/ruff/issues/15540 +127 | def f(): +128 | / for a in 1,: +129 | | yield a + | |_______________^ UP028 + | + = help: Replace with `yield from` +ℹ Unsafe fix +125 125 | +126 126 | # https://github.com/astral-sh/ruff/issues/15540 +127 127 | def f(): +128 |- for a in 1,: +129 |- yield a + 128 |+ yield from (1,)