Extend `RUF005` to recursive and literal-literal concatenations (#4557)

This commit is contained in:
Hoël Bagard 2023-05-24 10:26:34 +09:00 committed by GitHub
parent 7479dfd815
commit a256fdb9f4
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
3 changed files with 412 additions and 291 deletions

View File

@ -1,26 +1,10 @@
class Fun:
words = ("how", "fun!")
def yay(self):
return self.words
yay = Fun().yay
foo = [4, 5, 6]
bar = [1, 2, 3] + foo
zoob = tuple(bar)
quux = (7, 8, 9) + zoob
spam = quux + (10, 11, 12)
spom = list(spam)
eggs = spom + [13, 14, 15]
elatement = ("we all say", ) + yay()
excitement = ("we all think", ) + Fun().yay()
astonishment = ("we all feel", ) + Fun.words
chain = ['a', 'b', 'c'] + eggs + list(('yes', 'no', 'pants') + zoob)
baz = () + zoob
###
# Non-fixable Errors.
###
foo + [ # This will be preserved.
]
[*foo] + [ # This will be preserved.
]
first = [
# The order
1, # here
@ -38,11 +22,47 @@ second = first + [
6,
]
###
# Fixable errors.
###
class Fun:
words = ("how", "fun!")
def yay(self):
return self.words
yay = Fun().yay
foo = [4, 5, 6]
bar = [1, 2, 3] + foo
zoob = tuple(bar)
quux = (7, 8, 9) + zoob
spam = quux + (10, 11, 12)
spom = list(spam)
eggs = spom + [13, 14, 15]
elatement = ("we all say",) + yay()
excitement = ("we all think",) + Fun().yay()
astonishment = ("we all feel",) + Fun.words
chain = ["a", "b", "c"] + eggs + list(("yes", "no", "pants") + zoob)
baz = () + zoob
[] + foo + [
]
[] + foo + [ # This will be preserved, but doesn't prevent the fix
]
pylint_call = [sys.executable, "-m", "pylint"] + args + [path]
pylint_call_tuple = (sys.executable, "-m", "pylint") + args + (path, path2)
b = a + [2, 3] + [4]
# Uses the non-preferred quote style, which should be retained.
f"{[*a(), 'b']}"
f"{a() + ['b']}"
###
# Non-errors.
###
a = (1,) + [2]
a = [1, 2] + (3, 4)
a = ([1, 2, 3] + b) + (4, 5, 6)

View File

@ -49,92 +49,106 @@ fn make_splat_elts(
}
#[derive(Debug, Copy, Clone)]
enum Kind {
enum Type {
List,
Tuple,
}
/// RUF005
/// This suggestion could be unsafe if the non-literal expression in the
/// expression has overridden the `__add__` (or `__radd__`) magic methods.
pub(crate) fn collection_literal_concatenation(checker: &mut Checker, expr: &Expr) {
/// Recursively merge all the tuples and lists in the expression.
fn concatenate_expressions(expr: &Expr) -> Option<(Expr, Type)> {
let Expr::BinOp(ast::ExprBinOp { left, op: Operator::Add, right, range: _ }) = expr else {
return;
return None;
};
// Figure out which way the splat is, and what the kind of the collection is.
let (kind, splat_element, other_elements, splat_at_left, ctx) =
match (left.as_ref(), right.as_ref()) {
(
Expr::List(ast::ExprList {
elts: l_elts,
ctx,
range: _,
}),
_,
) => (Kind::List, right, l_elts, false, ctx),
(
Expr::Tuple(ast::ExprTuple {
elts: l_elts,
ctx,
range: _,
}),
_,
) => (Kind::Tuple, right, l_elts, false, ctx),
(
_,
Expr::List(ast::ExprList {
elts: r_elts,
ctx,
range: _,
}),
) => (Kind::List, left, r_elts, true, ctx),
(
_,
Expr::Tuple(ast::ExprTuple {
elts: r_elts,
ctx,
range: _,
}),
) => (Kind::Tuple, left, r_elts, true, ctx),
_ => return,
};
let new_left = match left.as_ref() {
Expr::BinOp(ast::ExprBinOp { .. }) => match concatenate_expressions(left) {
Some((new_left, _)) => new_left,
None => *left.clone(),
},
_ => *left.clone(),
};
// We'll be a bit conservative here; only calls, names and attribute accesses
// will be considered as splat elements.
if !(splat_element.is_call_expr()
|| splat_element.is_name_expr()
|| splat_element.is_attribute_expr())
{
let new_right = match right.as_ref() {
Expr::BinOp(ast::ExprBinOp { .. }) => match concatenate_expressions(right) {
Some((new_right, _)) => new_right,
None => *right.clone(),
},
_ => *right.clone(),
};
// Figure out which way the splat is, and the type of the collection.
let (type_, splat_element, other_elements, splat_at_left) = match (&new_left, &new_right) {
(Expr::List(ast::ExprList { elts: l_elts, .. }), _) => {
(Type::List, &new_right, l_elts, false)
}
(Expr::Tuple(ast::ExprTuple { elts: l_elts, .. }), _) => {
(Type::Tuple, &new_right, l_elts, false)
}
(_, Expr::List(ast::ExprList { elts: r_elts, .. })) => {
(Type::List, &new_left, r_elts, true)
}
(_, Expr::Tuple(ast::ExprTuple { elts: r_elts, .. })) => {
(Type::Tuple, &new_left, r_elts, true)
}
_ => return None,
};
let new_elts = match splat_element {
// We'll be a bit conservative here; only calls, names and attribute accesses
// will be considered as splat elements.
Expr::Call(_) | Expr::Attribute(_) | Expr::Name(_) => {
make_splat_elts(splat_element, other_elements, splat_at_left)
}
// If the splat element is itself a list/tuple, insert them in the other list/tuple.
Expr::List(ast::ExprList { elts, .. }) if matches!(type_, Type::List) => {
other_elements.iter().chain(elts.iter()).cloned().collect()
}
Expr::Tuple(ast::ExprTuple { elts, .. }) if matches!(type_, Type::Tuple) => {
other_elements.iter().chain(elts.iter()).cloned().collect()
}
_ => return None,
};
let new_expr = match type_ {
Type::List => ast::ExprList {
elts: new_elts,
ctx: ExprContext::Load,
range: TextRange::default(),
}
.into(),
Type::Tuple => ast::ExprTuple {
elts: new_elts,
ctx: ExprContext::Load,
range: TextRange::default(),
}
.into(),
};
Some((new_expr, type_))
}
/// RUF005
pub(crate) fn collection_literal_concatenation(checker: &mut Checker, expr: &Expr) {
// If the expression is already a child of an addition, we'll have analyzed it already.
if matches!(
checker.semantic_model().expr_parent(),
Some(Expr::BinOp(ast::ExprBinOp {
op: Operator::Add,
..
}))
) {
return;
}
let new_expr = match kind {
Kind::List => {
let node = ast::ExprList {
elts: make_splat_elts(splat_element, other_elements, splat_at_left),
ctx: *ctx,
range: TextRange::default(),
};
node.into()
}
Kind::Tuple => {
let node = ast::ExprTuple {
elts: make_splat_elts(splat_element, other_elements, splat_at_left),
ctx: *ctx,
range: TextRange::default(),
};
node.into()
}
let Some((new_expr, type_)) = concatenate_expressions(expr) else {
return
};
let contents = match kind {
// Wrap the new expression in parentheses if it was a tuple
Kind::Tuple => format!("({})", checker.generator().expr(&new_expr)),
Kind::List => checker.generator().expr(&new_expr),
let contents = match type_ {
// Wrap the new expression in parentheses if it was a tuple.
Type::Tuple => format!("({})", checker.generator().expr(&new_expr)),
Type::List => checker.generator().expr(&new_expr),
};
let fixable = !has_comments(expr, checker.locator);
let mut diagnostic = Diagnostic::new(
CollectionLiteralConcatenation {
expr: contents.clone(),
@ -142,9 +156,10 @@ pub(crate) fn collection_literal_concatenation(checker: &mut Checker, expr: &Exp
expr.range(),
);
if checker.patch(diagnostic.kind.rule()) {
if fixable {
#[allow(deprecated)]
diagnostic.set_fix(Fix::unspecified(Edit::range_replacement(
if !has_comments(expr, checker.locator) {
// This suggestion could be unsafe if the non-literal expression in the
// expression has overridden the `__add__` (or `__radd__`) magic methods.
diagnostic.set_fix(Fix::suggested(Edit::range_replacement(
contents,
expr.range(),
)));

View File

@ -1,271 +1,357 @@
---
source: crates/ruff/src/rules/ruff/mod.rs
---
RUF005.py:10:7: RUF005 [*] Consider `[1, 2, 3, *foo]` instead of concatenation
RUF005.py:4:1: RUF005 Consider `[*foo]` instead of concatenation
|
4 | # Non-fixable Errors.
5 | ###
6 | / foo + [ # This will be preserved.
7 | | ]
| |_^ RUF005
8 | [*foo] + [ # This will be preserved.
9 | ]
|
= help: Replace with `[*foo]`
RUF005.py:6:1: RUF005 Consider `[*foo]` instead of concatenation
|
10 | foo = [4, 5, 6]
11 | bar = [1, 2, 3] + foo
6 | foo + [ # This will be preserved.
7 | ]
8 | / [*foo] + [ # This will be preserved.
9 | | ]
| |_^ RUF005
10 | first = [
11 | # The order
|
= help: Replace with `[*foo]`
RUF005.py:16:10: RUF005 Consider `[*first, 4, 5, 6]` instead of concatenation
|
16 | # to preserve
17 | ]
18 | second = first + [
| __________^
19 | | # please
20 | | 4,
21 | | # don't
22 | | 5,
23 | | # touch
24 | | 6,
25 | | ]
| |_^ RUF005
|
= help: Replace with `[*first, 4, 5, 6]`
RUF005.py:39:7: RUF005 [*] Consider `[1, 2, 3, *foo]` instead of concatenation
|
39 | foo = [4, 5, 6]
40 | bar = [1, 2, 3] + foo
| ^^^^^^^^^^^^^^^ RUF005
12 | zoob = tuple(bar)
13 | quux = (7, 8, 9) + zoob
41 | zoob = tuple(bar)
42 | quux = (7, 8, 9) + zoob
|
= help: Replace with `[1, 2, 3, *foo]`
Suggested fix
7 7 | yay = Fun().yay
8 8 |
9 9 | foo = [4, 5, 6]
10 |-bar = [1, 2, 3] + foo
10 |+bar = [1, 2, 3, *foo]
11 11 | zoob = tuple(bar)
12 12 | quux = (7, 8, 9) + zoob
13 13 | spam = quux + (10, 11, 12)
36 36 | yay = Fun().yay
37 37 |
38 38 | foo = [4, 5, 6]
39 |-bar = [1, 2, 3] + foo
39 |+bar = [1, 2, 3, *foo]
40 40 | zoob = tuple(bar)
41 41 | quux = (7, 8, 9) + zoob
42 42 | spam = quux + (10, 11, 12)
RUF005.py:12:8: RUF005 [*] Consider `(7, 8, 9, *zoob)` instead of concatenation
RUF005.py:41:8: RUF005 [*] Consider `(7, 8, 9, *zoob)` instead of concatenation
|
12 | bar = [1, 2, 3] + foo
13 | zoob = tuple(bar)
14 | quux = (7, 8, 9) + zoob
41 | bar = [1, 2, 3] + foo
42 | zoob = tuple(bar)
43 | quux = (7, 8, 9) + zoob
| ^^^^^^^^^^^^^^^^ RUF005
15 | spam = quux + (10, 11, 12)
16 | spom = list(spam)
44 | spam = quux + (10, 11, 12)
45 | spom = list(spam)
|
= help: Replace with `(7, 8, 9, *zoob)`
Suggested fix
9 9 | foo = [4, 5, 6]
10 10 | bar = [1, 2, 3] + foo
11 11 | zoob = tuple(bar)
12 |-quux = (7, 8, 9) + zoob
12 |+quux = (7, 8, 9, *zoob)
13 13 | spam = quux + (10, 11, 12)
14 14 | spom = list(spam)
15 15 | eggs = spom + [13, 14, 15]
38 38 | foo = [4, 5, 6]
39 39 | bar = [1, 2, 3] + foo
40 40 | zoob = tuple(bar)
41 |-quux = (7, 8, 9) + zoob
41 |+quux = (7, 8, 9, *zoob)
42 42 | spam = quux + (10, 11, 12)
43 43 | spom = list(spam)
44 44 | eggs = spom + [13, 14, 15]
RUF005.py:13:8: RUF005 [*] Consider `(*quux, 10, 11, 12)` instead of concatenation
RUF005.py:42:8: RUF005 [*] Consider `(*quux, 10, 11, 12)` instead of concatenation
|
13 | zoob = tuple(bar)
14 | quux = (7, 8, 9) + zoob
15 | spam = quux + (10, 11, 12)
42 | zoob = tuple(bar)
43 | quux = (7, 8, 9) + zoob
44 | spam = quux + (10, 11, 12)
| ^^^^^^^^^^^^^^^^^^^ RUF005
16 | spom = list(spam)
17 | eggs = spom + [13, 14, 15]
45 | spom = list(spam)
46 | eggs = spom + [13, 14, 15]
|
= help: Replace with `(*quux, 10, 11, 12)`
Suggested fix
10 10 | bar = [1, 2, 3] + foo
11 11 | zoob = tuple(bar)
12 12 | quux = (7, 8, 9) + zoob
13 |-spam = quux + (10, 11, 12)
13 |+spam = (*quux, 10, 11, 12)
14 14 | spom = list(spam)
15 15 | eggs = spom + [13, 14, 15]
16 16 | elatement = ("we all say", ) + yay()
39 39 | bar = [1, 2, 3] + foo
40 40 | zoob = tuple(bar)
41 41 | quux = (7, 8, 9) + zoob
42 |-spam = quux + (10, 11, 12)
42 |+spam = (*quux, 10, 11, 12)
43 43 | spom = list(spam)
44 44 | eggs = spom + [13, 14, 15]
45 45 | elatement = ("we all say",) + yay()
RUF005.py:15:8: RUF005 [*] Consider `[*spom, 13, 14, 15]` instead of concatenation
RUF005.py:44:8: RUF005 [*] Consider `[*spom, 13, 14, 15]` instead of concatenation
|
15 | spam = quux + (10, 11, 12)
16 | spom = list(spam)
17 | eggs = spom + [13, 14, 15]
44 | spam = quux + (10, 11, 12)
45 | spom = list(spam)
46 | eggs = spom + [13, 14, 15]
| ^^^^^^^^^^^^^^^^^^^ RUF005
18 | elatement = ("we all say", ) + yay()
19 | excitement = ("we all think", ) + Fun().yay()
47 | elatement = ("we all say",) + yay()
48 | excitement = ("we all think",) + Fun().yay()
|
= help: Replace with `[*spom, 13, 14, 15]`
Suggested fix
12 12 | quux = (7, 8, 9) + zoob
13 13 | spam = quux + (10, 11, 12)
14 14 | spom = list(spam)
15 |-eggs = spom + [13, 14, 15]
15 |+eggs = [*spom, 13, 14, 15]
16 16 | elatement = ("we all say", ) + yay()
17 17 | excitement = ("we all think", ) + Fun().yay()
18 18 | astonishment = ("we all feel", ) + Fun.words
41 41 | quux = (7, 8, 9) + zoob
42 42 | spam = quux + (10, 11, 12)
43 43 | spom = list(spam)
44 |-eggs = spom + [13, 14, 15]
44 |+eggs = [*spom, 13, 14, 15]
45 45 | elatement = ("we all say",) + yay()
46 46 | excitement = ("we all think",) + Fun().yay()
47 47 | astonishment = ("we all feel",) + Fun.words
RUF005.py:16:13: RUF005 [*] Consider `("we all say", *yay())` instead of concatenation
RUF005.py:45:13: RUF005 [*] Consider `("we all say", *yay())` instead of concatenation
|
16 | spom = list(spam)
17 | eggs = spom + [13, 14, 15]
18 | elatement = ("we all say", ) + yay()
| ^^^^^^^^^^^^^^^^^^^^^^^^ RUF005
19 | excitement = ("we all think", ) + Fun().yay()
20 | astonishment = ("we all feel", ) + Fun.words
45 | spom = list(spam)
46 | eggs = spom + [13, 14, 15]
47 | elatement = ("we all say",) + yay()
| ^^^^^^^^^^^^^^^^^^^^^^^ RUF005
48 | excitement = ("we all think",) + Fun().yay()
49 | astonishment = ("we all feel",) + Fun.words
|
= help: Replace with `("we all say", *yay())`
Suggested fix
13 13 | spam = quux + (10, 11, 12)
14 14 | spom = list(spam)
15 15 | eggs = spom + [13, 14, 15]
16 |-elatement = ("we all say", ) + yay()
16 |+elatement = ("we all say", *yay())
17 17 | excitement = ("we all think", ) + Fun().yay()
18 18 | astonishment = ("we all feel", ) + Fun.words
19 19 |
42 42 | spam = quux + (10, 11, 12)
43 43 | spom = list(spam)
44 44 | eggs = spom + [13, 14, 15]
45 |-elatement = ("we all say",) + yay()
45 |+elatement = ("we all say", *yay())
46 46 | excitement = ("we all think",) + Fun().yay()
47 47 | astonishment = ("we all feel",) + Fun.words
48 48 |
RUF005.py:17:14: RUF005 [*] Consider `("we all think", *Fun().yay())` instead of concatenation
RUF005.py:46:14: RUF005 [*] Consider `("we all think", *Fun().yay())` instead of concatenation
|
17 | eggs = spom + [13, 14, 15]
18 | elatement = ("we all say", ) + yay()
19 | excitement = ("we all think", ) + Fun().yay()
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ RUF005
20 | astonishment = ("we all feel", ) + Fun.words
46 | eggs = spom + [13, 14, 15]
47 | elatement = ("we all say",) + yay()
48 | excitement = ("we all think",) + Fun().yay()
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ RUF005
49 | astonishment = ("we all feel",) + Fun.words
|
= help: Replace with `("we all think", *Fun().yay())`
Suggested fix
14 14 | spom = list(spam)
15 15 | eggs = spom + [13, 14, 15]
16 16 | elatement = ("we all say", ) + yay()
17 |-excitement = ("we all think", ) + Fun().yay()
17 |+excitement = ("we all think", *Fun().yay())
18 18 | astonishment = ("we all feel", ) + Fun.words
19 19 |
20 20 | chain = ['a', 'b', 'c'] + eggs + list(('yes', 'no', 'pants') + zoob)
43 43 | spom = list(spam)
44 44 | eggs = spom + [13, 14, 15]
45 45 | elatement = ("we all say",) + yay()
46 |-excitement = ("we all think",) + Fun().yay()
46 |+excitement = ("we all think", *Fun().yay())
47 47 | astonishment = ("we all feel",) + Fun.words
48 48 |
49 49 | chain = ["a", "b", "c"] + eggs + list(("yes", "no", "pants") + zoob)
RUF005.py:18:16: RUF005 [*] Consider `("we all feel", *Fun.words)` instead of concatenation
RUF005.py:47:16: RUF005 [*] Consider `("we all feel", *Fun.words)` instead of concatenation
|
18 | elatement = ("we all say", ) + yay()
19 | excitement = ("we all think", ) + Fun().yay()
20 | astonishment = ("we all feel", ) + Fun.words
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ RUF005
21 |
22 | chain = ['a', 'b', 'c'] + eggs + list(('yes', 'no', 'pants') + zoob)
47 | elatement = ("we all say",) + yay()
48 | excitement = ("we all think",) + Fun().yay()
49 | astonishment = ("we all feel",) + Fun.words
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ RUF005
50 |
51 | chain = ["a", "b", "c"] + eggs + list(("yes", "no", "pants") + zoob)
|
= help: Replace with `("we all feel", *Fun.words)`
Suggested fix
15 15 | eggs = spom + [13, 14, 15]
16 16 | elatement = ("we all say", ) + yay()
17 17 | excitement = ("we all think", ) + Fun().yay()
18 |-astonishment = ("we all feel", ) + Fun.words
18 |+astonishment = ("we all feel", *Fun.words)
19 19 |
20 20 | chain = ['a', 'b', 'c'] + eggs + list(('yes', 'no', 'pants') + zoob)
21 21 |
44 44 | eggs = spom + [13, 14, 15]
45 45 | elatement = ("we all say",) + yay()
46 46 | excitement = ("we all think",) + Fun().yay()
47 |-astonishment = ("we all feel",) + Fun.words
47 |+astonishment = ("we all feel", *Fun.words)
48 48 |
49 49 | chain = ["a", "b", "c"] + eggs + list(("yes", "no", "pants") + zoob)
50 50 |
RUF005.py:20:9: RUF005 [*] Consider `["a", "b", "c", *eggs]` instead of concatenation
RUF005.py:49:9: RUF005 [*] Consider `["a", "b", "c", *eggs, *list(("yes", "no", "pants") + zoob)]` instead of concatenation
|
20 | astonishment = ("we all feel", ) + Fun.words
21 |
22 | chain = ['a', 'b', 'c'] + eggs + list(('yes', 'no', 'pants') + zoob)
| ^^^^^^^^^^^^^^^^^^^^^^ RUF005
23 |
24 | baz = () + zoob
49 | astonishment = ("we all feel",) + Fun.words
50 |
51 | chain = ["a", "b", "c"] + eggs + list(("yes", "no", "pants") + zoob)
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ RUF005
52 |
53 | baz = () + zoob
|
= help: Replace with `["a", "b", "c", *eggs]`
= help: Replace with `["a", "b", "c", *eggs, *list(("yes", "no", "pants") + zoob)]`
Suggested fix
17 17 | excitement = ("we all think", ) + Fun().yay()
18 18 | astonishment = ("we all feel", ) + Fun.words
19 19 |
20 |-chain = ['a', 'b', 'c'] + eggs + list(('yes', 'no', 'pants') + zoob)
20 |+chain = ["a", "b", "c", *eggs] + list(('yes', 'no', 'pants') + zoob)
21 21 |
22 22 | baz = () + zoob
23 23 |
46 46 | excitement = ("we all think",) + Fun().yay()
47 47 | astonishment = ("we all feel",) + Fun.words
48 48 |
49 |-chain = ["a", "b", "c"] + eggs + list(("yes", "no", "pants") + zoob)
49 |+chain = ["a", "b", "c", *eggs, *list(("yes", "no", "pants") + zoob)]
50 50 |
51 51 | baz = () + zoob
52 52 |
RUF005.py:20:39: RUF005 [*] Consider `("yes", "no", "pants", *zoob)` instead of concatenation
RUF005.py:49:39: RUF005 [*] Consider `("yes", "no", "pants", *zoob)` instead of concatenation
|
20 | astonishment = ("we all feel", ) + Fun.words
21 |
22 | chain = ['a', 'b', 'c'] + eggs + list(('yes', 'no', 'pants') + zoob)
49 | astonishment = ("we all feel",) + Fun.words
50 |
51 | chain = ["a", "b", "c"] + eggs + list(("yes", "no", "pants") + zoob)
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ RUF005
23 |
24 | baz = () + zoob
52 |
53 | baz = () + zoob
|
= help: Replace with `("yes", "no", "pants", *zoob)`
Suggested fix
17 17 | excitement = ("we all think", ) + Fun().yay()
18 18 | astonishment = ("we all feel", ) + Fun.words
19 19 |
20 |-chain = ['a', 'b', 'c'] + eggs + list(('yes', 'no', 'pants') + zoob)
20 |+chain = ['a', 'b', 'c'] + eggs + list(("yes", "no", "pants", *zoob))
21 21 |
22 22 | baz = () + zoob
23 23 |
46 46 | excitement = ("we all think",) + Fun().yay()
47 47 | astonishment = ("we all feel",) + Fun.words
48 48 |
49 |-chain = ["a", "b", "c"] + eggs + list(("yes", "no", "pants") + zoob)
49 |+chain = ["a", "b", "c"] + eggs + list(("yes", "no", "pants", *zoob))
50 50 |
51 51 | baz = () + zoob
52 52 |
RUF005.py:22:7: RUF005 [*] Consider `(*zoob,)` instead of concatenation
RUF005.py:51:7: RUF005 [*] Consider `(*zoob,)` instead of concatenation
|
22 | chain = ['a', 'b', 'c'] + eggs + list(('yes', 'no', 'pants') + zoob)
23 |
24 | baz = () + zoob
51 | chain = ["a", "b", "c"] + eggs + list(("yes", "no", "pants") + zoob)
52 |
53 | baz = () + zoob
| ^^^^^^^^^ RUF005
25 |
26 | first = [
54 |
55 | [] + foo + [
|
= help: Replace with `(*zoob,)`
Suggested fix
19 19 |
20 20 | chain = ['a', 'b', 'c'] + eggs + list(('yes', 'no', 'pants') + zoob)
21 21 |
22 |-baz = () + zoob
22 |+baz = (*zoob,)
23 23 |
24 24 | first = [
25 25 | # The order
48 48 |
49 49 | chain = ["a", "b", "c"] + eggs + list(("yes", "no", "pants") + zoob)
50 50 |
51 |-baz = () + zoob
51 |+baz = (*zoob,)
52 52 |
53 53 | [] + foo + [
54 54 | ]
RUF005.py:32:10: RUF005 Consider `[*first, 4, 5, 6]` instead of concatenation
RUF005.py:53:1: RUF005 [*] Consider `[*foo]` instead of concatenation
|
32 | # to preserve
33 | ]
34 | second = first + [
| __________^
35 | | # please
36 | | 4,
37 | | # don't
38 | | 5,
39 | | # touch
40 | | 6,
41 | | ]
53 | baz = () + zoob
54 |
55 | / [] + foo + [
56 | | ]
| |_^ RUF005
42 |
43 | [] + foo + [
|
= help: Replace with `[*first, 4, 5, 6]`
RUF005.py:41:1: RUF005 [*] Consider `[*foo]` instead of concatenation
|
41 | ]
42 |
43 | [] + foo + [
| ^^^^^^^^ RUF005
44 | ]
57 |
58 | pylint_call = [sys.executable, "-m", "pylint"] + args + [path]
|
= help: Replace with `[*foo]`
Suggested fix
38 38 | 6,
39 39 | ]
40 40 |
41 |-[] + foo + [
41 |+[*foo] + [
42 42 | ]
43 43 |
44 44 | [] + foo + [ # This will be preserved, but doesn't prevent the fix
50 50 |
51 51 | baz = () + zoob
52 52 |
53 |-[] + foo + [
54 |-]
53 |+[*foo]
55 54 |
56 55 | pylint_call = [sys.executable, "-m", "pylint"] + args + [path]
57 56 | pylint_call_tuple = (sys.executable, "-m", "pylint") + args + (path, path2)
RUF005.py:44:1: RUF005 [*] Consider `[*foo]` instead of concatenation
RUF005.py:56:15: RUF005 [*] Consider `[sys.executable, "-m", "pylint", *args, path]` instead of concatenation
|
44 | ]
45 |
46 | [] + foo + [ # This will be preserved, but doesn't prevent the fix
| ^^^^^^^^ RUF005
47 | ]
56 | ]
57 |
58 | pylint_call = [sys.executable, "-m", "pylint"] + args + [path]
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ RUF005
59 | pylint_call_tuple = (sys.executable, "-m", "pylint") + args + (path, path2)
60 | b = a + [2, 3] + [4]
|
= help: Replace with `[*foo]`
= help: Replace with `[sys.executable, "-m", "pylint", *args, path]`
Suggested fix
41 41 | [] + foo + [
42 42 | ]
43 43 |
44 |-[] + foo + [ # This will be preserved, but doesn't prevent the fix
44 |+[*foo] + [ # This will be preserved, but doesn't prevent the fix
45 45 | ]
46 46 |
47 47 | # Uses the non-preferred quote style, which should be retained.
53 53 | [] + foo + [
54 54 | ]
55 55 |
56 |-pylint_call = [sys.executable, "-m", "pylint"] + args + [path]
56 |+pylint_call = [sys.executable, "-m", "pylint", *args, path]
57 57 | pylint_call_tuple = (sys.executable, "-m", "pylint") + args + (path, path2)
58 58 | b = a + [2, 3] + [4]
59 59 |
RUF005.py:57:21: RUF005 [*] Consider `(sys.executable, "-m", "pylint", *args, path, path2)` instead of concatenation
|
57 | pylint_call = [sys.executable, "-m", "pylint"] + args + [path]
58 | pylint_call_tuple = (sys.executable, "-m", "pylint") + args + (path, path2)
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ RUF005
59 | b = a + [2, 3] + [4]
|
= help: Replace with `(sys.executable, "-m", "pylint", *args, path, path2)`
Suggested fix
54 54 | ]
55 55 |
56 56 | pylint_call = [sys.executable, "-m", "pylint"] + args + [path]
57 |-pylint_call_tuple = (sys.executable, "-m", "pylint") + args + (path, path2)
57 |+pylint_call_tuple = (sys.executable, "-m", "pylint", *args, path, path2)
58 58 | b = a + [2, 3] + [4]
59 59 |
60 60 | # Uses the non-preferred quote style, which should be retained.
RUF005.py:58:5: RUF005 [*] Consider `[*a, 2, 3, 4]` instead of concatenation
|
58 | pylint_call = [sys.executable, "-m", "pylint"] + args + [path]
59 | pylint_call_tuple = (sys.executable, "-m", "pylint") + args + (path, path2)
60 | b = a + [2, 3] + [4]
| ^^^^^^^^^^^^^^^^ RUF005
61 |
62 | # Uses the non-preferred quote style, which should be retained.
|
= help: Replace with `[*a, 2, 3, 4]`
Suggested fix
55 55 |
56 56 | pylint_call = [sys.executable, "-m", "pylint"] + args + [path]
57 57 | pylint_call_tuple = (sys.executable, "-m", "pylint") + args + (path, path2)
58 |-b = a + [2, 3] + [4]
58 |+b = [*a, 2, 3, 4]
59 59 |
60 60 | # Uses the non-preferred quote style, which should be retained.
61 61 | f"{a() + ['b']}"
RUF005.py:61:4: RUF005 [*] Consider `[*a(), 'b']` instead of concatenation
|
61 | # Uses the non-preferred quote style, which should be retained.
62 | f"{a() + ['b']}"
| ^^^^^^^^^^^ RUF005
63 |
64 | ###
|
= help: Replace with `[*a(), 'b']`
Suggested fix
58 58 | b = a + [2, 3] + [4]
59 59 |
60 60 | # Uses the non-preferred quote style, which should be retained.
61 |-f"{a() + ['b']}"
61 |+f"{[*a(), 'b']}"
62 62 |
63 63 | ###
64 64 | # Non-errors.