Skip to content

Commit

Permalink
Use set bracket replacement for iteration-over-set (#8001)
Browse files Browse the repository at this point in the history
  • Loading branch information
charliermarsh authored Oct 17, 2023
1 parent 73049df commit cb6d74c
Show file tree
Hide file tree
Showing 3 changed files with 124 additions and 73 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,14 @@
for item in {"apples", "lemons", "water"}: # flags in-line set literals
print(f"I like {item}.")

for item in {1,}:
print(f"I can count to {item}!")

for item in {
"apples", "lemons", "water"
}: # flags in-line set literals
print(f"I like {item}.")

numbers_list = [i for i in {1, 2, 3}] # flags sets in list comprehensions

numbers_set = {i for i in {1, 2, 3}} # flags sets in set comprehensions
Expand Down
25 changes: 11 additions & 14 deletions crates/ruff_linter/src/rules/pylint/rules/iteration_over_set.rs
Original file line number Diff line number Diff line change
@@ -1,9 +1,7 @@
use ast::ExprContext;
use ruff_python_ast::{self as ast, Expr};

use ruff_diagnostics::{AlwaysFixableViolation, Diagnostic, Edit, Fix};
use ruff_macros::{derive_message_formats, violation};
use ruff_text_size::{Ranged, TextRange};
use ruff_python_ast::{self as ast, Expr};
use ruff_text_size::Ranged;

use crate::checkers::ast::Checker;

Expand Down Expand Up @@ -38,7 +36,7 @@ impl AlwaysFixableViolation for IterationOverSet {
}

fn fix_title(&self) -> String {
format!("Use a sequence type instead of a `set` when iterating over values")
format!("Convert to `tuple`")
}
}

Expand All @@ -54,15 +52,14 @@ pub(crate) fn iteration_over_set(checker: &mut Checker, expr: &Expr) {

let mut diagnostic = Diagnostic::new(IterationOverSet, expr.range());

let tuple = checker.generator().expr(&Expr::Tuple(ast::ExprTuple {
elts: elts.clone(),
ctx: ExprContext::Store,
range: TextRange::default(),
}));
diagnostic.set_fix(Fix::safe_edit(Edit::range_replacement(
format!("({tuple})"),
expr.range(),
)));
let tuple = if let [elt] = elts.as_slice() {
let elt = checker.locator().slice(elt);
format!("({elt},)")
} else {
let set = checker.locator().slice(expr);
format!("({})", &set[1..set.len() - 1])
};
diagnostic.set_fix(Fix::safe_edit(Edit::range_replacement(tuple, expr.range())));

checker.diagnostics.push(diagnostic);
}
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ iteration_over_set.py:3:13: PLC0208 [*] Use a sequence type instead of a `set` w
| ^^^ PLC0208
4 | print(f"I can count to {item}!")
|
= help: Use a sequence type instead of a `set` when iterating over values
= help: Convert to `tuple`

Fix
1 1 | # Errors
Expand All @@ -28,7 +28,7 @@ iteration_over_set.py:6:13: PLC0208 [*] Use a sequence type instead of a `set` w
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ PLC0208
7 | print(f"I like {item}.")
|
= help: Use a sequence type instead of a `set` when iterating over values
= help: Convert to `tuple`

Fix
3 3 | for item in {1}:
Expand All @@ -38,90 +38,136 @@ iteration_over_set.py:6:13: PLC0208 [*] Use a sequence type instead of a `set` w
6 |+for item in ("apples", "lemons", "water"): # flags in-line set literals
7 7 | print(f"I like {item}.")
8 8 |
9 9 | numbers_list = [i for i in {1, 2, 3}] # flags sets in list comprehensions
9 9 | for item in {1,}:

iteration_over_set.py:9:28: PLC0208 [*] Use a sequence type instead of a `set` when iterating over values
iteration_over_set.py:9:13: PLC0208 [*] Use a sequence type instead of a `set` when iterating over values
|
7 | print(f"I like {item}.")
8 |
9 | numbers_list = [i for i in {1, 2, 3}] # flags sets in list comprehensions
| ^^^^^^^^^ PLC0208
10 |
11 | numbers_set = {i for i in {1, 2, 3}} # flags sets in set comprehensions
9 | for item in {1,}:
| ^^^^ PLC0208
10 | print(f"I can count to {item}!")
|
= help: Use a sequence type instead of a `set` when iterating over values
= help: Convert to `tuple`

