-
Notifications
You must be signed in to change notification settings - Fork 1.2k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Generalize PIE807 to handle dict literals #8608
Changes from 2 commits
56eb170
d4af4f5
b630dde
1154cbf
05930bc
0ef31d4
e14024e
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,27 +1,37 @@ | ||
@dataclass | ||
class Foo: | ||
foo: List[str] = field(default_factory=lambda: []) # PIE807 | ||
bar: Dict[str, int] = field(default_factory=lambda: {}) # PIE807 | ||
|
||
|
||
class FooTable(BaseTable): | ||
bar = fields.ListField(default=lambda: []) # PIE807 | ||
foo = fields.ListField(default=lambda: []) # PIE807 | ||
bar = fields.ListField(default=lambda: {}) # PIE807 | ||
|
||
|
||
class FooTable(BaseTable): | ||
bar = fields.ListField(lambda: []) # PIE807 | ||
foo = fields.ListField(lambda: []) # PIE807 | ||
bar = fields.ListField(default=lambda: {}) # PIE807 | ||
|
||
|
||
@dataclass | ||
class Foo: | ||
foo: List[str] = field(default_factory=list) | ||
bar: Dict[str, int] = field(default_factory=dict) | ||
|
||
|
||
class FooTable(BaseTable): | ||
bar = fields.ListField(list) | ||
foo = fields.ListField(list) | ||
bar = fields.ListField(dict) | ||
|
||
|
||
lambda *args, **kwargs: [] | ||
lambda *args, **kwargs: {} | ||
|
||
lambda *args: [] | ||
lambda *args: {} | ||
|
||
lambda **kwargs: [] | ||
lambda **kwargs: {} | ||
|
||
lambda: {**unwrap} |
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -21,6 +21,7 @@ use crate::checkers::ast::Checker; | |
/// @dataclass | ||
/// class Foo: | ||
/// bar: list[int] = field(default_factory=lambda: []) | ||
/// baz: dict[str, int] = field(default_factory=lambda: {}) | ||
/// ``` | ||
/// | ||
/// Use instead: | ||
|
@@ -31,46 +32,50 @@ use crate::checkers::ast::Checker; | |
/// @dataclass | ||
/// class Foo: | ||
/// bar: list[int] = field(default_factory=list) | ||
/// baz: dict[str, int] = field(default_factory=dict) | ||
/// ``` | ||
/// | ||
/// ## References | ||
/// - [Python documentation: `list`](https://docs.python.org/3/library/functions.html#func-list) | ||
#[violation] | ||
pub struct ReimplementedListBuiltin; | ||
pub struct ReimplementedContainerBuiltin; | ||
|
||
impl Violation for ReimplementedListBuiltin { | ||
impl Violation for ReimplementedContainerBuiltin { | ||
const FIX_AVAILABILITY: FixAvailability = FixAvailability::Sometimes; | ||
|
||
#[derive_message_formats] | ||
fn message(&self) -> String { | ||
format!("Prefer `list` over useless lambda") | ||
format!("Prefer `list` or `dict` over useless lambda") | ||
} | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. You could store the type on the There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Agreed! Can grep for |
||
|
||
fn fix_title(&self) -> Option<String> { | ||
Some("Replace with `list`".to_string()) | ||
Some("Replace with `list` or `dict`".to_string()) | ||
} | ||
} | ||
|
||
/// PIE807 | ||
pub(crate) fn reimplemented_list_builtin(checker: &mut Checker, expr: &ExprLambda) { | ||
pub(crate) fn reimplemented_container_builtin(checker: &mut Checker, expr: &ExprLambda) { | ||
let ExprLambda { | ||
parameters, | ||
body, | ||
range: _, | ||
} = expr; | ||
|
||
if parameters.is_none() { | ||
if let Expr::List(ast::ExprList { elts, .. }) = body.as_ref() { | ||
if elts.is_empty() { | ||
let mut diagnostic = Diagnostic::new(ReimplementedListBuiltin, expr.range()); | ||
if checker.semantic().is_builtin("list") { | ||
diagnostic.set_fix(Fix::safe_edit(Edit::range_replacement( | ||
"list".to_string(), | ||
expr.range(), | ||
))); | ||
} | ||
checker.diagnostics.push(diagnostic); | ||
let builtin = match body.as_ref() { | ||
Expr::List(ast::ExprList { elts, .. }) if elts.is_empty() => Some("list"), | ||
Expr::Dict(ast::ExprDict { values, .. }) if values.is_empty() => Some("dict"), | ||
_ => None, | ||
}; | ||
if let Some(builtin) = builtin { | ||
let mut diagnostic = Diagnostic::new(ReimplementedContainerBuiltin, expr.range()); | ||
if checker.semantic().is_builtin(builtin) { | ||
diagnostic.set_fix(Fix::safe_edit(Edit::range_replacement( | ||
builtin.to_string(), | ||
expr.range(), | ||
))); | ||
} | ||
checker.diagnostics.push(diagnostic); | ||
} | ||
} | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,58 +1,118 @@ | ||
--- | ||
source: crates/ruff_linter/src/rules/flake8_pie/mod.rs | ||
--- | ||
PIE807.py:3:44: PIE807 [*] Prefer `list` over useless lambda | ||
PIE807.py:3:44: PIE807 [*] Prefer `list` or `dict` over useless lambda | ||
| | ||
1 | @dataclass | ||
2 | class Foo: | ||
3 | foo: List[str] = field(default_factory=lambda: []) # PIE807 | ||
| ^^^^^^^^^^ PIE807 | ||
4 | bar: Dict[str, int] = field(default_factory=lambda: {}) # PIE807 | ||
| | ||
= help: Replace with `list` | ||
= help: Replace with `list` or `dict` | ||
|
||
ℹ Safe fix | ||
1 1 | @dataclass | ||
2 2 | class Foo: | ||
3 |- foo: List[str] = field(default_factory=lambda: []) # PIE807 | ||
3 |+ foo: List[str] = field(default_factory=list) # PIE807 | ||
4 4 | | ||
4 4 | bar: Dict[str, int] = field(default_factory=lambda: {}) # PIE807 | ||
5 5 | | ||
6 6 | class FooTable(BaseTable): | ||
6 6 | | ||
|
||
PIE807.py:7:36: PIE807 [*] Prefer `list` over useless lambda | ||
PIE807.py:4:49: PIE807 [*] Prefer `list` or `dict` over useless lambda | ||
| | ||
6 | class FooTable(BaseTable): | ||
7 | bar = fields.ListField(default=lambda: []) # PIE807 | ||
2 | class Foo: | ||
3 | foo: List[str] = field(default_factory=lambda: []) # PIE807 | ||
4 | bar: Dict[str, int] = field(default_factory=lambda: {}) # PIE807 | ||
| ^^^^^^^^^^ PIE807 | ||
| | ||
= help: Replace with `list` or `dict` | ||
|
||
ℹ Safe fix | ||
1 1 | @dataclass | ||
2 2 | class Foo: | ||
3 3 | foo: List[str] = field(default_factory=lambda: []) # PIE807 | ||
4 |- bar: Dict[str, int] = field(default_factory=lambda: {}) # PIE807 | ||
4 |+ bar: Dict[str, int] = field(default_factory=dict) # PIE807 | ||
5 5 | | ||
6 6 | | ||
7 7 | class FooTable(BaseTable): | ||
|
||
PIE807.py:8:36: PIE807 [*] Prefer `list` or `dict` over useless lambda | ||
| | ||
7 | class FooTable(BaseTable): | ||
8 | foo = fields.ListField(default=lambda: []) # PIE807 | ||
| ^^^^^^^^^^ PIE807 | ||
9 | bar = fields.ListField(default=lambda: {}) # PIE807 | ||
| | ||
= help: Replace with `list` | ||
= help: Replace with `list` or `dict` | ||
|
||
ℹ Safe fix | ||
4 4 | | ||
5 5 | | ||
6 6 | class FooTable(BaseTable): | ||
7 |- bar = fields.ListField(default=lambda: []) # PIE807 | ||
7 |+ bar = fields.ListField(default=list) # PIE807 | ||
8 8 | | ||
9 9 | | ||
10 10 | class FooTable(BaseTable): | ||
|
||
PIE807.py:11:28: PIE807 [*] Prefer `list` over useless lambda | ||
6 6 | | ||
7 7 | class FooTable(BaseTable): | ||
8 |- foo = fields.ListField(default=lambda: []) # PIE807 | ||
8 |+ foo = fields.ListField(default=list) # PIE807 | ||
9 9 | bar = fields.ListField(default=lambda: {}) # PIE807 | ||
10 10 | | ||
11 11 | | ||
|
||
PIE807.py:9:36: PIE807 [*] Prefer `list` or `dict` over useless lambda | ||
| | ||
7 | class FooTable(BaseTable): | ||
8 | foo = fields.ListField(default=lambda: []) # PIE807 | ||
9 | bar = fields.ListField(default=lambda: {}) # PIE807 | ||
| ^^^^^^^^^^ PIE807 | ||
| | ||
= help: Replace with `list` or `dict` | ||
|
||
ℹ Safe fix | ||
6 6 | | ||
7 7 | class FooTable(BaseTable): | ||
8 8 | foo = fields.ListField(default=lambda: []) # PIE807 | ||
9 |- bar = fields.ListField(default=lambda: {}) # PIE807 | ||
9 |+ bar = fields.ListField(default=dict) # PIE807 | ||
10 10 | | ||
11 11 | | ||
12 12 | class FooTable(BaseTable): | ||
|
||
PIE807.py:13:28: PIE807 [*] Prefer `list` or `dict` over useless lambda | ||
| | ||
10 | class FooTable(BaseTable): | ||
11 | bar = fields.ListField(lambda: []) # PIE807 | ||
12 | class FooTable(BaseTable): | ||
13 | foo = fields.ListField(lambda: []) # PIE807 | ||
| ^^^^^^^^^^ PIE807 | ||
14 | bar = fields.ListField(default=lambda: {}) # PIE807 | ||
| | ||
= help: Replace with `list` or `dict` | ||
|
||
ℹ Safe fix | ||
10 10 | | ||
11 11 | | ||
12 12 | class FooTable(BaseTable): | ||
13 |- foo = fields.ListField(lambda: []) # PIE807 | ||
13 |+ foo = fields.ListField(list) # PIE807 | ||
14 14 | bar = fields.ListField(default=lambda: {}) # PIE807 | ||
15 15 | | ||
16 16 | | ||
|
||
PIE807.py:14:36: PIE807 [*] Prefer `list` or `dict` over useless lambda | ||
| | ||
12 | class FooTable(BaseTable): | ||
13 | foo = fields.ListField(lambda: []) # PIE807 | ||
14 | bar = fields.ListField(default=lambda: {}) # PIE807 | ||
| ^^^^^^^^^^ PIE807 | ||
| | ||
= help: Replace with `list` | ||
= help: Replace with `list` or `dict` | ||
|
||
ℹ Safe fix | ||
8 8 | | ||
9 9 | | ||
10 10 | class FooTable(BaseTable): | ||
11 |- bar = fields.ListField(lambda: []) # PIE807 | ||
11 |+ bar = fields.ListField(list) # PIE807 | ||
12 12 | | ||
13 13 | | ||
14 14 | @dataclass | ||
11 11 | | ||
12 12 | class FooTable(BaseTable): | ||
13 13 | foo = fields.ListField(lambda: []) # PIE807 | ||
14 |- bar = fields.ListField(default=lambda: {}) # PIE807 | ||
14 |+ bar = fields.ListField(default=dict) # PIE807 | ||
15 15 | | ||
16 16 | | ||
17 17 | @dataclass | ||
|
||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Maybe just
ReimplementedBuiltin
would suffice?There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think we have some other rules that also detect re-implemented builtins though -- like the simplify rules that detect re-implemented
any
andall
loops.There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Hm yes
ReimplementedBuiltin
is used forSIM110
andSIM111
— that's such a generic name for those though...I think
ReimplementedContainerBuiltin
is fine but separately we should consider changing that other one to be more specific :D