mirror of
https://github.com/astral-sh/ruff.git
synced 2025-10-02 14:51:25 +00:00
Ignore unnecessary dunder calls within dunder definitions (#9496)
Closes https://github.com/astral-sh/ruff/issues/9486.
This commit is contained in:
parent
009430e034
commit
957a1f35c4
3 changed files with 32 additions and 2 deletions
|
@ -24,6 +24,12 @@ class Thing:
|
||||||
super().__init__() # OK
|
super().__init__() # OK
|
||||||
super().__class__(stuff=(1, 2, 3)) # OK
|
super().__class__(stuff=(1, 2, 3)) # OK
|
||||||
|
|
||||||
|
def __getattribute__(self, item):
|
||||||
|
return object.__getattribute__(self, item) # OK
|
||||||
|
|
||||||
|
def do_thing(self, item):
|
||||||
|
return object.__getattribute__(self, item) # PLC2801
|
||||||
|
|
||||||
|
|
||||||
blah = lambda: {"a": 1}.__delitem__("a") # OK
|
blah = lambda: {"a": 1}.__delitem__("a") # OK
|
||||||
|
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
use ruff_diagnostics::{Diagnostic, Edit, Fix, FixAvailability, Violation};
|
use ruff_diagnostics::{Diagnostic, Edit, Fix, FixAvailability, Violation};
|
||||||
use ruff_macros::{derive_message_formats, violation};
|
use ruff_macros::{derive_message_formats, violation};
|
||||||
use ruff_python_ast::{self as ast, Expr};
|
use ruff_python_ast::{self as ast, Expr, Stmt};
|
||||||
use ruff_python_semantic::SemanticModel;
|
use ruff_python_semantic::SemanticModel;
|
||||||
use ruff_text_size::Ranged;
|
use ruff_text_size::Ranged;
|
||||||
|
|
||||||
|
@ -80,11 +80,17 @@ pub(crate) fn unnecessary_dunder_call(checker: &mut Checker, call: &ast::ExprCal
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Ignore certain dunder methods used in lambda expressions.
|
// Ignore certain dunder method calls in lambda expressions. These methods would require
|
||||||
|
// rewriting as a statement, which is not possible in a lambda expression.
|
||||||
if allow_nested_expression(attr, checker.semantic()) {
|
if allow_nested_expression(attr, checker.semantic()) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Ignore dunder method calls within dunder methods definitions.
|
||||||
|
if in_dunder_method_definition(checker.semantic()) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
// Ignore dunder methods used on `super`.
|
// Ignore dunder methods used on `super`.
|
||||||
if let Expr::Call(ast::ExprCall { func, .. }) = value.as_ref() {
|
if let Expr::Call(ast::ExprCall { func, .. }) = value.as_ref() {
|
||||||
if checker.semantic().is_builtin("super") {
|
if checker.semantic().is_builtin("super") {
|
||||||
|
@ -344,3 +350,13 @@ fn allow_nested_expression(dunder_name: &str, semantic: &SemanticModel) -> bool
|
||||||
| "__ior__"
|
| "__ior__"
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Returns `true` if the [`SemanticModel`] is currently in a dunder method definition.
|
||||||
|
fn in_dunder_method_definition(semantic: &SemanticModel) -> bool {
|
||||||
|
semantic.current_statements().any(|statement| {
|
||||||
|
let Stmt::FunctionDef(func_def) = statement else {
|
||||||
|
return false;
|
||||||
|
};
|
||||||
|
func_def.name.starts_with("__") && func_def.name.ends_with("__")
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
|
@ -321,4 +321,12 @@ unnecessary_dunder_call.py:19:7: PLC2801 Unnecessary dunder call to `__neg__`. M
|
||||||
|
|
|
|
||||||
= help: Multiply by -1 instead
|
= help: Multiply by -1 instead
|
||||||
|
|
||||||
|
unnecessary_dunder_call.py:31:16: PLC2801 Unnecessary dunder call to `__getattribute__`. Access attribute directly or use getattr built-in function.
|
||||||
|
|
|
||||||
|
30 | def do_thing(self, item):
|
||||||
|
31 | return object.__getattribute__(self, item) # PLC2801
|
||||||
|
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ PLC2801
|
||||||
|
|
|
||||||
|
= help: Access attribute directly or use getattr built-in function
|
||||||
|
|
||||||
|
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue