mirror of
https://github.com/astral-sh/ruff.git
synced 2025-09-28 21:05:08 +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(
|
Stmt::Assert(
|
||||||
assert_stmt @ ast::StmtAssert {
|
assert_stmt @ ast::StmtAssert {
|
||||||
|
|
|
@ -222,7 +222,7 @@ pub(crate) struct Checker<'a> {
|
||||||
analyze: deferred::Analyze,
|
analyze: deferred::Analyze,
|
||||||
/// The cumulative set of diagnostics computed across all lint rules.
|
/// The cumulative set of diagnostics computed across all lint rules.
|
||||||
pub(crate) diagnostics: Vec<Diagnostic>,
|
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>,
|
pub(crate) flake8_bugbear_seen: Vec<TextRange>,
|
||||||
/// The end offset of the last visited statement.
|
/// The end offset of the last visited statement.
|
||||||
last_stmt_end: TextSize,
|
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, "041") => (RuleGroup::Preview, rules::ruff::rules::UnnecessaryNestedLiteral),
|
||||||
(Ruff, "046") => (RuleGroup::Preview, rules::ruff::rules::UnnecessaryCastToInt),
|
(Ruff, "046") => (RuleGroup::Preview, rules::ruff::rules::UnnecessaryCastToInt),
|
||||||
(Ruff, "048") => (RuleGroup::Preview, rules::ruff::rules::MapIntVersionParsing),
|
(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, "052") => (RuleGroup::Preview, rules::ruff::rules::UsedDummyVariable),
|
||||||
(Ruff, "055") => (RuleGroup::Preview, rules::ruff::rules::UnnecessaryRegularExpression),
|
(Ruff, "055") => (RuleGroup::Preview, rules::ruff::rules::UnnecessaryRegularExpression),
|
||||||
(Ruff, "100") => (RuleGroup::Stable, rules::ruff::rules::UnusedNOQA),
|
(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::InvalidAssertMessageLiteralArgument, Path::new("RUF040.py"))]
|
||||||
#[test_case(Rule::UnnecessaryNestedLiteral, Path::new("RUF041.py"))]
|
#[test_case(Rule::UnnecessaryNestedLiteral, Path::new("RUF041.py"))]
|
||||||
#[test_case(Rule::UnnecessaryNestedLiteral, Path::new("RUF041.pyi"))]
|
#[test_case(Rule::UnnecessaryNestedLiteral, Path::new("RUF041.pyi"))]
|
||||||
|
#[test_case(Rule::IfKeyInDictDel, Path::new("RUF051.py"))]
|
||||||
#[test_case(Rule::UsedDummyVariable, Path::new("RUF052.py"))]
|
#[test_case(Rule::UsedDummyVariable, Path::new("RUF052.py"))]
|
||||||
fn rules(rule_code: Rule, path: &Path) -> Result<()> {
|
fn rules(rule_code: Rule, path: &Path) -> Result<()> {
|
||||||
let snapshot = format!("{}_{}", rule_code.noqa_code(), path.to_string_lossy());
|
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 default_factory_kwarg::*;
|
||||||
pub(crate) use explicit_f_string_type_conversion::*;
|
pub(crate) use explicit_f_string_type_conversion::*;
|
||||||
pub(crate) use function_call_in_dataclass_default::*;
|
pub(crate) use function_call_in_dataclass_default::*;
|
||||||
|
pub(crate) use if_key_in_dict_del::*;
|
||||||
pub(crate) use implicit_optional::*;
|
pub(crate) use implicit_optional::*;
|
||||||
pub(crate) use incorrectly_parenthesized_tuple_in_subscript::*;
|
pub(crate) use incorrectly_parenthesized_tuple_in_subscript::*;
|
||||||
pub(crate) use invalid_assert_message_literal_argument::*;
|
pub(crate) use invalid_assert_message_literal_argument::*;
|
||||||
|
@ -54,6 +55,7 @@ mod default_factory_kwarg;
|
||||||
mod explicit_f_string_type_conversion;
|
mod explicit_f_string_type_conversion;
|
||||||
mod function_call_in_dataclass_default;
|
mod function_call_in_dataclass_default;
|
||||||
mod helpers;
|
mod helpers;
|
||||||
|
mod if_key_in_dict_del;
|
||||||
mod implicit_optional;
|
mod implicit_optional;
|
||||||
mod incorrectly_parenthesized_tuple_in_subscript;
|
mod incorrectly_parenthesized_tuple_in_subscript;
|
||||||
mod invalid_assert_message_literal_argument;
|
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",
|
"RUF046",
|
||||||
"RUF048",
|
"RUF048",
|
||||||
"RUF05",
|
"RUF05",
|
||||||
|
"RUF051",
|
||||||
"RUF052",
|
"RUF052",
|
||||||
"RUF055",
|
"RUF055",
|
||||||
"RUF1",
|
"RUF1",
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue