diff --git a/crates/ruff_linter/resources/test/fixtures/pyupgrade/UP027.py b/crates/ruff_linter/resources/test/fixtures/pyupgrade/UP027.py deleted file mode 100644 index 5a40da3bb9f462..00000000000000 --- a/crates/ruff_linter/resources/test/fixtures/pyupgrade/UP027.py +++ /dev/null @@ -1,18 +0,0 @@ -# Should change -foo, bar, baz = [fn(x) for x in items] - -foo, bar, baz =[fn(x) for x in items] - -foo, bar, baz = [fn(x) for x in items] - -foo, bar, baz = [[i for i in fn(x)] for x in items] - -foo, bar, baz = [ - fn(x) - for x in items -] - -# Should not change -foo = [fn(x) for x in items] - -x, = [await foo for foo in bar] diff --git a/crates/ruff_linter/src/checkers/ast/analyze/statement.rs b/crates/ruff_linter/src/checkers/ast/analyze/statement.rs index 9bdc28a1c5863d..ba923acb1985ac 100644 --- a/crates/ruff_linter/src/checkers/ast/analyze/statement.rs +++ b/crates/ruff_linter/src/checkers/ast/analyze/statement.rs @@ -1560,9 +1560,6 @@ pub(crate) fn statement(stmt: &Stmt, checker: &mut Checker) { checker, stmt, targets, value, ); } - if checker.enabled(Rule::UnpackedListComprehension) { - pyupgrade::rules::unpacked_list_comprehension(checker, targets, value); - } if checker.enabled(Rule::PandasDfVariableName) { if let Some(diagnostic) = pandas_vet::rules::assignment_to_df(targets) { checker.diagnostics.push(diagnostic); diff --git a/crates/ruff_linter/src/codes.rs b/crates/ruff_linter/src/codes.rs index fc2a17fb1f995d..e4f1b09bd1c062 100644 --- a/crates/ruff_linter/src/codes.rs +++ b/crates/ruff_linter/src/codes.rs @@ -513,7 +513,6 @@ pub fn code_to_rule(linter: Linter, code: &str) -> Option<(RuleGroup, Rule)> { (Pyupgrade, "024") => (RuleGroup::Stable, rules::pyupgrade::rules::OSErrorAlias), (Pyupgrade, "025") => (RuleGroup::Stable, rules::pyupgrade::rules::UnicodeKindPrefix), (Pyupgrade, "026") => (RuleGroup::Stable, rules::pyupgrade::rules::DeprecatedMockImport), - (Pyupgrade, "027") => (RuleGroup::Deprecated, rules::pyupgrade::rules::UnpackedListComprehension), (Pyupgrade, "028") => (RuleGroup::Stable, rules::pyupgrade::rules::YieldInForLoop), (Pyupgrade, "029") => (RuleGroup::Stable, rules::pyupgrade::rules::UnnecessaryBuiltinImport), (Pyupgrade, "030") => (RuleGroup::Stable, rules::pyupgrade::rules::FormatLiterals), diff --git a/crates/ruff_linter/src/rules/pyupgrade/mod.rs b/crates/ruff_linter/src/rules/pyupgrade/mod.rs index 950e53dee673c4..2fc8ac7df9b8e3 100644 --- a/crates/ruff_linter/src/rules/pyupgrade/mod.rs +++ b/crates/ruff_linter/src/rules/pyupgrade/mod.rs @@ -83,7 +83,6 @@ mod tests { #[test_case(Rule::UnnecessaryDefaultTypeArgs, Path::new("UP043.py"))] #[test_case(Rule::UnnecessaryEncodeUTF8, Path::new("UP012.py"))] #[test_case(Rule::UnnecessaryFutureImport, Path::new("UP010.py"))] - #[test_case(Rule::UnpackedListComprehension, Path::new("UP027.py"))] #[test_case(Rule::UselessMetaclassType, Path::new("UP001.py"))] #[test_case(Rule::UselessObjectInheritance, Path::new("UP004.py"))] #[test_case(Rule::YieldInForLoop, Path::new("UP028_0.py"))] diff --git a/crates/ruff_linter/src/rules/pyupgrade/rules/mod.rs b/crates/ruff_linter/src/rules/pyupgrade/rules/mod.rs index ac3ea97d308568..01ea9124fc24da 100644 --- a/crates/ruff_linter/src/rules/pyupgrade/rules/mod.rs +++ b/crates/ruff_linter/src/rules/pyupgrade/rules/mod.rs @@ -31,7 +31,6 @@ pub(crate) use unnecessary_coding_comment::*; pub(crate) use unnecessary_default_type_args::*; pub(crate) use unnecessary_encode_utf8::*; pub(crate) use unnecessary_future_import::*; -pub(crate) use unpacked_list_comprehension::*; pub(crate) use use_pep585_annotation::*; pub(crate) use use_pep604_annotation::*; pub(crate) use use_pep604_isinstance::*; @@ -74,7 +73,6 @@ mod unnecessary_coding_comment; mod unnecessary_default_type_args; mod unnecessary_encode_utf8; mod unnecessary_future_import; -mod unpacked_list_comprehension; mod use_pep585_annotation; mod use_pep604_annotation; mod use_pep604_isinstance; diff --git a/crates/ruff_linter/src/rules/pyupgrade/rules/unpacked_list_comprehension.rs b/crates/ruff_linter/src/rules/pyupgrade/rules/unpacked_list_comprehension.rs deleted file mode 100644 index 3162725e00f290..00000000000000 --- a/crates/ruff_linter/src/rules/pyupgrade/rules/unpacked_list_comprehension.rs +++ /dev/null @@ -1,89 +0,0 @@ -use ruff_python_ast::{self as ast, Expr}; - -use ruff_diagnostics::{AlwaysFixableViolation, Diagnostic, Edit, Fix}; -use ruff_macros::{derive_message_formats, violation}; -use ruff_python_ast::helpers::any_over_expr; -use ruff_text_size::Ranged; - -use crate::checkers::ast::Checker; - -/// ## Deprecation -/// There's no [evidence](https://github.com/astral-sh/ruff/issues/12754) that generators are -/// meaningfully faster than list comprehensions when combined with unpacking. -/// -/// ## What it does -/// Checks for list comprehensions that are immediately unpacked. -/// -/// ## Why is this bad? -/// There is no reason to use a list comprehension if the result is immediately -/// unpacked. Instead, use a generator expression, which avoids allocating -/// an intermediary list. -/// -/// ## Example -/// ```python -/// a, b, c = [foo(x) for x in items] -/// ``` -/// -/// Use instead: -/// ```python -/// a, b, c = (foo(x) for x in items) -/// ``` -/// -/// ## References -/// - [Python documentation: Generator expressions](https://docs.python.org/3/reference/expressions.html#generator-expressions) -/// - [Python documentation: List comprehensions](https://docs.python.org/3/tutorial/datastructures.html#list-comprehensions) -#[violation] -pub struct UnpackedListComprehension; - -impl AlwaysFixableViolation for UnpackedListComprehension { - #[derive_message_formats] - fn message(&self) -> String { - "Replace unpacked list comprehension with a generator expression".to_string() - } - - fn fix_title(&self) -> String { - "Replace with generator expression".to_string() - } -} - -/// UP027 -pub(crate) fn unpacked_list_comprehension(checker: &mut Checker, targets: &[Expr], value: &Expr) { - let Some(target) = targets.first() else { - return; - }; - - if !target.is_tuple_expr() { - return; - } - - let Expr::ListComp(ast::ExprListComp { - elt, - generators, - range: _, - }) = value - else { - return; - }; - - if generators.iter().any(|generator| generator.is_async) || contains_await(elt) { - return; - } - - let mut diagnostic = Diagnostic::new(UnpackedListComprehension, value.range()); - let existing = checker.locator().slice(value); - - let mut content = String::with_capacity(existing.len()); - content.push('('); - content.push_str(&existing[1..existing.len() - 1]); - content.push(')'); - diagnostic.set_fix(Fix::safe_edit(Edit::range_replacement( - content, - value.range(), - ))); - checker.diagnostics.push(diagnostic); -} - -/// Return `true` if the [`Expr`] contains an `await` expression. -fn contains_await(expr: &Expr) -> bool { - any_over_expr(expr, &Expr::is_await_expr) -} diff --git a/crates/ruff_linter/src/rules/pyupgrade/snapshots/ruff_linter__rules__pyupgrade__tests__UP027.py.snap b/crates/ruff_linter/src/rules/pyupgrade/snapshots/ruff_linter__rules__pyupgrade__tests__UP027.py.snap deleted file mode 100644 index 526b2ea8467ead..00000000000000 --- a/crates/ruff_linter/src/rules/pyupgrade/snapshots/ruff_linter__rules__pyupgrade__tests__UP027.py.snap +++ /dev/null @@ -1,113 +0,0 @@ ---- -source: crates/ruff_linter/src/rules/pyupgrade/mod.rs -snapshot_kind: text ---- -UP027.py:2:17: UP027 [*] Replace unpacked list comprehension with a generator expression - | -1 | # Should change -2 | foo, bar, baz = [fn(x) for x in items] - | ^^^^^^^^^^^^^^^^^^^^^^ UP027 -3 | -4 | foo, bar, baz =[fn(x) for x in items] - | - = help: Replace with generator expression - -ℹ Safe fix -1 1 | # Should change -2 |-foo, bar, baz = [fn(x) for x in items] - 2 |+foo, bar, baz = (fn(x) for x in items) -3 3 | -4 4 | foo, bar, baz =[fn(x) for x in items] -5 5 | - -UP027.py:4:16: UP027 [*] Replace unpacked list comprehension with a generator expression - | -2 | foo, bar, baz = [fn(x) for x in items] -3 | -4 | foo, bar, baz =[fn(x) for x in items] - | ^^^^^^^^^^^^^^^^^^^^^^ UP027 -5 | -6 | foo, bar, baz = [fn(x) for x in items] - | - = help: Replace with generator expression - -ℹ Safe fix -1 1 | # Should change -2 2 | foo, bar, baz = [fn(x) for x in items] -3 3 | -4 |-foo, bar, baz =[fn(x) for x in items] - 4 |+foo, bar, baz =(fn(x) for x in items) -5 5 | -6 6 | foo, bar, baz = [fn(x) for x in items] -7 7 | - -UP027.py:6:26: UP027 [*] Replace unpacked list comprehension with a generator expression - | -4 | foo, bar, baz =[fn(x) for x in items] -5 | -6 | foo, bar, baz = [fn(x) for x in items] - | ^^^^^^^^^^^^^^^^^^^^^^ UP027 -7 | -8 | foo, bar, baz = [[i for i in fn(x)] for x in items] - | - = help: Replace with generator expression - -ℹ Safe fix -3 3 | -4 4 | foo, bar, baz =[fn(x) for x in items] -5 5 | -6 |-foo, bar, baz = [fn(x) for x in items] - 6 |+foo, bar, baz = (fn(x) for x in items) -7 7 | -8 8 | foo, bar, baz = [[i for i in fn(x)] for x in items] -9 9 | - -UP027.py:8:17: UP027 [*] Replace unpacked list comprehension with a generator expression - | - 6 | foo, bar, baz = [fn(x) for x in items] - 7 | - 8 | foo, bar, baz = [[i for i in fn(x)] for x in items] - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ UP027 - 9 | -10 | foo, bar, baz = [ - | - = help: Replace with generator expression - -ℹ Safe fix -5 5 | -6 6 | foo, bar, baz = [fn(x) for x in items] -7 7 | -8 |-foo, bar, baz = [[i for i in fn(x)] for x in items] - 8 |+foo, bar, baz = ([i for i in fn(x)] for x in items) -9 9 | -10 10 | foo, bar, baz = [ -11 11 | fn(x) - -UP027.py:10:17: UP027 [*] Replace unpacked list comprehension with a generator expression - | - 8 | foo, bar, baz = [[i for i in fn(x)] for x in items] - 9 | -10 | foo, bar, baz = [ - | _________________^ -11 | | fn(x) -12 | | for x in items -13 | | ] - | |_^ UP027 -14 | -15 | # Should not change - | - = help: Replace with generator expression - -ℹ Safe fix -7 7 | -8 8 | foo, bar, baz = [[i for i in fn(x)] for x in items] -9 9 | -10 |-foo, bar, baz = [ - 10 |+foo, bar, baz = ( -11 11 | fn(x) -12 12 | for x in items -13 |-] - 13 |+) -14 14 | -15 15 | # Should not change -16 16 | foo = [fn(x) for x in items] diff --git a/ruff.schema.json b/ruff.schema.json index 271182150d52e6..843a1d615832fc 100644 --- a/ruff.schema.json +++ b/ruff.schema.json @@ -4073,7 +4073,6 @@ "UP024", "UP025", "UP026", - "UP027", "UP028", "UP029", "UP03",