Fix
6 6 | for item in {"apples", "lemons", "water"}: # flags in-line set literals
7 7 | print(f"I like {item}.")
8 8 |
9 |-numbers_list = [i for i in {1, 2, 3}] # flags sets in list comprehensions
9 |+numbers_list = [i for i in (1, 2, 3)] # flags sets in list comprehensions
10 10 |
11 11 | numbers_set = {i for i in {1, 2, 3}} # flags sets in set comprehensions
12 12 |
9 |-for item in {1,}:
9 |+for item in (1,):
10 10 | print(f"I can count to {item}!")
11 11 |
12 12 | for item in {

iteration_over_set.py:11:27: PLC0208 [*] Use a sequence type instead of a `set` when iterating over values
iteration_over_set.py:12:13: PLC0208 [*] Use a sequence type instead of a `set` when iterating over values
|
9 | numbers_list = [i for i in {1, 2, 3}] # flags sets in list comprehensions
10 |
11 | numbers_set = {i for i in {1, 2, 3}} # flags sets in set comprehensions
| ^^^^^^^^^ PLC0208
12 |
13 | numbers_dict = {str(i): i for i in {1, 2, 3}} # flags sets in dict comprehensions
10 | print(f"I can count to {item}!")
11 |
12 | for item in {
| _____________^
13 | | "apples", "lemons", "water"
14 | | }: # flags in-line set literals
| |_^ PLC0208
15 | print(f"I like {item}.")
|
= help: Use a sequence type instead of a `set` when iterating over values
= help: Convert to `tuple`

ℹ Fix
8 8 |
9 9 | numbers_list = [i for i in {1, 2, 3}] # flags sets in list comprehensions
10 10 |
11 |-numbers_set = {i for i in {1, 2, 3}} # flags sets in set comprehensions
11 |+numbers_set = {i for i in (1, 2, 3)} # flags sets in set comprehensions
12 12 |
13 13 | numbers_dict = {str(i): i for i in {1, 2, 3}} # flags sets in dict comprehensions
14 14 |

iteration_over_set.py:13:36: PLC0208 [*] Use a sequence type instead of a `set` when iterating over values
9 9 | for item in {1,}:
10 10 | print(f"I can count to {item}!")
11 11 |
12 |-for item in {
12 |+for item in (
13 13 | "apples", "lemons", "water"
14 |-}: # flags in-line set literals
14 |+): # flags in-line set literals
15 15 | print(f"I like {item}.")
16 16 |
17 17 | numbers_list = [i for i in {1, 2, 3}] # flags sets in list comprehensions

iteration_over_set.py:17:28: PLC0208 [*] Use a sequence type instead of a `set` when iterating over values
|
11 | numbers_set = {i for i in {1, 2, 3}} # flags sets in set comprehensions
12 |
13 | numbers_dict = {str(i): i for i in {1, 2, 3}} # flags sets in dict comprehensions
| ^^^^^^^^^ PLC0208
14 |
15 | numbers_gen = (i for i in {1, 2, 3}) # flags sets in generator expressions
15 | print(f"I like {item}.")
16 |
17 | numbers_list = [i for i in {1, 2, 3}] # flags sets in list comprehensions
| ^^^^^^^^^ PLC0208
18 |
19 | numbers_set = {i for i in {1, 2, 3}} # flags sets in set comprehensions
|
= help: Use a sequence type instead of a `set` when iterating over values
= help: Convert to `tuple`

ℹ Fix
10 10 |
11 11 | numbers_set = {i for i in {1, 2, 3}} # flags sets in set comprehensions
12 12 |
13 |-numbers_dict = {str(i): i for i in {1, 2, 3}} # flags sets in dict comprehensions
13 |+numbers_dict = {str(i): i for i in (1, 2, 3)} # flags sets in dict comprehensions
14 14 |
15 15 | numbers_gen = (i for i in {1, 2, 3}) # flags sets in generator expressions
14 14 | }: # flags in-line set literals
15 15 | print(f"I like {item}.")
16 16 |
17 |-numbers_list = [i for i in {1, 2, 3}] # flags sets in list comprehensions
17 |+numbers_list = [i for i in (1, 2, 3)] # flags sets in list comprehensions
18 18 |
19 19 | numbers_set = {i for i in {1, 2, 3}} # flags sets in set comprehensions
20 20 |

