mirror of
https://github.com/astral-sh/ruff.git
synced 2025-08-03 10:22:24 +00:00
[ruff
] if k in d: del d[k]
(RUF051
) (#14553)
## Summary Resolves #7537. ## Test Plan `cargo nextest run` and `cargo insta test`. --------- Co-authored-by: Micha Reiser <micha@reiser.io>
This commit is contained in:
parent
f30227c436
commit
6f8d8fa36b
9 changed files with 893 additions and 1 deletions
130
crates/ruff_linter/resources/test/fixtures/ruff/RUF051.py
vendored
Normal file
130
crates/ruff_linter/resources/test/fixtures/ruff/RUF051.py
vendored
Normal file
|
@ -0,0 +1,130 @@
|
|||
d = {}
|
||||
l = []
|
||||
|
||||
|
||||
### Errors
|
||||
|
||||
if k in d: # Bare name
|
||||
del d[k]
|
||||
|
||||
if '' in d: # String
|
||||
del d[""] # Different quotes
|
||||
|
||||
if b"" in d: # Bytes
|
||||
del d[ # Multiline slice
|
||||
b'''''' # Triple quotes
|
||||
]
|
||||
|
||||
if 0 in d: del d[0] # Single-line statement
|
||||
|
||||
if 3j in d: # Complex
|
||||
del d[3j]
|
||||
|
||||
if 0.1234 in d: # Float
|
||||
del d[.1_2_3_4] # Number separators and shorthand syntax
|
||||
|
||||
if True in d: # True
|
||||
del d[True]
|
||||
|
||||
if False in d: # False
|
||||
del d[False]
|
||||
|
||||
if None in d: # None
|
||||
del d[
|
||||
# Comment in the middle
|
||||
None
|
||||
]
|
||||
|
||||
if ... in d: # Ellipsis
|
||||
del d[
|
||||
# Comment in the middle, indented
|
||||
...]
|
||||
|
||||
if "a" "bc" in d: # String concatenation
|
||||
del d['abc']
|
||||
|
||||
if r"\foo" in d: # Raw string
|
||||
del d['\\foo']
|
||||
|
||||
if b'yt' b'es' in d: # Bytes concatenation
|
||||
del d[rb"""ytes"""] # Raw bytes
|
||||
|
||||
if k in d:
|
||||
# comment that gets dropped
|
||||
del d[k]
|
||||
|
||||
### Safely fixable
|
||||
|
||||
if k in d:
|
||||
del d[k]
|
||||
|
||||
if '' in d:
|
||||
del d[""]
|
||||
|
||||
if b"" in d:
|
||||
del d[
|
||||
b''''''
|
||||
]
|
||||
|
||||
if 0 in d: del d[0]
|
||||
|
||||
if 3j in d:
|
||||
del d[3j]
|
||||
|
||||
if 0.1234 in d:
|
||||
del d[.1_2_3_4]
|
||||
|
||||
if True in d:
|
||||
del d[True]
|
||||
|
||||
if False in d:
|
||||
del d[False]
|
||||
|
||||
if None in d:
|
||||
del d[
|
||||
None
|
||||
]
|
||||
|
||||
if ... in d:
|
||||
del d[
|
||||
...]
|
||||
|
||||
if "a" "bc" in d:
|
||||
del d['abc']
|
||||
|
||||
if r"\foo" in d:
|
||||
del d['\\foo']
|
||||
|
||||
if b'yt' b'es' in d:
|
||||
del d[rb"""ytes"""] # This should not make the fix unsafe
|
||||
|
||||
|
||||
|
||||
### No errors
|
||||
|
||||
if k in l: # Not a dict
|
||||
del l[k]
|
||||
|
||||
if d.__contains__(k): # Explicit dunder call
|
||||
del d[k]
|
||||
|
||||
if a.k in d: # Attribute
|
||||
del d[a.k]
|
||||
|
||||
if (a, b) in d: # Tuple
|
||||
del d[a, b]
|
||||
|
||||
if 2 in d: # Different key value (int)
|
||||
del d[3]
|
||||
|
||||
if 2_4j in d: # Different key value (complex)
|
||||
del d[3.6] # Different key value (float)
|
||||
|
||||
if 0.1 + 0.2 in d: # Complex expression
|
||||
del d[0.3]
|
||||
|
||||
if f"0" in d: # f-string
|
||||
del d[f"0"]
|
||||
|
||||
if k in a.d: # Attribute dict
|
||||
del a.d[k]
|
|
@ -1235,6 +1235,9 @@ pub(crate) fn statement(stmt: &Stmt, checker: &mut Checker) {
|
|||
}
|
||||
}
|
||||
}
|
||||
if checker.enabled(Rule::IfKeyInDictDel) {
|
||||
ruff::rules::if_key_in_dict_del(checker, if_);
|
||||
}
|
||||
}
|
||||
Stmt::Assert(
|
||||
assert_stmt @ ast::StmtAssert {
|
||||
|
|
|
@ -222,7 +222,7 @@ pub(crate) struct Checker<'a> {
|
|||
analyze: deferred::Analyze,
|
||||
/// The cumulative set of diagnostics computed across all lint rules.
|
||||
pub(crate) diagnostics: Vec<Diagnostic>,
|
||||
/// The list of names already seen by flake8-bugbear diagnostics, to avoid duplicate violations..
|
||||
/// The list of names already seen by flake8-bugbear diagnostics, to avoid duplicate violations.
|
||||
pub(crate) flake8_bugbear_seen: Vec<TextRange>,
|
||||
/// The end offset of the last visited statement.
|
||||
last_stmt_end: TextSize,
|
||||
|
|
|
@ -987,6 +987,7 @@ pub fn code_to_rule(linter: Linter, code: &str) -> Option<(RuleGroup, Rule)> {
|
|||
(Ruff, "041") => (RuleGroup::Preview, rules::ruff::rules::UnnecessaryNestedLiteral),
|
||||
(Ruff, "046") => (RuleGroup::Preview, rules::ruff::rules::UnnecessaryCastToInt),
|
||||
(Ruff, "048") => (RuleGroup::Preview, rules::ruff::rules::MapIntVersionParsing),
|
||||
(Ruff, "051") => (RuleGroup::Preview, rules::ruff::rules::IfKeyInDictDel),
|
||||
(Ruff, "052") => (RuleGroup::Preview, rules::ruff::rules::UsedDummyVariable),
|
||||
(Ruff, "055") => (RuleGroup::Preview, rules::ruff::rules::UnnecessaryRegularExpression),
|
||||
(Ruff, "100") => (RuleGroup::Stable, rules::ruff::rules::UnusedNOQA),
|
||||
|
|
|
@ -71,6 +71,7 @@ mod tests {
|
|||
#[test_case(Rule::InvalidAssertMessageLiteralArgument, Path::new("RUF040.py"))]
|
||||
#[test_case(Rule::UnnecessaryNestedLiteral, Path::new("RUF041.py"))]
|
||||
#[test_case(Rule::UnnecessaryNestedLiteral, Path::new("RUF041.pyi"))]
|
||||
#[test_case(Rule::IfKeyInDictDel, Path::new("RUF051.py"))]
|
||||
#[test_case(Rule::UsedDummyVariable, Path::new("RUF052.py"))]
|
||||
fn rules(rule_code: Rule, path: &Path) -> Result<()> {
|
||||
let snapshot = format!("{}_{}", rule_code.noqa_code(), path.to_string_lossy());
|
||||
|
|
154
crates/ruff_linter/src/rules/ruff/rules/if_key_in_dict_del.rs
Normal file
154
crates/ruff_linter/src/rules/ruff/rules/if_key_in_dict_del.rs
Normal file
|
@ -0,0 +1,154 @@
|
|||
use crate::checkers::ast::Checker;
|
||||
use ruff_diagnostics::{AlwaysFixableViolation, Applicability, Diagnostic, Edit, Fix};
|
||||
use ruff_macros::{derive_message_formats, ViolationMetadata};
|
||||
use ruff_python_ast::{CmpOp, Expr, ExprName, ExprSubscript, Stmt, StmtIf};
|
||||
use ruff_python_semantic::analyze::typing;
|
||||
use ruff_python_semantic::SemanticModel;
|
||||
|
||||
type Key = Expr;
|
||||
type Dict = ExprName;
|
||||
|
||||
/// ## What it does
|
||||
/// Checks for `if key in dictionary: del dictionary[key]`.
|
||||
///
|
||||
/// ## Why is this bad?
|
||||
/// To remove a key-value pair from a dictionary, it's more concise to use `.pop(..., None)`.
|
||||
///
|
||||
/// ## Example
|
||||
///
|
||||
/// ```python
|
||||
/// if key in dictionary:
|
||||
/// del dictionary[key]
|
||||
/// ```
|
||||
///
|
||||
/// Use instead:
|
||||
///
|
||||
/// ```python
|
||||
/// dictionary.pop(key, None)
|
||||
/// ```
|
||||
///
|
||||
/// ## Fix safety
|
||||
/// This rule's fix is marked as safe, unless the if statement contains comments.
|
||||
#[derive(ViolationMetadata)]
|
||||
pub(crate) struct IfKeyInDictDel;
|
||||
|
||||
impl AlwaysFixableViolation for IfKeyInDictDel {
|
||||
#[derive_message_formats]
|
||||
fn message(&self) -> String {
|
||||
"Use `pop` instead of `key in dict` followed by `delete dict[key]`".to_string()
|
||||
}
|
||||
|
||||
fn fix_title(&self) -> String {
|
||||
"Replace `if` statement with `.pop(..., None)`".to_string()
|
||||
}
|
||||
}
|
||||
|
||||
/// RUF051
|
||||
pub(crate) fn if_key_in_dict_del(checker: &mut Checker, stmt: &StmtIf) {
|
||||
let [Stmt::Delete(delete)] = &stmt.body[..] else {
|
||||
return;
|
||||
};
|
||||
|
||||
let Some((test_dict, test_key)) = extract_dict_and_key_from_test(&stmt.test) else {
|
||||
return;
|
||||
};
|
||||
let Some((del_dict, del_key)) = extract_dict_and_key_from_del(&delete.targets) else {
|
||||
return;
|
||||
};
|
||||
|
||||
if !is_same_key(test_key, del_key) || !is_same_dict(test_dict, del_dict) {
|
||||
return;
|
||||
}
|
||||
|
||||
if !is_known_to_be_of_type_dict(checker.semantic(), test_dict) {
|
||||
return;
|
||||
}
|
||||
|
||||
let fix = replace_with_dict_pop_fix(checker, stmt, test_dict, test_key);
|
||||
|
||||
let diagnostic = Diagnostic::new(IfKeyInDictDel, delete.range);
|
||||
|
||||
checker.diagnostics.push(diagnostic.with_fix(fix));
|
||||
}
|
||||
|
||||
fn extract_dict_and_key_from_test(test: &Expr) -> Option<(&Dict, &Key)> {
|
||||
let Expr::Compare(comp) = test else {
|
||||
return None;
|
||||
};
|
||||
|
||||
let [Expr::Name(dict)] = comp.comparators.as_ref() else {
|
||||
return None;
|
||||
};
|
||||
|
||||
if !matches!(comp.ops.as_ref(), [CmpOp::In]) {
|
||||
return None;
|
||||
}
|
||||
|
||||
Some((dict, &comp.left))
|
||||
}
|
||||
|
||||
fn extract_dict_and_key_from_del(targets: &[Expr]) -> Option<(&Dict, &Key)> {
|
||||
let [Expr::Subscript(ExprSubscript { value, slice, .. })] = targets else {
|
||||
return None;
|
||||
};
|
||||
|
||||
let Expr::Name(dict) = value.as_ref() else {
|
||||
return None;
|
||||
};
|
||||
|
||||
Some((dict, slice))
|
||||
}
|
||||
|
||||
fn is_same_key(test: &Key, del: &Key) -> bool {
|
||||
match (test, del) {
|
||||
(Expr::Name(ExprName { id: test, .. }), Expr::Name(ExprName { id: del, .. })) => {
|
||||
test.as_str() == del.as_str()
|
||||
}
|
||||
|
||||
(Expr::NoneLiteral(..), Expr::NoneLiteral(..)) => true,
|
||||
(Expr::EllipsisLiteral(..), Expr::EllipsisLiteral(..)) => true,
|
||||
|
||||
(Expr::BooleanLiteral(test), Expr::BooleanLiteral(del)) => test.value == del.value,
|
||||
(Expr::NumberLiteral(test), Expr::NumberLiteral(del)) => test.value == del.value,
|
||||
|
||||
(Expr::BytesLiteral(test), Expr::BytesLiteral(del)) => {
|
||||
Iterator::eq(test.value.bytes(), del.value.bytes())
|
||||
}
|
||||
|
||||
(Expr::StringLiteral(test), Expr::StringLiteral(del)) => {
|
||||
Iterator::eq(test.value.chars(), del.value.chars())
|
||||
}
|
||||
|
||||
_ => false,
|
||||
}
|
||||
}
|
||||
|
||||
fn is_same_dict(test: &Dict, del: &Dict) -> bool {
|
||||
test.id.as_str() == del.id.as_str()
|
||||
}
|
||||
|
||||
fn is_known_to_be_of_type_dict(semantic: &SemanticModel, dict: &Dict) -> bool {
|
||||
let Some(binding) = semantic.only_binding(dict).map(|id| semantic.binding(id)) else {
|
||||
return false;
|
||||
};
|
||||
|
||||
typing::is_dict(binding, semantic)
|
||||
}
|
||||
|
||||
fn replace_with_dict_pop_fix(checker: &Checker, stmt: &StmtIf, dict: &Dict, key: &Key) -> Fix {
|
||||
let locator = checker.locator();
|
||||
let dict_expr = locator.slice(dict);
|
||||
let key_expr = locator.slice(key);
|
||||
|
||||
let replacement = format!("{dict_expr}.pop({key_expr}, None)");
|
||||
let edit = Edit::range_replacement(replacement, stmt.range);
|
||||
|
||||
let comment_ranges = checker.comment_ranges();
|
||||
let applicability = if comment_ranges.intersects(stmt.range) {
|
||||
Applicability::Unsafe
|
||||
} else {
|
||||
Applicability::Safe
|
||||
};
|
||||
|
||||
Fix::applicable_edit(edit, applicability)
|
||||
}
|
|
@ -7,6 +7,7 @@ pub(crate) use decimal_from_float_literal::*;
|
|||
pub(crate) use default_factory_kwarg::*;
|
||||
pub(crate) use explicit_f_string_type_conversion::*;
|
||||
pub(crate) use function_call_in_dataclass_default::*;
|
||||
pub(crate) use if_key_in_dict_del::*;
|
||||
pub(crate) use implicit_optional::*;
|
||||
pub(crate) use incorrectly_parenthesized_tuple_in_subscript::*;
|
||||
pub(crate) use invalid_assert_message_literal_argument::*;
|
||||
|
@ -54,6 +55,7 @@ mod default_factory_kwarg;
|
|||
mod explicit_f_string_type_conversion;
|
||||
mod function_call_in_dataclass_default;
|
||||
mod helpers;
|
||||
mod if_key_in_dict_del;
|
||||
mod implicit_optional;
|
||||
mod incorrectly_parenthesized_tuple_in_subscript;
|
||||
mod invalid_assert_message_literal_argument;
|
||||
|
|
|
@ -0,0 +1,600 @@
|
|||
---
|
||||
source: crates/ruff_linter/src/rules/ruff/mod.rs
|
||||
snapshot_kind: text
|
||||
---
|
||||
RUF051.py:8:5: RUF051 [*] Use `pop` instead of `key in dict` followed by `delete dict[key]`
|
||||
|
|
||||
7 | if k in d: # Bare name
|
||||
8 | del d[k]
|
||||
| ^^^^^^^^ RUF051
|
||||
9 |
|
||||
10 | if '' in d: # String
|
||||
|
|
||||
= help: Replace `if` statement with `.pop(..., None)`
|
||||
|
||||
ℹ Unsafe fix
|
||||
4 4 |
|
||||
5 5 | ### Errors
|
||||
6 6 |
|
||||
7 |-if k in d: # Bare name
|
||||
8 |- del d[k]
|
||||
7 |+d.pop(k, None)
|
||||
9 8 |
|
||||
10 9 | if '' in d: # String
|
||||
11 10 | del d[""] # Different quotes
|
||||
|
||||
RUF051.py:11:5: RUF051 [*] Use `pop` instead of `key in dict` followed by `delete dict[key]`
|
||||
|
|
||||
10 | if '' in d: # String
|
||||
11 | del d[""] # Different quotes
|
||||
| ^^^^^^^^^ RUF051
|
||||
12 |
|
||||
13 | if b"" in d: # Bytes
|
||||
|
|
||||
= help: Replace `if` statement with `.pop(..., None)`
|
||||
|
||||
ℹ Unsafe fix
|
||||
7 7 | if k in d: # Bare name
|
||||
8 8 | del d[k]
|
||||
9 9 |
|
||||
10 |-if '' in d: # String
|
||||
11 |- del d[""] # Different quotes
|
||||
10 |+d.pop('', None) # Different quotes
|
||||
12 11 |
|
||||
13 12 | if b"" in d: # Bytes
|
||||
14 13 | del d[ # Multiline slice
|
||||
|
||||
RUF051.py:14:5: RUF051 [*] Use `pop` instead of `key in dict` followed by `delete dict[key]`
|
||||
|
|
||||
13 | if b"" in d: # Bytes
|
||||
14 | del d[ # Multiline slice
|
||||
| _____^
|
||||
15 | | b'''''' # Triple quotes
|
||||
16 | | ]
|
||||
| |_____^ RUF051
|
||||
17 |
|
||||
18 | if 0 in d: del d[0] # Single-line statement
|
||||
|
|
||||
= help: Replace `if` statement with `.pop(..., None)`
|
||||
|
||||
ℹ Unsafe fix
|
||||
10 10 | if '' in d: # String
|
||||
11 11 | del d[""] # Different quotes
|
||||
12 12 |
|
||||
13 |-if b"" in d: # Bytes
|
||||
14 |- del d[ # Multiline slice
|
||||
15 |- b'''''' # Triple quotes
|
||||
16 |- ]
|
||||
13 |+d.pop(b"", None)
|
||||
17 14 |
|
||||
18 15 | if 0 in d: del d[0] # Single-line statement
|
||||
19 16 |
|
||||
|
||||
RUF051.py:18:12: RUF051 [*] Use `pop` instead of `key in dict` followed by `delete dict[key]`
|
||||
|
|
||||
16 | ]
|
||||
17 |
|
||||
18 | if 0 in d: del d[0] # Single-line statement
|
||||
| ^^^^^^^^ RUF051
|
||||
19 |
|
||||
20 | if 3j in d: # Complex
|
||||
|
|
||||
= help: Replace `if` statement with `.pop(..., None)`
|
||||
|
||||
ℹ Safe fix
|
||||
15 15 | b'''''' # Triple quotes
|
||||
16 16 | ]
|
||||
17 17 |
|
||||
18 |-if 0 in d: del d[0] # Single-line statement
|
||||
18 |+d.pop(0, None) # Single-line statement
|
||||
19 19 |
|
||||
20 20 | if 3j in d: # Complex
|
||||
21 21 | del d[3j]
|
||||
|
||||
RUF051.py:21:5: RUF051 [*] Use `pop` instead of `key in dict` followed by `delete dict[key]`
|
||||
|
|
||||
20 | if 3j in d: # Complex
|
||||
21 | del d[3j]
|
||||
| ^^^^^^^^^ RUF051
|
||||
22 |
|
||||
23 | if 0.1234 in d: # Float
|
||||
|
|
||||
= help: Replace `if` statement with `.pop(..., None)`
|
||||
|
||||
ℹ Unsafe fix
|
||||
17 17 |
|
||||
18 18 | if 0 in d: del d[0] # Single-line statement
|
||||
19 19 |
|
||||
20 |-if 3j in d: # Complex
|
||||
21 |- del d[3j]
|
||||
20 |+d.pop(3j, None)
|
||||
22 21 |
|
||||
23 22 | if 0.1234 in d: # Float
|
||||
24 23 | del d[.1_2_3_4] # Number separators and shorthand syntax
|
||||
|
||||
RUF051.py:24:5: RUF051 [*] Use `pop` instead of `key in dict` followed by `delete dict[key]`
|
||||
|
|
||||
23 | if 0.1234 in d: # Float
|
||||
24 | del d[.1_2_3_4] # Number separators and shorthand syntax
|
||||
| ^^^^^^^^^^^^^^^ RUF051
|
||||
25 |
|
||||
26 | if True in d: # True
|
||||
|
|
||||
= help: Replace `if` statement with `.pop(..., None)`
|
||||
|
||||
ℹ Unsafe fix
|
||||
20 20 | if 3j in d: # Complex
|
||||
21 21 | del d[3j]
|
||||
22 22 |
|
||||
23 |-if 0.1234 in d: # Float
|
||||
24 |- del d[.1_2_3_4] # Number separators and shorthand syntax
|
||||
23 |+d.pop(0.1234, None) # Number separators and shorthand syntax
|
||||
25 24 |
|
||||
26 25 | if True in d: # True
|
||||
27 26 | del d[True]
|
||||
|
||||
RUF051.py:27:5: RUF051 [*] Use `pop` instead of `key in dict` followed by `delete dict[key]`
|
||||
|
|
||||
26 | if True in d: # True
|
||||
27 | del d[True]
|
||||
| ^^^^^^^^^^^ RUF051
|
||||
28 |
|
||||
29 | if False in d: # False
|
||||
|
|
||||
= help: Replace `if` statement with `.pop(..., None)`
|
||||
|
||||
ℹ Unsafe fix
|
||||
23 23 | if 0.1234 in d: # Float
|
||||
24 24 | del d[.1_2_3_4] # Number separators and shorthand syntax
|
||||
25 25 |
|
||||
26 |-if True in d: # True
|
||||
27 |- del d[True]
|
||||
26 |+d.pop(True, None)
|
||||
28 27 |
|
||||
29 28 | if False in d: # False
|
||||
30 29 | del d[False]
|
||||
|
||||
RUF051.py:30:5: RUF051 [*] Use `pop` instead of `key in dict` followed by `delete dict[key]`
|
||||
|
|
||||
29 | if False in d: # False
|
||||
30 | del d[False]
|
||||
| ^^^^^^^^^^^^ RUF051
|
||||
31 |
|
||||
32 | if None in d: # None
|
||||
|
|
||||
= help: Replace `if` statement with `.pop(..., None)`
|
||||
|
||||
ℹ Unsafe fix
|
||||
26 26 | if True in d: # True
|
||||
27 27 | del d[True]
|
||||
28 28 |
|
||||
29 |-if False in d: # False
|
||||
30 |- del d[False]
|
||||
29 |+d.pop(False, None)
|
||||
31 30 |
|
||||
32 31 | if None in d: # None
|
||||
33 32 | del d[
|
||||
|
||||
RUF051.py:33:5: RUF051 [*] Use `pop` instead of `key in dict` followed by `delete dict[key]`
|
||||
|
|
||||
32 | if None in d: # None
|
||||
33 | del d[
|
||||
| _____^
|
||||
34 | | # Comment in the middle
|
||||
35 | | None
|
||||
36 | | ]
|
||||
| |_____^ RUF051
|
||||
37 |
|
||||
38 | if ... in d: # Ellipsis
|
||||
|
|
||||
= help: Replace `if` statement with `.pop(..., None)`
|
||||
|
||||
ℹ Unsafe fix
|
||||
29 29 | if False in d: # False
|
||||
30 30 | del d[False]
|
||||
31 31 |
|
||||
32 |-if None in d: # None
|
||||
33 |- del d[
|
||||
34 |- # Comment in the middle
|
||||
35 |- None
|
||||
36 |- ]
|
||||
32 |+d.pop(None, None)
|
||||
37 33 |
|
||||
38 34 | if ... in d: # Ellipsis
|
||||
39 35 | del d[
|
||||
|
||||
RUF051.py:39:5: RUF051 [*] Use `pop` instead of `key in dict` followed by `delete dict[key]`
|
||||
|
|
||||
38 | if ... in d: # Ellipsis
|
||||
39 | del d[
|
||||
| _____^
|
||||
40 | | # Comment in the middle, indented
|
||||
41 | | ...]
|
||||
| |____________^ RUF051
|
||||
42 |
|
||||
43 | if "a" "bc" in d: # String concatenation
|
||||
|
|
||||
= help: Replace `if` statement with `.pop(..., None)`
|
||||
|
||||
ℹ Unsafe fix
|
||||
35 35 | None
|
||||
36 36 | ]
|
||||
37 37 |
|
||||
38 |-if ... in d: # Ellipsis
|
||||
39 |- del d[
|
||||
40 |- # Comment in the middle, indented
|
||||
41 |- ...]
|
||||
38 |+d.pop(..., None)
|
||||
42 39 |
|
||||
43 40 | if "a" "bc" in d: # String concatenation
|
||||
44 41 | del d['abc']
|
||||
|
||||
RUF051.py:44:5: RUF051 [*] Use `pop` instead of `key in dict` followed by `delete dict[key]`
|
||||
|
|
||||
43 | if "a" "bc" in d: # String concatenation
|
||||
44 | del d['abc']
|
||||
| ^^^^^^^^^^^^ RUF051
|
||||
45 |
|
||||
46 | if r"\foo" in d: # Raw string
|
||||
|
|
||||
= help: Replace `if` statement with `.pop(..., None)`
|
||||
|
||||
ℹ Unsafe fix
|
||||
40 40 | # Comment in the middle, indented
|
||||
41 41 | ...]
|
||||
42 42 |
|
||||
43 |-if "a" "bc" in d: # String concatenation
|
||||
44 |- del d['abc']
|
||||
43 |+d.pop("a" "bc", None)
|
||||
45 44 |
|
||||
46 45 | if r"\foo" in d: # Raw string
|
||||
47 46 | del d['\\foo']
|
||||
|
||||
RUF051.py:47:5: RUF051 [*] Use `pop` instead of `key in dict` followed by `delete dict[key]`
|
||||
|
|
||||
46 | if r"\foo" in d: # Raw string
|
||||
47 | del d['\\foo']
|
||||
| ^^^^^^^^^^^^^^ RUF051
|
||||
48 |
|
||||
49 | if b'yt' b'es' in d: # Bytes concatenation
|
||||
|
|
||||
= help: Replace `if` statement with `.pop(..., None)`
|
||||
|
||||
ℹ Unsafe fix
|
||||
43 43 | if "a" "bc" in d: # String concatenation
|
||||
44 44 | del d['abc']
|
||||
45 45 |
|
||||
46 |-if r"\foo" in d: # Raw string
|
||||
47 |- del d['\\foo']
|
||||
46 |+d.pop(r"\foo", None)
|
||||
48 47 |
|
||||
49 48 | if b'yt' b'es' in d: # Bytes concatenation
|
||||
50 49 | del d[rb"""ytes"""] # Raw bytes
|
||||
|
||||
RUF051.py:50:5: RUF051 [*] Use `pop` instead of `key in dict` followed by `delete dict[key]`
|
||||
|
|
||||
49 | if b'yt' b'es' in d: # Bytes concatenation
|
||||
50 | del d[rb"""ytes"""] # Raw bytes
|
||||
| ^^^^^^^^^^^^^^^^^^^ RUF051
|
||||
51 |
|
||||
52 | if k in d:
|
||||
|
|
||||
= help: Replace `if` statement with `.pop(..., None)`
|
||||
|
||||
ℹ Unsafe fix
|
||||
46 46 | if r"\foo" in d: # Raw string
|
||||
47 47 | del d['\\foo']
|
||||
48 48 |
|
||||
49 |-if b'yt' b'es' in d: # Bytes concatenation
|
||||
50 |- del d[rb"""ytes"""] # Raw bytes
|
||||
49 |+d.pop(b'yt' b'es', None) # Raw bytes
|
||||
51 50 |
|
||||
52 51 | if k in d:
|
||||
53 52 | # comment that gets dropped
|
||||
|
||||
RUF051.py:54:5: RUF051 [*] Use `pop` instead of `key in dict` followed by `delete dict[key]`
|
||||
|
|
||||
52 | if k in d:
|
||||
53 | # comment that gets dropped
|
||||
54 | del d[k]
|
||||
| ^^^^^^^^ RUF051
|
||||
55 |
|
||||
56 | ### Safely fixable
|
||||
|
|
||||
= help: Replace `if` statement with `.pop(..., None)`
|
||||
|
||||
ℹ Unsafe fix
|
||||
49 49 | if b'yt' b'es' in d: # Bytes concatenation
|
||||
50 50 | del d[rb"""ytes"""] # Raw bytes
|
||||
51 51 |
|
||||
52 |-if k in d:
|
||||
53 |- # comment that gets dropped
|
||||
54 |- del d[k]
|
||||
52 |+d.pop(k, None)
|
||||
55 53 |
|
||||
56 54 | ### Safely fixable
|
||||
57 55 |
|
||||
|
||||
RUF051.py:59:5: RUF051 [*] Use `pop` instead of `key in dict` followed by `delete dict[key]`
|
||||
|
|
||||
58 | if k in d:
|
||||
59 | del d[k]
|
||||
| ^^^^^^^^ RUF051
|
||||
60 |
|
||||
61 | if '' in d:
|
||||
|
|
||||
= help: Replace `if` statement with `.pop(..., None)`
|
||||
|
||||
ℹ Safe fix
|
||||
55 55 |
|
||||
56 56 | ### Safely fixable
|
||||
57 57 |
|
||||
58 |-if k in d:
|
||||
59 |- del d[k]
|
||||
58 |+d.pop(k, None)
|
||||
60 59 |
|
||||
61 60 | if '' in d:
|
||||
62 61 | del d[""]
|
||||
|
||||
RUF051.py:62:5: RUF051 [*] Use `pop` instead of `key in dict` followed by `delete dict[key]`
|
||||
|
|
||||
61 | if '' in d:
|
||||
62 | del d[""]
|
||||
| ^^^^^^^^^ RUF051
|
||||
63 |
|
||||
64 | if b"" in d:
|
||||
|
|
||||
= help: Replace `if` statement with `.pop(..., None)`
|
||||
|
||||
ℹ Safe fix
|
||||
58 58 | if k in d:
|
||||
59 59 | del d[k]
|
||||
60 60 |
|
||||
61 |-if '' in d:
|
||||
62 |- del d[""]
|
||||
61 |+d.pop('', None)
|
||||
63 62 |
|
||||
64 63 | if b"" in d:
|
||||
65 64 | del d[
|
||||
|
||||
RUF051.py:65:5: RUF051 [*] Use `pop` instead of `key in dict` followed by `delete dict[key]`
|
||||
|
|
||||
64 | if b"" in d:
|
||||
65 | del d[
|
||||
| _____^
|
||||
66 | | b''''''
|
||||
67 | | ]
|
||||
| |_____^ RUF051
|
||||
68 |
|
||||
69 | if 0 in d: del d[0]
|
||||
|
|
||||
= help: Replace `if` statement with `.pop(..., None)`
|
||||
|
||||
ℹ Safe fix
|
||||
61 61 | if '' in d:
|
||||
62 62 | del d[""]
|
||||
63 63 |
|
||||
64 |-if b"" in d:
|
||||
65 |- del d[
|
||||
66 |- b''''''
|
||||
67 |- ]
|
||||
64 |+d.pop(b"", None)
|
||||
68 65 |
|
||||
69 66 | if 0 in d: del d[0]
|
||||
70 67 |
|
||||
|
||||
RUF051.py:69:12: RUF051 [*] Use `pop` instead of `key in dict` followed by `delete dict[key]`
|
||||
|
|
||||
67 | ]
|
||||
68 |
|
||||
69 | if 0 in d: del d[0]
|
||||
| ^^^^^^^^ RUF051
|
||||
70 |
|
||||
71 | if 3j in d:
|
||||
|
|
||||
= help: Replace `if` statement with `.pop(..., None)`
|
||||
|
||||
ℹ Safe fix
|
||||
66 66 | b''''''
|
||||
67 67 | ]
|
||||
68 68 |
|
||||
69 |-if 0 in d: del d[0]
|
||||
69 |+d.pop(0, None)
|
||||
70 70 |
|
||||
71 71 | if 3j in d:
|
||||
72 72 | del d[3j]
|
||||
|
||||
RUF051.py:72:5: RUF051 [*] Use `pop` instead of `key in dict` followed by `delete dict[key]`
|
||||
|
|
||||
71 | if 3j in d:
|
||||
72 | del d[3j]
|
||||
| ^^^^^^^^^ RUF051
|
||||
73 |
|
||||
74 | if 0.1234 in d:
|
||||
|
|
||||
= help: Replace `if` statement with `.pop(..., None)`
|
||||
|
||||
ℹ Safe fix
|
||||
68 68 |
|
||||
69 69 | if 0 in d: del d[0]
|
||||
70 70 |
|
||||
71 |-if 3j in d:
|
||||
72 |- del d[3j]
|
||||
71 |+d.pop(3j, None)
|
||||
73 72 |
|
||||
74 73 | if 0.1234 in d:
|
||||
75 74 | del d[.1_2_3_4]
|
||||
|
||||
RUF051.py:75:5: RUF051 [*] Use `pop` instead of `key in dict` followed by `delete dict[key]`
|
||||
|
|
||||
74 | if 0.1234 in d:
|
||||
75 | del d[.1_2_3_4]
|
||||
| ^^^^^^^^^^^^^^^ RUF051
|
||||
76 |
|
||||
77 | if True in d:
|
||||
|
|
||||
= help: Replace `if` statement with `.pop(..., None)`
|
||||
|
||||
ℹ Safe fix
|
||||
71 71 | if 3j in d:
|
||||
72 72 | del d[3j]
|
||||
73 73 |
|
||||
74 |-if 0.1234 in d:
|
||||
75 |- del d[.1_2_3_4]
|
||||
74 |+d.pop(0.1234, None)
|
||||
76 75 |
|
||||
77 76 | if True in d:
|
||||
78 77 | del d[True]
|
||||
|
||||
RUF051.py:78:5: RUF051 [*] Use `pop` instead of `key in dict` followed by `delete dict[key]`
|
||||
|
|
||||
77 | if True in d:
|
||||
78 | del d[True]
|
||||
| ^^^^^^^^^^^ RUF051
|
||||
79 |
|
||||
80 | if False in d:
|
||||
|
|
||||
= help: Replace `if` statement with `.pop(..., None)`
|
||||
|
||||
ℹ Safe fix
|
||||
74 74 | if 0.1234 in d:
|
||||
75 75 | del d[.1_2_3_4]
|
||||
76 76 |
|
||||
77 |-if True in d:
|
||||
78 |- del d[True]
|
||||
77 |+d.pop(True, None)
|
||||
79 78 |
|
||||
80 79 | if False in d:
|
||||
81 80 | del d[False]
|
||||
|
||||
RUF051.py:81:5: RUF051 [*] Use `pop` instead of `key in dict` followed by `delete dict[key]`
|
||||
|
|
||||
80 | if False in d:
|
||||
81 | del d[False]
|
||||
| ^^^^^^^^^^^^ RUF051
|
||||
82 |
|
||||
83 | if None in d:
|
||||
|
|
||||
= help: Replace `if` statement with `.pop(..., None)`
|
||||
|
||||
ℹ Safe fix
|
||||
77 77 | if True in d:
|
||||
78 78 | del d[True]
|
||||
79 79 |
|
||||
80 |-if False in d:
|
||||
81 |- del d[False]
|
||||
80 |+d.pop(False, None)
|
||||
82 81 |
|
||||
83 82 | if None in d:
|
||||
84 83 | del d[
|
||||
|
||||
RUF051.py:84:5: RUF051 [*] Use `pop` instead of `key in dict` followed by `delete dict[key]`
|
||||
|
|
||||
83 | if None in d:
|
||||
84 | del d[
|
||||
| _____^
|
||||
85 | | None
|
||||
86 | | ]
|
||||
| |_____^ RUF051
|
||||
87 |
|
||||
88 | if ... in d:
|
||||
|
|
||||
= help: Replace `if` statement with `.pop(..., None)`
|
||||
|
||||
ℹ Safe fix
|
||||
80 80 | if False in d:
|
||||
81 81 | del d[False]
|
||||
82 82 |
|
||||
83 |-if None in d:
|
||||
84 |- del d[
|
||||
85 |- None
|
||||
86 |- ]
|
||||
83 |+d.pop(None, None)
|
||||
87 84 |
|
||||
88 85 | if ... in d:
|
||||
89 86 | del d[
|
||||
|
||||
RUF051.py:89:5: RUF051 [*] Use `pop` instead of `key in dict` followed by `delete dict[key]`
|
||||
|
|
||||
88 | if ... in d:
|
||||
89 | del d[
|
||||
| _____^
|
||||
90 | | ...]
|
||||
| |____________^ RUF051
|
||||
91 |
|
||||
92 | if "a" "bc" in d:
|
||||
|
|
||||
= help: Replace `if` statement with `.pop(..., None)`
|
||||
|
||||
ℹ Safe fix
|
||||
85 85 | None
|
||||
86 86 | ]
|
||||
87 87 |
|
||||
88 |-if ... in d:
|
||||
89 |- del d[
|
||||
90 |- ...]
|
||||
88 |+d.pop(..., None)
|
||||
91 89 |
|
||||
92 90 | if "a" "bc" in d:
|
||||
93 91 | del d['abc']
|
||||
|
||||
RUF051.py:93:5: RUF051 [*] Use `pop` instead of `key in dict` followed by `delete dict[key]`
|
||||
|
|
||||
92 | if "a" "bc" in d:
|
||||
93 | del d['abc']
|
||||
| ^^^^^^^^^^^^ RUF051
|
||||
94 |
|
||||
95 | if r"\foo" in d:
|
||||
|
|
||||
= help: Replace `if` statement with `.pop(..., None)`
|
||||
|
||||
ℹ Safe fix
|
||||
89 89 | del d[
|
||||
90 90 | ...]
|
||||
91 91 |
|
||||
92 |-if "a" "bc" in d:
|
||||
93 |- del d['abc']
|
||||
92 |+d.pop("a" "bc", None)
|
||||
94 93 |
|
||||
95 94 | if r"\foo" in d:
|
||||
96 95 | del d['\\foo']
|
||||
|
||||
RUF051.py:96:5: RUF051 [*] Use `pop` instead of `key in dict` followed by `delete dict[key]`
|
||||
|
|
||||
95 | if r"\foo" in d:
|
||||
96 | del d['\\foo']
|
||||
| ^^^^^^^^^^^^^^ RUF051
|
||||
97 |
|
||||
98 | if b'yt' b'es' in d:
|
||||
|
|
||||
= help: Replace `if` statement with `.pop(..., None)`
|
||||
|
||||
ℹ Safe fix
|
||||
92 92 | if "a" "bc" in d:
|
||||
93 93 | del d['abc']
|
||||
94 94 |
|
||||
95 |-if r"\foo" in d:
|
||||
96 |- del d['\\foo']
|
||||
95 |+d.pop(r"\foo", None)
|
||||
97 96 |
|
||||
98 97 | if b'yt' b'es' in d:
|
||||
99 98 | del d[rb"""ytes"""] # This should not make the fix unsafe
|
||||
|
||||
RUF051.py:99:5: RUF051 [*] Use `pop` instead of `key in dict` followed by `delete dict[key]`
|
||||
|
|
||||
98 | if b'yt' b'es' in d:
|
||||
99 | del d[rb"""ytes"""] # This should not make the fix unsafe
|
||||
| ^^^^^^^^^^^^^^^^^^^ RUF051
|
||||
|
|
||||
= help: Replace `if` statement with `.pop(..., None)`
|
||||
|
||||
ℹ Safe fix
|
||||
95 95 | if r"\foo" in d:
|
||||
96 96 | del d['\\foo']
|
||||
97 97 |
|
||||
98 |-if b'yt' b'es' in d:
|
||||
99 |- del d[rb"""ytes"""] # This should not make the fix unsafe
|
||||
98 |+d.pop(b'yt' b'es', None) # This should not make the fix unsafe
|
||||
100 99 |
|
||||
101 100 |
|
||||
102 101 |
|
1
ruff.schema.json
generated
1
ruff.schema.json
generated
|
@ -3850,6 +3850,7 @@
|
|||
"RUF046",
|
||||
"RUF048",
|
||||
"RUF05",
|
||||
"RUF051",
|
||||
"RUF052",
|
||||
"RUF055",
|
||||
"RUF1",
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue