diff --git a/crates/ruff/resources/test/fixtures/ruff/RUF015.py b/crates/ruff/resources/test/fixtures/ruff/RUF015.py index 393694d89b3f1..2aa92f467cfe8 100644 --- a/crates/ruff/resources/test/fixtures/ruff/RUF015.py +++ b/crates/ruff/resources/test/fixtures/ruff/RUF015.py @@ -2,21 +2,9 @@ # RUF015 list(x)[0] -list(x)[:1] -list(x)[:1:1] -list(x)[:1:2] tuple(x)[0] -tuple(x)[:1] -tuple(x)[:1:1] -tuple(x)[:1:2] list(i for i in x)[0] -list(i for i in x)[:1] -list(i for i in x)[:1:1] -list(i for i in x)[:1:2] [i for i in x][0] -[i for i in x][:1] -[i for i in x][:1:1] -[i for i in x][:1:2] # OK (not indexing (solely) the first element) list(x) @@ -29,6 +17,9 @@ [i for i in x] [i for i in x][1] [i for i in x][-1] +[i for i in x][:1] +[i for i in x][:1:1] +[i for i in x][:1:2] [i for i in x][1:] [i for i in x][:3:2] [i for i in x][::2] diff --git a/crates/ruff/src/rules/ruff/rules/unnecessary_iterable_allocation_for_first_element.rs b/crates/ruff/src/rules/ruff/rules/unnecessary_iterable_allocation_for_first_element.rs index 47c789f65e3ca..85ae2bb9dfedd 100644 --- a/crates/ruff/src/rules/ruff/rules/unnecessary_iterable_allocation_for_first_element.rs +++ b/crates/ruff/src/rules/ruff/rules/unnecessary_iterable_allocation_for_first_element.rs @@ -1,14 +1,13 @@ use std::borrow::Cow; -use num_bigint::BigInt; -use num_traits::{One, Zero}; -use ruff_python_ast::{self as ast, Comprehension, Constant, Expr, Ranged}; -use ruff_text_size::{TextRange, TextSize}; +use num_traits::Zero; use unicode_width::UnicodeWidthStr; use ruff_diagnostics::{AlwaysAutofixableViolation, Diagnostic, Edit, Fix}; use ruff_macros::{derive_message_formats, violation}; +use ruff_python_ast::{self as ast, Comprehension, Constant, Expr, Ranged}; use ruff_python_semantic::SemanticModel; +use ruff_text_size::{TextRange, TextSize}; use crate::checkers::ast::Checker; use crate::registry::AsRule; @@ -49,37 +48,20 @@ use crate::registry::AsRule; #[violation] pub(crate) struct UnnecessaryIterableAllocationForFirstElement { iterable: String, - subscript_kind: HeadSubscriptKind, } impl AlwaysAutofixableViolation for UnnecessaryIterableAllocationForFirstElement { #[derive_message_formats] fn message(&self) -> String { - let UnnecessaryIterableAllocationForFirstElement { - iterable, - subscript_kind, - } = self; + let UnnecessaryIterableAllocationForFirstElement { iterable } = self; let iterable = Self::truncate(iterable); - match subscript_kind { - HeadSubscriptKind::Index => { - format!("Prefer `next({iterable})` over single element slice") - } - HeadSubscriptKind::Slice => { - format!("Prefer `[next({iterable})]` over single element slice") - } - } + format!("Prefer `next({iterable})` over single element slice") } fn autofix_title(&self) -> String { - let UnnecessaryIterableAllocationForFirstElement { - iterable, - subscript_kind, - } = self; + let UnnecessaryIterableAllocationForFirstElement { iterable } = self; let iterable = Self::truncate(iterable); - match subscript_kind { - HeadSubscriptKind::Index => format!("Replace with `next({iterable})`"), - HeadSubscriptKind::Slice => format!("Replace with `[next({iterable})]"), - } + format!("Replace with `next({iterable})`") } } @@ -106,9 +88,9 @@ pub(crate) fn unnecessary_iterable_allocation_for_first_element( .. } = subscript; - let Some(subscript_kind) = classify_subscript(slice) else { + if !is_head_slice(slice) { return; - }; + } let Some(target) = match_iteration_target(value, checker.semantic()) else { return; @@ -123,72 +105,31 @@ pub(crate) fn unnecessary_iterable_allocation_for_first_element( let mut diagnostic = Diagnostic::new( UnnecessaryIterableAllocationForFirstElement { iterable: iterable.to_string(), - subscript_kind, }, *range, ); if checker.patch(diagnostic.kind.rule()) { - let replacement = match subscript_kind { - HeadSubscriptKind::Index => format!("next({iterable})"), - HeadSubscriptKind::Slice => format!("[next({iterable})]"), - }; - diagnostic.set_fix(Fix::suggested(Edit::range_replacement(replacement, *range))); + diagnostic.set_fix(Fix::suggested(Edit::range_replacement( + format!("next({iterable})"), + *range, + ))); } checker.diagnostics.push(diagnostic); } -/// A subscript slice that represents the first element of a list. -#[derive(Debug, Clone, Copy, PartialEq, Eq)] -enum HeadSubscriptKind { - /// The subscript is an index (e.g., `[0]`). - Index, - /// The subscript is a slice (e.g., `[:1]`). - Slice, -} - -/// Check that the slice [`Expr`] is functionally equivalent to slicing into the first element. The -/// first `bool` checks that the element is in fact first, the second checks if it's a slice or an -/// index. -fn classify_subscript(expr: &Expr) -> Option { - let result = match expr { - Expr::Constant(ast::ExprConstant { - value: Constant::Int(value), - .. - }) if value.is_zero() => HeadSubscriptKind::Index, - Expr::Slice(ast::ExprSlice { - step, lower, upper, .. - }) => { - // Avoid, e.g., `list(...)[:2]` - let upper = upper.as_ref()?; - let upper = as_int(upper)?; - if !upper.is_one() { - return None; - } - - // Avoid, e.g., `list(...)[2:]`. - if let Some(lower) = lower.as_ref() { - let lower = as_int(lower)?; - if !lower.is_zero() { - return None; - } - } - - // Avoid, e.g., `list(...)[::-1]` - if let Some(step) = step.as_ref() { - let step = as_int(step)?; - if step < upper { - return None; - } - } - - HeadSubscriptKind::Slice - } - _ => return None, - }; - - Some(result) +/// Check that the slice [`Expr`] is a slice of the first element (e.g., `x[0]`). +fn is_head_slice(expr: &Expr) -> bool { + if let Expr::Constant(ast::ExprConstant { + value: Constant::Int(value), + .. + }) = expr + { + value.is_zero() + } else { + false + } } #[derive(Debug)] @@ -310,17 +251,3 @@ fn match_simple_comprehension(elt: &Expr, generators: &[Comprehension]) -> Optio Some(generator.iter.range()) } - -/// If an expression is a constant integer, returns the value of that integer; otherwise, -/// returns `None`. -fn as_int(expr: &Expr) -> Option<&BigInt> { - if let Expr::Constant(ast::ExprConstant { - value: Constant::Int(value), - .. - }) = expr - { - Some(value) - } else { - None - } -} diff --git a/crates/ruff/src/rules/ruff/snapshots/ruff__rules__ruff__tests__RUF015_RUF015.py.snap b/crates/ruff/src/rules/ruff/snapshots/ruff__rules__ruff__tests__RUF015_RUF015.py.snap index c55e737c6d0b3..e8f01fe1a2c47 100644 --- a/crates/ruff/src/rules/ruff/snapshots/ruff__rules__ruff__tests__RUF015_RUF015.py.snap +++ b/crates/ruff/src/rules/ruff/snapshots/ruff__rules__ruff__tests__RUF015_RUF015.py.snap @@ -6,8 +6,8 @@ RUF015.py:4:1: RUF015 [*] Prefer `next(iter(x))` over single element slice 3 | # RUF015 4 | list(x)[0] | ^^^^^^^^^^ RUF015 -5 | list(x)[:1] -6 | list(x)[:1:1] +5 | tuple(x)[0] +6 | list(i for i in x)[0] | = help: Replace with `next(iter(x))` @@ -17,490 +17,238 @@ RUF015.py:4:1: RUF015 [*] Prefer `next(iter(x))` over single element slice 3 3 | # RUF015 4 |-list(x)[0] 4 |+next(iter(x)) -5 5 | list(x)[:1] -6 6 | list(x)[:1:1] -7 7 | list(x)[:1:2] +5 5 | tuple(x)[0] +6 6 | list(i for i in x)[0] +7 7 | [i for i in x][0] -RUF015.py:5:1: RUF015 [*] Prefer `[next(iter(x))]` over single element slice +RUF015.py:5:1: RUF015 [*] Prefer `next(iter(x))` over single element slice | 3 | # RUF015 4 | list(x)[0] -5 | list(x)[:1] +5 | tuple(x)[0] | ^^^^^^^^^^^ RUF015 -6 | list(x)[:1:1] -7 | list(x)[:1:2] +6 | list(i for i in x)[0] +7 | [i for i in x][0] | - = help: Replace with `[next(iter(x))] + = help: Replace with `next(iter(x))` ℹ Suggested fix 2 2 | 3 3 | # RUF015 4 4 | list(x)[0] -5 |-list(x)[:1] - 5 |+[next(iter(x))] -6 6 | list(x)[:1:1] -7 7 | list(x)[:1:2] -8 8 | tuple(x)[0] +5 |-tuple(x)[0] + 5 |+next(iter(x)) +6 6 | list(i for i in x)[0] +7 7 | [i for i in x][0] +8 8 | -RUF015.py:6:1: RUF015 [*] Prefer `[next(iter(x))]` over single element slice +RUF015.py:6:1: RUF015 [*] Prefer `next(iter(x))` over single element slice | 4 | list(x)[0] -5 | list(x)[:1] -6 | list(x)[:1:1] - | ^^^^^^^^^^^^^ RUF015 -7 | list(x)[:1:2] -8 | tuple(x)[0] +5 | tuple(x)[0] +6 | list(i for i in x)[0] + | ^^^^^^^^^^^^^^^^^^^^^ RUF015 +7 | [i for i in x][0] | - = help: Replace with `[next(iter(x))] + = help: Replace with `next(iter(x))` ℹ Suggested fix 3 3 | # RUF015 4 4 | list(x)[0] -5 5 | list(x)[:1] -6 |-list(x)[:1:1] - 6 |+[next(iter(x))] -7 7 | list(x)[:1:2] -8 8 | tuple(x)[0] -9 9 | tuple(x)[:1] - -RUF015.py:7:1: RUF015 [*] Prefer `[next(iter(x))]` over single element slice +5 5 | tuple(x)[0] +6 |-list(i for i in x)[0] + 6 |+next(iter(x)) +7 7 | [i for i in x][0] +8 8 | +9 9 | # OK (not indexing (solely) the first element) + +RUF015.py:7:1: RUF015 [*] Prefer `next(iter(x))` over single element slice | -5 | list(x)[:1] -6 | list(x)[:1:1] -7 | list(x)[:1:2] - | ^^^^^^^^^^^^^ RUF015 -8 | tuple(x)[0] -9 | tuple(x)[:1] +5 | tuple(x)[0] +6 | list(i for i in x)[0] +7 | [i for i in x][0] + | ^^^^^^^^^^^^^^^^^ RUF015 +8 | +9 | # OK (not indexing (solely) the first element) | - = help: Replace with `[next(iter(x))] + = help: Replace with `next(iter(x))` ℹ Suggested fix 4 4 | list(x)[0] -5 5 | list(x)[:1] -6 6 | list(x)[:1:1] -7 |-list(x)[:1:2] - 7 |+[next(iter(x))] -8 8 | tuple(x)[0] -9 9 | tuple(x)[:1] -10 10 | tuple(x)[:1:1] - -RUF015.py:8:1: RUF015 [*] Prefer `next(iter(x))` over single element slice - | - 6 | list(x)[:1:1] - 7 | list(x)[:1:2] - 8 | tuple(x)[0] - | ^^^^^^^^^^^ RUF015 - 9 | tuple(x)[:1] -10 | tuple(x)[:1:1] - | - = help: Replace with `next(iter(x))` - -ℹ Suggested fix -5 5 | list(x)[:1] -6 6 | list(x)[:1:1] -7 7 | list(x)[:1:2] -8 |-tuple(x)[0] - 8 |+next(iter(x)) -9 9 | tuple(x)[:1] -10 10 | tuple(x)[:1:1] -11 11 | tuple(x)[:1:2] - -RUF015.py:9:1: RUF015 [*] Prefer `[next(iter(x))]` over single element slice - | - 7 | list(x)[:1:2] - 8 | tuple(x)[0] - 9 | tuple(x)[:1] - | ^^^^^^^^^^^^ RUF015 -10 | tuple(x)[:1:1] -11 | tuple(x)[:1:2] - | - = help: Replace with `[next(iter(x))] - -ℹ Suggested fix -6 6 | list(x)[:1:1] -7 7 | list(x)[:1:2] -8 8 | tuple(x)[0] -9 |-tuple(x)[:1] - 9 |+[next(iter(x))] -10 10 | tuple(x)[:1:1] -11 11 | tuple(x)[:1:2] -12 12 | list(i for i in x)[0] - -RUF015.py:10:1: RUF015 [*] Prefer `[next(iter(x))]` over single element slice - | - 8 | tuple(x)[0] - 9 | tuple(x)[:1] -10 | tuple(x)[:1:1] - | ^^^^^^^^^^^^^^ RUF015 -11 | tuple(x)[:1:2] -12 | list(i for i in x)[0] - | - = help: Replace with `[next(iter(x))] - -ℹ Suggested fix -7 7 | list(x)[:1:2] -8 8 | tuple(x)[0] -9 9 | tuple(x)[:1] -10 |-tuple(x)[:1:1] - 10 |+[next(iter(x))] -11 11 | tuple(x)[:1:2] -12 12 | list(i for i in x)[0] -13 13 | list(i for i in x)[:1] - -RUF015.py:11:1: RUF015 [*] Prefer `[next(iter(x))]` over single element slice - | - 9 | tuple(x)[:1] -10 | tuple(x)[:1:1] -11 | tuple(x)[:1:2] - | ^^^^^^^^^^^^^^ RUF015 -12 | list(i for i in x)[0] -13 | list(i for i in x)[:1] - | - = help: Replace with `[next(iter(x))] - -ℹ Suggested fix -8 8 | tuple(x)[0] -9 9 | tuple(x)[:1] -10 10 | tuple(x)[:1:1] -11 |-tuple(x)[:1:2] - 11 |+[next(iter(x))] -12 12 | list(i for i in x)[0] -13 13 | list(i for i in x)[:1] -14 14 | list(i for i in x)[:1:1] - -RUF015.py:12:1: RUF015 [*] Prefer `next(iter(x))` over single element slice - | -10 | tuple(x)[:1:1] -11 | tuple(x)[:1:2] -12 | list(i for i in x)[0] - | ^^^^^^^^^^^^^^^^^^^^^ RUF015 -13 | list(i for i in x)[:1] -14 | list(i for i in x)[:1:1] - | - = help: Replace with `next(iter(x))` - -ℹ Suggested fix -9 9 | tuple(x)[:1] -10 10 | tuple(x)[:1:1] -11 11 | tuple(x)[:1:2] -12 |-list(i for i in x)[0] - 12 |+next(iter(x)) -13 13 | list(i for i in x)[:1] -14 14 | list(i for i in x)[:1:1] -15 15 | list(i for i in x)[:1:2] - -RUF015.py:13:1: RUF015 [*] Prefer `[next(iter(x))]` over single element slice - | -11 | tuple(x)[:1:2] -12 | list(i for i in x)[0] -13 | list(i for i in x)[:1] - | ^^^^^^^^^^^^^^^^^^^^^^ RUF015 -14 | list(i for i in x)[:1:1] -15 | list(i for i in x)[:1:2] - | - = help: Replace with `[next(iter(x))] - -ℹ Suggested fix -10 10 | tuple(x)[:1:1] -11 11 | tuple(x)[:1:2] -12 12 | list(i for i in x)[0] -13 |-list(i for i in x)[:1] - 13 |+[next(iter(x))] -14 14 | list(i for i in x)[:1:1] -15 15 | list(i for i in x)[:1:2] -16 16 | [i for i in x][0] - -RUF015.py:14:1: RUF015 [*] Prefer `[next(iter(x))]` over single element slice - | -12 | list(i for i in x)[0] -13 | list(i for i in x)[:1] -14 | list(i for i in x)[:1:1] - | ^^^^^^^^^^^^^^^^^^^^^^^^ RUF015 -15 | list(i for i in x)[:1:2] -16 | [i for i in x][0] - | - = help: Replace with `[next(iter(x))] - -ℹ Suggested fix -11 11 | tuple(x)[:1:2] -12 12 | list(i for i in x)[0] -13 13 | list(i for i in x)[:1] -14 |-list(i for i in x)[:1:1] - 14 |+[next(iter(x))] -15 15 | list(i for i in x)[:1:2] -16 16 | [i for i in x][0] -17 17 | [i for i in x][:1] - -RUF015.py:15:1: RUF015 [*] Prefer `[next(iter(x))]` over single element slice - | -13 | list(i for i in x)[:1] -14 | list(i for i in x)[:1:1] -15 | list(i for i in x)[:1:2] - | ^^^^^^^^^^^^^^^^^^^^^^^^ RUF015 -16 | [i for i in x][0] -17 | [i for i in x][:1] - | - = help: Replace with `[next(iter(x))] - -ℹ Suggested fix -12 12 | list(i for i in x)[0] -13 13 | list(i for i in x)[:1] -14 14 | list(i for i in x)[:1:1] -15 |-list(i for i in x)[:1:2] - 15 |+[next(iter(x))] -16 16 | [i for i in x][0] -17 17 | [i for i in x][:1] -18 18 | [i for i in x][:1:1] - -RUF015.py:16:1: RUF015 [*] Prefer `next(iter(x))` over single element slice - | -14 | list(i for i in x)[:1:1] -15 | list(i for i in x)[:1:2] -16 | [i for i in x][0] - | ^^^^^^^^^^^^^^^^^ RUF015 -17 | [i for i in x][:1] -18 | [i for i in x][:1:1] - | - = help: Replace with `next(iter(x))` - -ℹ Suggested fix -13 13 | list(i for i in x)[:1] -14 14 | list(i for i in x)[:1:1] -15 15 | list(i for i in x)[:1:2] -16 |-[i for i in x][0] - 16 |+next(iter(x)) -17 17 | [i for i in x][:1] -18 18 | [i for i in x][:1:1] -19 19 | [i for i in x][:1:2] - -RUF015.py:17:1: RUF015 [*] Prefer `[next(iter(x))]` over single element slice - | -15 | list(i for i in x)[:1:2] -16 | [i for i in x][0] -17 | [i for i in x][:1] - | ^^^^^^^^^^^^^^^^^^ RUF015 -18 | [i for i in x][:1:1] -19 | [i for i in x][:1:2] - | - = help: Replace with `[next(iter(x))] - -ℹ Suggested fix -14 14 | list(i for i in x)[:1:1] -15 15 | list(i for i in x)[:1:2] -16 16 | [i for i in x][0] -17 |-[i for i in x][:1] - 17 |+[next(iter(x))] -18 18 | [i for i in x][:1:1] -19 19 | [i for i in x][:1:2] -20 20 | - -RUF015.py:18:1: RUF015 [*] Prefer `[next(iter(x))]` over single element slice - | -16 | [i for i in x][0] -17 | [i for i in x][:1] -18 | [i for i in x][:1:1] - | ^^^^^^^^^^^^^^^^^^^^ RUF015 -19 | [i for i in x][:1:2] - | - = help: Replace with `[next(iter(x))] - -ℹ Suggested fix -15 15 | list(i for i in x)[:1:2] -16 16 | [i for i in x][0] -17 17 | [i for i in x][:1] -18 |-[i for i in x][:1:1] - 18 |+[next(iter(x))] -19 19 | [i for i in x][:1:2] -20 20 | -21 21 | # OK (not indexing (solely) the first element) - -RUF015.py:19:1: RUF015 [*] Prefer `[next(iter(x))]` over single element slice - | -17 | [i for i in x][:1] -18 | [i for i in x][:1:1] -19 | [i for i in x][:1:2] - | ^^^^^^^^^^^^^^^^^^^^ RUF015 -20 | -21 | # OK (not indexing (solely) the first element) - | - = help: Replace with `[next(iter(x))] - -ℹ Suggested fix -16 16 | [i for i in x][0] -17 17 | [i for i in x][:1] -18 18 | [i for i in x][:1:1] -19 |-[i for i in x][:1:2] - 19 |+[next(iter(x))] -20 20 | -21 21 | # OK (not indexing (solely) the first element) -22 22 | list(x) - -RUF015.py:38:1: RUF015 [*] Prefer `next(i + 1 for i in x)` over single element slice - | -37 | # RUF015 (doesn't mirror the underlying list) -38 | [i + 1 for i in x][0] +5 5 | tuple(x)[0] +6 6 | list(i for i in x)[0] +7 |-[i for i in x][0] + 7 |+next(iter(x)) +8 8 | +9 9 | # OK (not indexing (solely) the first element) +10 10 | list(x) + +RUF015.py:29:1: RUF015 [*] Prefer `next(i + 1 for i in x)` over single element slice + | +28 | # RUF015 (doesn't mirror the underlying list) +29 | [i + 1 for i in x][0] | ^^^^^^^^^^^^^^^^^^^^^ RUF015 -39 | [i for i in x if i > 5][0] -40 | [(i, i + 1) for i in x][0] +30 | [i for i in x if i > 5][0] +31 | [(i, i + 1) for i in x][0] | = help: Replace with `next(i + 1 for i in x)` ℹ Suggested fix -35 35 | [i for i in x][::] -36 36 | -37 37 | # RUF015 (doesn't mirror the underlying list) -38 |-[i + 1 for i in x][0] - 38 |+next(i + 1 for i in x) -39 39 | [i for i in x if i > 5][0] -40 40 | [(i, i + 1) for i in x][0] -41 41 | +26 26 | [i for i in x][::] +27 27 | +28 28 | # RUF015 (doesn't mirror the underlying list) +29 |-[i + 1 for i in x][0] + 29 |+next(i + 1 for i in x) +30 30 | [i for i in x if i > 5][0] +31 31 | [(i, i + 1) for i in x][0] +32 32 | -RUF015.py:39:1: RUF015 [*] Prefer `next(i for i in x if i > 5)` over single element slice +RUF015.py:30:1: RUF015 [*] Prefer `next(i for i in x if i > 5)` over single element slice | -37 | # RUF015 (doesn't mirror the underlying list) -38 | [i + 1 for i in x][0] -39 | [i for i in x if i > 5][0] +28 | # RUF015 (doesn't mirror the underlying list) +29 | [i + 1 for i in x][0] +30 | [i for i in x if i > 5][0] | ^^^^^^^^^^^^^^^^^^^^^^^^^^ RUF015 -40 | [(i, i + 1) for i in x][0] +31 | [(i, i + 1) for i in x][0] | = help: Replace with `next(i for i in x if i > 5)` ℹ Suggested fix -36 36 | -37 37 | # RUF015 (doesn't mirror the underlying list) -38 38 | [i + 1 for i in x][0] -39 |-[i for i in x if i > 5][0] - 39 |+next(i for i in x if i > 5) -40 40 | [(i, i + 1) for i in x][0] -41 41 | -42 42 | # RUF015 (multiple generators) +27 27 | +28 28 | # RUF015 (doesn't mirror the underlying list) +29 29 | [i + 1 for i in x][0] +30 |-[i for i in x if i > 5][0] + 30 |+next(i for i in x if i > 5) +31 31 | [(i, i + 1) for i in x][0] +32 32 | +33 33 | # RUF015 (multiple generators) -RUF015.py:40:1: RUF015 [*] Prefer `next((i, i + 1) for i in x)` over single element slice +RUF015.py:31:1: RUF015 [*] Prefer `next((i, i + 1) for i in x)` over single element slice | -38 | [i + 1 for i in x][0] -39 | [i for i in x if i > 5][0] -40 | [(i, i + 1) for i in x][0] +29 | [i + 1 for i in x][0] +30 | [i for i in x if i > 5][0] +31 | [(i, i + 1) for i in x][0] | ^^^^^^^^^^^^^^^^^^^^^^^^^^ RUF015 -41 | -42 | # RUF015 (multiple generators) +32 | +33 | # RUF015 (multiple generators) | = help: Replace with `next((i, i + 1) for i in x)` ℹ Suggested fix -37 37 | # RUF015 (doesn't mirror the underlying list) -38 38 | [i + 1 for i in x][0] -39 39 | [i for i in x if i > 5][0] -40 |-[(i, i + 1) for i in x][0] - 40 |+next((i, i + 1) for i in x) -41 41 | -42 42 | # RUF015 (multiple generators) -43 43 | y = range(10) +28 28 | # RUF015 (doesn't mirror the underlying list) +29 29 | [i + 1 for i in x][0] +30 30 | [i for i in x if i > 5][0] +31 |-[(i, i + 1) for i in x][0] + 31 |+next((i, i + 1) for i in x) +32 32 | +33 33 | # RUF015 (multiple generators) +34 34 | y = range(10) -RUF015.py:44:1: RUF015 [*] Prefer `next(i + j for i in x for j in y)` over single element slice +RUF015.py:35:1: RUF015 [*] Prefer `next(i + j for i in x for j in y)` over single element slice | -42 | # RUF015 (multiple generators) -43 | y = range(10) -44 | [i + j for i in x for j in y][0] +33 | # RUF015 (multiple generators) +34 | y = range(10) +35 | [i + j for i in x for j in y][0] | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ RUF015 -45 | -46 | # RUF015 +36 | +37 | # RUF015 | = help: Replace with `next(i + j for i in x for j in y)` ℹ Suggested fix -41 41 | -42 42 | # RUF015 (multiple generators) -43 43 | y = range(10) -44 |-[i + j for i in x for j in y][0] - 44 |+next(i + j for i in x for j in y) -45 45 | -46 46 | # RUF015 -47 47 | list(range(10))[0] +32 32 | +33 33 | # RUF015 (multiple generators) +34 34 | y = range(10) +35 |-[i + j for i in x for j in y][0] + 35 |+next(i + j for i in x for j in y) +36 36 | +37 37 | # RUF015 +38 38 | list(range(10))[0] -RUF015.py:47:1: RUF015 [*] Prefer `next(iter(range(10)))` over single element slice +RUF015.py:38:1: RUF015 [*] Prefer `next(iter(range(10)))` over single element slice | -46 | # RUF015 -47 | list(range(10))[0] +37 | # RUF015 +38 | list(range(10))[0] | ^^^^^^^^^^^^^^^^^^ RUF015 -48 | list(x.y)[0] -49 | list(x["y"])[0] +39 | list(x.y)[0] +40 | list(x["y"])[0] | = help: Replace with `next(iter(range(10)))` ℹ Suggested fix -44 44 | [i + j for i in x for j in y][0] -45 45 | -46 46 | # RUF015 -47 |-list(range(10))[0] - 47 |+next(iter(range(10))) -48 48 | list(x.y)[0] -49 49 | list(x["y"])[0] -50 50 | +35 35 | [i + j for i in x for j in y][0] +36 36 | +37 37 | # RUF015 +38 |-list(range(10))[0] + 38 |+next(iter(range(10))) +39 39 | list(x.y)[0] +40 40 | list(x["y"])[0] +41 41 | -RUF015.py:48:1: RUF015 [*] Prefer `next(iter(x.y))` over single element slice +RUF015.py:39:1: RUF015 [*] Prefer `next(iter(x.y))` over single element slice | -46 | # RUF015 -47 | list(range(10))[0] -48 | list(x.y)[0] +37 | # RUF015 +38 | list(range(10))[0] +39 | list(x.y)[0] | ^^^^^^^^^^^^ RUF015 -49 | list(x["y"])[0] +40 | list(x["y"])[0] | = help: Replace with `next(iter(x.y))` ℹ Suggested fix -45 45 | -46 46 | # RUF015 -47 47 | list(range(10))[0] -48 |-list(x.y)[0] - 48 |+next(iter(x.y)) -49 49 | list(x["y"])[0] -50 50 | -51 51 | # RUF015 (multi-line) +36 36 | +37 37 | # RUF015 +38 38 | list(range(10))[0] +39 |-list(x.y)[0] + 39 |+next(iter(x.y)) +40 40 | list(x["y"])[0] +41 41 | +42 42 | # RUF015 (multi-line) -RUF015.py:49:1: RUF015 [*] Prefer `next(iter(x["y"]))` over single element slice +RUF015.py:40:1: RUF015 [*] Prefer `next(iter(x["y"]))` over single element slice | -47 | list(range(10))[0] -48 | list(x.y)[0] -49 | list(x["y"])[0] +38 | list(range(10))[0] +39 | list(x.y)[0] +40 | list(x["y"])[0] | ^^^^^^^^^^^^^^^ RUF015 -50 | -51 | # RUF015 (multi-line) +41 | +42 | # RUF015 (multi-line) | = help: Replace with `next(iter(x["y"]))` ℹ Suggested fix -46 46 | # RUF015 -47 47 | list(range(10))[0] -48 48 | list(x.y)[0] -49 |-list(x["y"])[0] - 49 |+next(iter(x["y"])) -50 50 | -51 51 | # RUF015 (multi-line) -52 52 | revision_heads_map_ast = [ +37 37 | # RUF015 +38 38 | list(range(10))[0] +39 39 | list(x.y)[0] +40 |-list(x["y"])[0] + 40 |+next(iter(x["y"])) +41 41 | +42 42 | # RUF015 (multi-line) +43 43 | revision_heads_map_ast = [ -RUF015.py:52:26: RUF015 [*] Prefer `next(...)` over single element slice +RUF015.py:43:26: RUF015 [*] Prefer `next(...)` over single element slice | -51 | # RUF015 (multi-line) -52 | revision_heads_map_ast = [ +42 | # RUF015 (multi-line) +43 | revision_heads_map_ast = [ | __________________________^ -53 | | a -54 | | for a in revision_heads_map_ast_obj.body -55 | | if isinstance(a, ast.Assign) and a.targets[0].id == "REVISION_HEADS_MAP" -56 | | ][0] +44 | | a +45 | | for a in revision_heads_map_ast_obj.body +46 | | if isinstance(a, ast.Assign) and a.targets[0].id == "REVISION_HEADS_MAP" +47 | | ][0] | |____^ RUF015 | = help: Replace with `next(...)` ℹ Suggested fix -49 49 | list(x["y"])[0] -50 50 | -51 51 | # RUF015 (multi-line) -52 |-revision_heads_map_ast = [ - 52 |+revision_heads_map_ast = next( -53 53 | a -54 54 | for a in revision_heads_map_ast_obj.body -55 55 | if isinstance(a, ast.Assign) and a.targets[0].id == "REVISION_HEADS_MAP" -56 |-][0] - 56 |+) +40 40 | list(x["y"])[0] +41 41 | +42 42 | # RUF015 (multi-line) +43 |-revision_heads_map_ast = [ + 43 |+revision_heads_map_ast = next( +44 44 | a +45 45 | for a in revision_heads_map_ast_obj.body +46 46 | if isinstance(a, ast.Assign) and a.targets[0].id == "REVISION_HEADS_MAP" +47 |-][0] + 47 |+)