iteration_over_set.py:15:27: PLC0208 [*] Use a sequence type instead of a `set` when iterating over values
iteration_over_set.py:19:27: PLC0208 [*] Use a sequence type instead of a `set` when iterating over values
|
13 | numbers_dict = {str(i): i for i in {1, 2, 3}} # flags sets in dict comprehensions
14 |
15 | numbers_gen = (i for i in {1, 2, 3}) # flags sets in generator expressions
17 | numbers_list = [i for i in {1, 2, 3}] # flags sets in list comprehensions
18 |
19 | numbers_set = {i for i in {1, 2, 3}} # flags sets in set comprehensions
| ^^^^^^^^^ PLC0208
16 |
17 | # Non-errors
20 |
21 | numbers_dict = {str(i): i for i in {1, 2, 3}} # flags sets in dict comprehensions
|
= help: Use a sequence type instead of a `set` when iterating over values
= help: Convert to `tuple`

Fix
12 12 |
13 13 | numbers_dict = {str(i): i for i in {1, 2, 3}} # flags sets in dict comprehensions
14 14 |
15 |-numbers_gen = (i for i in {1, 2, 3}) # flags sets in generator expressions
15 |+numbers_gen = (i for i in (1, 2, 3)) # flags sets in generator expressions
16 16 |
17 17 | # Non-errors
17 17 | numbers_list = [i for i in {1, 2, 3}] # flags sets in list comprehensions
18 18 |
19 |-numbers_set = {i for i in {1, 2, 3}} # flags sets in set comprehensions
19 |+numbers_set = {i for i in (1, 2, 3)} # flags sets in set comprehensions
20 20 |
21 21 | numbers_dict = {str(i): i for i in {1, 2, 3}} # flags sets in dict comprehensions
22 22 |

iteration_over_set.py:21:36: PLC0208 [*] Use a sequence type instead of a `set` when iterating over values
|
19 | numbers_set = {i for i in {1, 2, 3}} # flags sets in set comprehensions
20 |
21 | numbers_dict = {str(i): i for i in {1, 2, 3}} # flags sets in dict comprehensions
| ^^^^^^^^^ PLC0208
22 |
23 | numbers_gen = (i for i in {1, 2, 3}) # flags sets in generator expressions
|
= help: Convert to `tuple`

Fix
18 18 |
19 19 | numbers_set = {i for i in {1, 2, 3}} # flags sets in set comprehensions
20 20 |
21 |-numbers_dict = {str(i): i for i in {1, 2, 3}} # flags sets in dict comprehensions
21 |+numbers_dict = {str(i): i for i in (1, 2, 3)} # flags sets in dict comprehensions
22 22 |
23 23 | numbers_gen = (i for i in {1, 2, 3}) # flags sets in generator expressions
24 24 |

iteration_over_set.py:23:27: PLC0208 [*] Use a sequence type instead of a `set` when iterating over values
|
21 | numbers_dict = {str(i): i for i in {1, 2, 3}} # flags sets in dict comprehensions
22 |
23 | numbers_gen = (i for i in {1, 2, 3}) # flags sets in generator expressions
| ^^^^^^^^^ PLC0208
24 |
25 | # Non-errors
|
= help: Convert to `tuple`

Fix
20 20 |
21 21 | numbers_dict = {str(i): i for i in {1, 2, 3}} # flags sets in dict comprehensions
22 22 |
23 |-numbers_gen = (i for i in {1, 2, 3}) # flags sets in generator expressions
23 |+numbers_gen = (i for i in (1, 2, 3)) # flags sets in generator expressions
24 24 |
25 25 | # Non-errors
26 26 |


0 comments on commit cb6d74c

Please sign in to comment.