-
Notifications
You must be signed in to change notification settings - Fork 1.2k
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Add Pylint rule
C0208
(use-sequence-for-iteration
) as PLC0208
(…
…`iteration-over-set`) (#4706)
- Loading branch information
Showing
9 changed files
with
197 additions
and
0 deletions.
There are no files selected for viewing
38 changes: 38 additions & 0 deletions
38
crates/ruff/resources/test/fixtures/pylint/iteration_over_set.py
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,38 @@ | ||
# Errors | ||
|
||
for item in {"apples", "lemons", "water"}: # flags in-line set literals | ||
print(f"I like {item}.") | ||
|
||
for item in set(("apples", "lemons", "water")): # flags set() calls | ||
print(f"I like {item}.") | ||
|
||
for number in {i for i in range(10)}: # flags set comprehensions | ||
print(number) | ||
|
||
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 | ||
|
||
numbers_dict = {str(i): i for i in {1, 2, 3}} # flags sets in dict comprehensions | ||
|
||
numbers_gen = (i for i in {1, 2, 3}) # flags sets in generator expressions | ||
|
||
# Non-errors | ||
|
||
items = {"apples", "lemons", "water"} | ||
for item in items: # only complains about in-line sets (as per Pylint) | ||
print(f"I like {item}.") | ||
|
||
for item in ["apples", "lemons", "water"]: # lists are fine | ||
print(f"I like {item}.") | ||
|
||
for item in ("apples", "lemons", "water"): # tuples are fine | ||
print(f"I like {item}.") | ||
|
||
numbers_list = [i for i in [1, 2, 3]] # lists in comprehensions are fine | ||
|
||
numbers_set = {i for i in (1, 2, 3)} # tuples in comprehensions are fine | ||
|
||
numbers_dict = {str(i): i for i in [1, 2, 3]} # lists in dict comprehensions are fine | ||
|
||
numbers_gen = (i for i in (1, 2, 3)) # tuples in generator expressions are fine |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,62 @@ | ||
use rustpython_parser::ast::{Expr, ExprName, Ranged}; | ||
|
||
use ruff_diagnostics::{Diagnostic, Violation}; | ||
use ruff_macros::{derive_message_formats, violation}; | ||
|
||
use crate::checkers::ast::Checker; | ||
|
||
/// ## What it does | ||
/// Checks for iterations over `set` literals and comprehensions. | ||
/// | ||
/// ## Why is this bad? | ||
/// Iterating over a `set` is less efficient than iterating over a sequence | ||
/// type, like `list` or `tuple`. | ||
/// | ||
/// ## Example | ||
/// ```python | ||
/// for number in {1, 2, 3}: | ||
/// ... | ||
/// ``` | ||
/// | ||
/// Use instead: | ||
/// ```python | ||
/// for number in (1, 2, 3): | ||
/// ... | ||
/// ``` | ||
/// | ||
/// ## References | ||
/// - [Python documentation: `set`](https://docs.python.org/3/library/stdtypes.html#set) | ||
#[violation] | ||
pub struct IterationOverSet; | ||
|
||
impl Violation for IterationOverSet { | ||
#[derive_message_formats] | ||
fn message(&self) -> String { | ||
format!("Use a sequence type instead of a `set` when iterating over values") | ||
} | ||
} | ||
|
||
/// PLC0208 | ||
pub(crate) fn iteration_over_set(checker: &mut Checker, expr: &Expr) { | ||
let is_set = match expr { | ||
// Ex) `for i in {1, 2, 3}` | ||
Expr::Set(_) => true, | ||
// Ex)` for i in {n for n in range(1, 4)}` | ||
Expr::SetComp(_) => true, | ||
// Ex) `for i in set(1, 2, 3)` | ||
Expr::Call(call) => { | ||
if let Expr::Name(ExprName { id, .. }) = call.func.as_ref() { | ||
id.as_str() == "set" && checker.semantic_model().is_builtin("set") | ||
} else { | ||
false | ||
} | ||
} | ||
_ => false, | ||
}; | ||
|
||
if is_set { | ||
checker | ||
.diagnostics | ||
.push(Diagnostic::new(IterationOverSet, expr.range())); | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
71 changes: 71 additions & 0 deletions
71
...src/rules/pylint/snapshots/ruff__rules__pylint__tests__PLC0208_iteration_over_set.py.snap
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,71 @@ | ||
--- | ||
source: crates/ruff/src/rules/pylint/mod.rs | ||
--- | ||
iteration_over_set.py:3:13: PLC0208 Use a sequence type instead of a `set` when iterating over values | ||
| | ||
3 | # Errors | ||
4 | | ||
5 | for item in {"apples", "lemons", "water"}: # flags in-line set literals | ||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ PLC0208 | ||
6 | print(f"I like {item}.") | ||
| | ||
|
||
iteration_over_set.py:6:13: PLC0208 Use a sequence type instead of a `set` when iterating over values | ||
| | ||
6 | print(f"I like {item}.") | ||
7 | | ||
8 | for item in set(("apples", "lemons", "water")): # flags set() calls | ||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ PLC0208 | ||
9 | print(f"I like {item}.") | ||
| | ||
|
||
iteration_over_set.py:9:15: PLC0208 Use a sequence type instead of a `set` when iterating over values | ||
| | ||
9 | print(f"I like {item}.") | ||
10 | | ||
11 | for number in {i for i in range(10)}: # flags set comprehensions | ||
| ^^^^^^^^^^^^^^^^^^^^^^ PLC0208 | ||
12 | print(number) | ||
| | ||
|
||
iteration_over_set.py:12:28: PLC0208 Use a sequence type instead of a `set` when iterating over values | ||
| | ||
12 | print(number) | ||
13 | | ||
14 | numbers_list = [i for i in {1, 2, 3}] # flags sets in list comprehensions | ||
| ^^^^^^^^^ PLC0208 | ||
15 | | ||
16 | numbers_set = {i for i in {1, 2, 3}} # flags sets in set comprehensions | ||
| | ||
|
||
iteration_over_set.py:14:27: PLC0208 Use a sequence type instead of a `set` when iterating over values | ||
| | ||
14 | numbers_list = [i for i in {1, 2, 3}] # flags sets in list comprehensions | ||
15 | | ||
16 | numbers_set = {i for i in {1, 2, 3}} # flags sets in set comprehensions | ||
| ^^^^^^^^^ PLC0208 | ||
17 | | ||
18 | numbers_dict = {str(i): i for i in {1, 2, 3}} # flags sets in dict comprehensions | ||
| | ||
|
||
iteration_over_set.py:16:36: PLC0208 Use a sequence type instead of a `set` when iterating over values | ||
| | ||
16 | numbers_set = {i for i in {1, 2, 3}} # flags sets in set comprehensions | ||
17 | | ||
18 | numbers_dict = {str(i): i for i in {1, 2, 3}} # flags sets in dict comprehensions | ||
| ^^^^^^^^^ PLC0208 | ||
19 | | ||
20 | numbers_gen = (i for i in {1, 2, 3}) # flags sets in generator expressions | ||
| | ||
|
||
iteration_over_set.py:18:27: PLC0208 Use a sequence type instead of a `set` when iterating over values | ||
| | ||
18 | numbers_dict = {str(i): i for i in {1, 2, 3}} # flags sets in dict comprehensions | ||
19 | | ||
20 | numbers_gen = (i for i in {1, 2, 3}) # flags sets in generator expressions | ||
| ^^^^^^^^^ PLC0208 | ||
21 | | ||
22 | # Non-errors | ||
| | ||
|
||
|
Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.
Oops, something went wrong.