Re-code unnecessary-dict-comprehension-for-iterable (RUF025) as C420 (#12533)

Closes https://github.com/astral-sh/ruff/issues/12110.
This commit is contained in:
Charlie Marsh 2024-08-12 05:27:05 -04:00 committed by Micha Reiser
parent fa2f3f9f2f
commit 78a7ac0722
11 changed files with 36 additions and 33 deletions

View file

@ -1488,7 +1488,9 @@ pub(crate) fn expression(expr: &Expr, checker: &mut Checker) {
} }
if checker.enabled(Rule::UnnecessaryDictComprehensionForIterable) { if checker.enabled(Rule::UnnecessaryDictComprehensionForIterable) {
ruff::rules::unnecessary_dict_comprehension_for_iterable(checker, dict_comp); flake8_comprehensions::rules::unnecessary_dict_comprehension_for_iterable(
checker, dict_comp,
);
} }
if checker.enabled(Rule::FunctionUsesLoopVariable) { if checker.enabled(Rule::FunctionUsesLoopVariable) {

View file

@ -4,12 +4,12 @@
/// `--select`. For pylint this is e.g. C0414 and E0118 but also C and E01. /// `--select`. For pylint this is e.g. C0414 and E0118 but also C and E01.
use std::fmt::Formatter; use std::fmt::Formatter;
use strum_macros::{AsRefStr, EnumIter};
use crate::registry::{AsRule, Linter}; use crate::registry::{AsRule, Linter};
use crate::rule_selector::is_single_rule_selector; use crate::rule_selector::is_single_rule_selector;
use crate::rules; use crate::rules;
use strum_macros::{AsRefStr, EnumIter};
#[derive(PartialEq, Eq, PartialOrd, Ord)] #[derive(PartialEq, Eq, PartialOrd, Ord)]
pub struct NoqaCode(&'static str, &'static str); pub struct NoqaCode(&'static str, &'static str);
@ -378,6 +378,7 @@ pub fn code_to_rule(linter: Linter, code: &str) -> Option<(RuleGroup, Rule)> {
(Flake8Comprehensions, "17") => (RuleGroup::Stable, rules::flake8_comprehensions::rules::UnnecessaryMap), (Flake8Comprehensions, "17") => (RuleGroup::Stable, rules::flake8_comprehensions::rules::UnnecessaryMap),
(Flake8Comprehensions, "18") => (RuleGroup::Stable, rules::flake8_comprehensions::rules::UnnecessaryLiteralWithinDictCall), (Flake8Comprehensions, "18") => (RuleGroup::Stable, rules::flake8_comprehensions::rules::UnnecessaryLiteralWithinDictCall),
(Flake8Comprehensions, "19") => (RuleGroup::Stable, rules::flake8_comprehensions::rules::UnnecessaryComprehensionInCall), (Flake8Comprehensions, "19") => (RuleGroup::Stable, rules::flake8_comprehensions::rules::UnnecessaryComprehensionInCall),
(Flake8Comprehensions, "20") => (RuleGroup::Preview, rules::flake8_comprehensions::rules::UnnecessaryDictComprehensionForIterable),
// flake8-debugger // flake8-debugger
(Flake8Debugger, "0") => (RuleGroup::Stable, rules::flake8_debugger::rules::Debugger), (Flake8Debugger, "0") => (RuleGroup::Stable, rules::flake8_debugger::rules::Debugger),
@ -951,7 +952,6 @@ pub fn code_to_rule(linter: Linter, code: &str) -> Option<(RuleGroup, Rule)> {
(Ruff, "022") => (RuleGroup::Preview, rules::ruff::rules::UnsortedDunderAll), (Ruff, "022") => (RuleGroup::Preview, rules::ruff::rules::UnsortedDunderAll),
(Ruff, "023") => (RuleGroup::Preview, rules::ruff::rules::UnsortedDunderSlots), (Ruff, "023") => (RuleGroup::Preview, rules::ruff::rules::UnsortedDunderSlots),
(Ruff, "024") => (RuleGroup::Stable, rules::ruff::rules::MutableFromkeysValue), (Ruff, "024") => (RuleGroup::Stable, rules::ruff::rules::MutableFromkeysValue),
(Ruff, "025") => (RuleGroup::Preview, rules::ruff::rules::UnnecessaryDictComprehensionForIterable),
(Ruff, "026") => (RuleGroup::Stable, rules::ruff::rules::DefaultFactoryKwarg), (Ruff, "026") => (RuleGroup::Stable, rules::ruff::rules::DefaultFactoryKwarg),
(Ruff, "027") => (RuleGroup::Preview, rules::ruff::rules::MissingFStringSyntax), (Ruff, "027") => (RuleGroup::Preview, rules::ruff::rules::MissingFStringSyntax),
(Ruff, "028") => (RuleGroup::Preview, rules::ruff::rules::InvalidFormatterSuppressionComment), (Ruff, "028") => (RuleGroup::Preview, rules::ruff::rules::InvalidFormatterSuppressionComment),

View file

@ -123,5 +123,7 @@ static REDIRECTS: Lazy<HashMap<&'static str, &'static str>> = Lazy::new(|| {
("RUF96", "RUF95"), ("RUF96", "RUF95"),
// See: https://github.com/astral-sh/ruff/issues/10791 // See: https://github.com/astral-sh/ruff/issues/10791
("PLW0117", "PLW0177"), ("PLW0117", "PLW0177"),
// See: https://github.com/astral-sh/ruff/issues/12110
("RUF025", "C420"),
]) ])
}); });

View file

@ -21,6 +21,7 @@ mod tests {
#[test_case(Rule::UnnecessaryComprehension, Path::new("C416.py"))] #[test_case(Rule::UnnecessaryComprehension, Path::new("C416.py"))]
#[test_case(Rule::UnnecessaryComprehensionInCall, Path::new("C419.py"))] #[test_case(Rule::UnnecessaryComprehensionInCall, Path::new("C419.py"))]
#[test_case(Rule::UnnecessaryComprehensionInCall, Path::new("C419_2.py"))] #[test_case(Rule::UnnecessaryComprehensionInCall, Path::new("C419_2.py"))]
#[test_case(Rule::UnnecessaryDictComprehensionForIterable, Path::new("C420.py"))]
#[test_case(Rule::UnnecessaryDoubleCastOrProcess, Path::new("C414.py"))] #[test_case(Rule::UnnecessaryDoubleCastOrProcess, Path::new("C414.py"))]
#[test_case(Rule::UnnecessaryGeneratorDict, Path::new("C402.py"))] #[test_case(Rule::UnnecessaryGeneratorDict, Path::new("C402.py"))]
#[test_case(Rule::UnnecessaryGeneratorList, Path::new("C400.py"))] #[test_case(Rule::UnnecessaryGeneratorList, Path::new("C400.py"))]

View file

@ -2,6 +2,7 @@ pub(crate) use unnecessary_call_around_sorted::*;
pub(crate) use unnecessary_collection_call::*; pub(crate) use unnecessary_collection_call::*;
pub(crate) use unnecessary_comprehension::*; pub(crate) use unnecessary_comprehension::*;
pub(crate) use unnecessary_comprehension_in_call::*; pub(crate) use unnecessary_comprehension_in_call::*;
pub(crate) use unnecessary_dict_comprehension_for_iterable::*;
pub(crate) use unnecessary_double_cast_or_process::*; pub(crate) use unnecessary_double_cast_or_process::*;
pub(crate) use unnecessary_generator_dict::*; pub(crate) use unnecessary_generator_dict::*;
pub(crate) use unnecessary_generator_list::*; pub(crate) use unnecessary_generator_list::*;
@ -22,6 +23,7 @@ mod unnecessary_call_around_sorted;
mod unnecessary_collection_call; mod unnecessary_collection_call;
mod unnecessary_comprehension; mod unnecessary_comprehension;
mod unnecessary_comprehension_in_call; mod unnecessary_comprehension_in_call;
mod unnecessary_dict_comprehension_for_iterable;
mod unnecessary_double_cast_or_process; mod unnecessary_double_cast_or_process;
mod unnecessary_generator_dict; mod unnecessary_generator_dict;
mod unnecessary_generator_list; mod unnecessary_generator_list;

View file

@ -1,12 +1,12 @@
--- ---
source: crates/ruff_linter/src/rules/ruff/mod.rs source: crates/ruff_linter/src/rules/flake8_comprehensions/mod.rs
--- ---
RUF025.py:6:5: RUF025 [*] Unnecessary dict comprehension for iterable; use `dict.fromkeys` instead C420.py:6:5: C420 [*] Unnecessary dict comprehension for iterable; use `dict.fromkeys` instead
| |
4 | def func(): 4 | def func():
5 | numbers = [1, 2, 3] 5 | numbers = [1, 2, 3]
6 | {n: None for n in numbers} # RUF025 6 | {n: None for n in numbers} # RUF025
| ^^^^^^^^^^^^^^^^^^^^^^^^^^ RUF025 | ^^^^^^^^^^^^^^^^^^^^^^^^^^ C420
| |
= help: Replace with `dict.fromkeys(iterable, value)`) = help: Replace with `dict.fromkeys(iterable, value)`)
@ -20,11 +20,11 @@ RUF025.py:6:5: RUF025 [*] Unnecessary dict comprehension for iterable; use `dict
8 8 | 8 8 |
9 9 | def func(): 9 9 | def func():
RUF025.py:10:23: RUF025 [*] Unnecessary dict comprehension for iterable; use `dict.fromkeys` instead C420.py:10:23: C420 [*] Unnecessary dict comprehension for iterable; use `dict.fromkeys` instead
| |
9 | def func(): 9 | def func():
10 | for key, value in {n: 1 for n in [1, 2, 3]}.items(): # RUF025 10 | for key, value in {n: 1 for n in [1, 2, 3]}.items(): # RUF025
| ^^^^^^^^^^^^^^^^^^^^^^^^^ RUF025 | ^^^^^^^^^^^^^^^^^^^^^^^^^ C420
11 | pass 11 | pass
| |
= help: Replace with `dict.fromkeys(iterable)`) = help: Replace with `dict.fromkeys(iterable)`)
@ -39,11 +39,11 @@ RUF025.py:10:23: RUF025 [*] Unnecessary dict comprehension for iterable; use `di
12 12 | 12 12 |
13 13 | 13 13 |
RUF025.py:15:5: RUF025 [*] Unnecessary dict comprehension for iterable; use `dict.fromkeys` instead C420.py:15:5: C420 [*] Unnecessary dict comprehension for iterable; use `dict.fromkeys` instead
| |
14 | def func(): 14 | def func():
15 | {n: 1.1 for n in [1, 2, 3]} # RUF025 15 | {n: 1.1 for n in [1, 2, 3]} # RUF025
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^ RUF025 | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ C420
| |
= help: Replace with `dict.fromkeys(iterable)`) = help: Replace with `dict.fromkeys(iterable)`)
@ -57,12 +57,12 @@ RUF025.py:15:5: RUF025 [*] Unnecessary dict comprehension for iterable; use `dic
17 17 | 17 17 |
18 18 | def func(): 18 18 | def func():
RUF025.py:26:7: RUF025 [*] Unnecessary dict comprehension for iterable; use `dict.fromkeys` instead C420.py:26:7: C420 [*] Unnecessary dict comprehension for iterable; use `dict.fromkeys` instead
| |
24 | return data 24 | return data
25 | 25 |
26 | f({c: "a" for c in "12345"}) # RUF025 26 | f({c: "a" for c in "12345"}) # RUF025
| ^^^^^^^^^^^^^^^^^^^^^^^^^ RUF025 | ^^^^^^^^^^^^^^^^^^^^^^^^^ C420
| |
= help: Replace with `dict.fromkeys(iterable)`) = help: Replace with `dict.fromkeys(iterable)`)
@ -76,11 +76,11 @@ RUF025.py:26:7: RUF025 [*] Unnecessary dict comprehension for iterable; use `dic
28 28 | 28 28 |
29 29 | def func(): 29 29 | def func():
RUF025.py:30:5: RUF025 [*] Unnecessary dict comprehension for iterable; use `dict.fromkeys` instead C420.py:30:5: C420 [*] Unnecessary dict comprehension for iterable; use `dict.fromkeys` instead
| |
29 | def func(): 29 | def func():
30 | {n: True for n in [1, 2, 2]} # RUF025 30 | {n: True for n in [1, 2, 2]} # RUF025
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ RUF025 | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ C420
| |
= help: Replace with `dict.fromkeys(iterable)`) = help: Replace with `dict.fromkeys(iterable)`)
@ -94,11 +94,11 @@ RUF025.py:30:5: RUF025 [*] Unnecessary dict comprehension for iterable; use `dic
32 32 | 32 32 |
33 33 | def func(): 33 33 | def func():
RUF025.py:34:5: RUF025 [*] Unnecessary dict comprehension for iterable; use `dict.fromkeys` instead C420.py:34:5: C420 [*] Unnecessary dict comprehension for iterable; use `dict.fromkeys` instead
| |
33 | def func(): 33 | def func():
34 | {n: b"hello" for n in (1, 2, 2)} # RUF025 34 | {n: b"hello" for n in (1, 2, 2)} # RUF025
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ RUF025 | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ C420
| |
= help: Replace with `dict.fromkeys(iterable)`) = help: Replace with `dict.fromkeys(iterable)`)
@ -112,11 +112,11 @@ RUF025.py:34:5: RUF025 [*] Unnecessary dict comprehension for iterable; use `dic
36 36 | 36 36 |
37 37 | def func(): 37 37 | def func():
RUF025.py:38:5: RUF025 [*] Unnecessary dict comprehension for iterable; use `dict.fromkeys` instead C420.py:38:5: C420 [*] Unnecessary dict comprehension for iterable; use `dict.fromkeys` instead
| |
37 | def func(): 37 | def func():
38 | {n: ... for n in [1, 2, 3]} # RUF025 38 | {n: ... for n in [1, 2, 3]} # RUF025
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^ RUF025 | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ C420
| |
= help: Replace with `dict.fromkeys(iterable)`) = help: Replace with `dict.fromkeys(iterable)`)
@ -130,11 +130,11 @@ RUF025.py:38:5: RUF025 [*] Unnecessary dict comprehension for iterable; use `dic
40 40 | 40 40 |
41 41 | def func(): 41 41 | def func():
RUF025.py:42:5: RUF025 [*] Unnecessary dict comprehension for iterable; use `dict.fromkeys` instead C420.py:42:5: C420 [*] Unnecessary dict comprehension for iterable; use `dict.fromkeys` instead
| |
41 | def func(): 41 | def func():
42 | {n: False for n in {1: "a", 2: "b"}} # RUF025 42 | {n: False for n in {1: "a", 2: "b"}} # RUF025
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ RUF025 | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ C420
| |
= help: Replace with `dict.fromkeys(iterable)`) = help: Replace with `dict.fromkeys(iterable)`)
@ -148,11 +148,11 @@ RUF025.py:42:5: RUF025 [*] Unnecessary dict comprehension for iterable; use `dic
44 44 | 44 44 |
45 45 | def func(): 45 45 | def func():
RUF025.py:46:5: RUF025 [*] Unnecessary dict comprehension for iterable; use `dict.fromkeys` instead C420.py:46:5: C420 [*] Unnecessary dict comprehension for iterable; use `dict.fromkeys` instead
| |
45 | def func(): 45 | def func():
46 | {(a, b): 1 for (a, b) in [(1, 2), (3, 4)]} # RUF025 46 | {(a, b): 1 for (a, b) in [(1, 2), (3, 4)]} # RUF025
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ RUF025 | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ C420
| |
= help: Replace with `dict.fromkeys(iterable)`) = help: Replace with `dict.fromkeys(iterable)`)
@ -166,11 +166,11 @@ RUF025.py:46:5: RUF025 [*] Unnecessary dict comprehension for iterable; use `dic
48 48 | 48 48 |
49 49 | def func(): 49 49 | def func():
RUF025.py:54:5: RUF025 [*] Unnecessary dict comprehension for iterable; use `dict.fromkeys` instead C420.py:54:5: C420 [*] Unnecessary dict comprehension for iterable; use `dict.fromkeys` instead
| |
53 | a = f() 53 | a = f()
54 | {n: a for n in [1, 2, 3]} # RUF025 54 | {n: a for n in [1, 2, 3]} # RUF025
| ^^^^^^^^^^^^^^^^^^^^^^^^^ RUF025 | ^^^^^^^^^^^^^^^^^^^^^^^^^ C420
| |
= help: Replace with `dict.fromkeys(iterable)`) = help: Replace with `dict.fromkeys(iterable)`)
@ -184,12 +184,12 @@ RUF025.py:54:5: RUF025 [*] Unnecessary dict comprehension for iterable; use `dic
56 56 | 56 56 |
57 57 | def func(): 57 57 | def func():
RUF025.py:59:6: RUF025 [*] Unnecessary dict comprehension for iterable; use `dict.fromkeys` instead C420.py:59:6: C420 [*] Unnecessary dict comprehension for iterable; use `dict.fromkeys` instead
| |
57 | def func(): 57 | def func():
58 | values = ["a", "b", "c"] 58 | values = ["a", "b", "c"]
59 | [{n: values for n in [1, 2, 3]}] # RUF025 59 | [{n: values for n in [1, 2, 3]}] # RUF025
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ RUF025 | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ C420
| |
= help: Replace with `dict.fromkeys(iterable)`) = help: Replace with `dict.fromkeys(iterable)`)
@ -202,5 +202,3 @@ RUF025.py:59:6: RUF025 [*] Unnecessary dict comprehension for iterable; use `dic
60 60 | 60 60 |
61 61 | 61 61 |
62 62 | # Non-violation cases: RUF025 62 62 | # Non-violation cases: RUF025

View file

@ -49,7 +49,6 @@ mod tests {
#[test_case(Rule::UnsortedDunderAll, Path::new("RUF022.py"))] #[test_case(Rule::UnsortedDunderAll, Path::new("RUF022.py"))]
#[test_case(Rule::UnsortedDunderSlots, Path::new("RUF023.py"))] #[test_case(Rule::UnsortedDunderSlots, Path::new("RUF023.py"))]
#[test_case(Rule::MutableFromkeysValue, Path::new("RUF024.py"))] #[test_case(Rule::MutableFromkeysValue, Path::new("RUF024.py"))]
#[test_case(Rule::UnnecessaryDictComprehensionForIterable, Path::new("RUF025.py"))]
#[test_case(Rule::DefaultFactoryKwarg, Path::new("RUF026.py"))] #[test_case(Rule::DefaultFactoryKwarg, Path::new("RUF026.py"))]
#[test_case(Rule::MissingFStringSyntax, Path::new("RUF027_0.py"))] #[test_case(Rule::MissingFStringSyntax, Path::new("RUF027_0.py"))]
#[test_case(Rule::MissingFStringSyntax, Path::new("RUF027_1.py"))] #[test_case(Rule::MissingFStringSyntax, Path::new("RUF027_1.py"))]

View file

@ -24,7 +24,6 @@ pub(crate) use sort_dunder_slots::*;
pub(crate) use static_key_dict_comprehension::*; pub(crate) use static_key_dict_comprehension::*;
#[cfg(any(feature = "test-rules", test))] #[cfg(any(feature = "test-rules", test))]
pub(crate) use test_rules::*; pub(crate) use test_rules::*;
pub(crate) use unnecessary_dict_comprehension_for_iterable::*;
pub(crate) use unnecessary_iterable_allocation_for_first_element::*; pub(crate) use unnecessary_iterable_allocation_for_first_element::*;
pub(crate) use unnecessary_key_check::*; pub(crate) use unnecessary_key_check::*;
pub(crate) use unused_async::*; pub(crate) use unused_async::*;
@ -61,7 +60,6 @@ mod static_key_dict_comprehension;
mod suppression_comment_visitor; mod suppression_comment_visitor;
#[cfg(any(feature = "test-rules", test))] #[cfg(any(feature = "test-rules", test))]
pub(crate) mod test_rules; pub(crate) mod test_rules;
mod unnecessary_dict_comprehension_for_iterable;
mod unnecessary_iterable_allocation_for_first_element; mod unnecessary_iterable_allocation_for_first_element;
mod unnecessary_key_check; mod unnecessary_key_check;
mod unused_async; mod unused_async;

3
ruff.schema.json generated
View file

@ -2833,6 +2833,8 @@
"C417", "C417",
"C418", "C418",
"C419", "C419",
"C42",
"C420",
"C9", "C9",
"C90", "C90",
"C901", "C901",
@ -3728,7 +3730,6 @@
"RUF022", "RUF022",
"RUF023", "RUF023",
"RUF024", "RUF024",
"RUF025",
"RUF026", "RUF026",
"RUF027", "RUF027",
"RUF028", "RUF028",