diff --git a/crates/ruff_linter/resources/test/fixtures/pylint/unnecessary_dunder_call.py b/crates/ruff_linter/resources/test/fixtures/pylint/unnecessary_dunder_call.py index 28d2626dfc953..17e433e9d7019 100644 --- a/crates/ruff_linter/resources/test/fixtures/pylint/unnecessary_dunder_call.py +++ b/crates/ruff_linter/resources/test/fixtures/pylint/unnecessary_dunder_call.py @@ -1,3 +1,6 @@ +from typing import Any + + print((3.0).__add__(4.0)) # PLC2801 print((3.0).__sub__(4.0)) # PLC2801 print((3.0).__mul__(4.0)) # PLC2801 @@ -13,8 +16,12 @@ print((3.0).__str__()) # PLC2801 print((3.0).__repr__()) # PLC2801 print([1, 2, 3].__len__()) # PLC2801 +print((1).__neg__()) # PLC2801 class Thing: - def __init__(self) -> None: + def __init__(self, stuff: Any) -> None: super().__init__() # Ok + super().__class__(stuff=(1, 2, 3)) # Ok + +blah = lambda: {"a": 1}.__delitem__("a") # Ok diff --git a/crates/ruff_linter/src/rules/pylint/rules/unnecessary_dunder_call.rs b/crates/ruff_linter/src/rules/pylint/rules/unnecessary_dunder_call.rs index 966c8d04f7530..1be67861d070e 100644 --- a/crates/ruff_linter/src/rules/pylint/rules/unnecessary_dunder_call.rs +++ b/crates/ruff_linter/src/rules/pylint/rules/unnecessary_dunder_call.rs @@ -6,6 +6,7 @@ use ruff_text_size::Ranged; use crate::checkers::ast::Checker; use crate::rules::pylint::helpers::is_known_dunder_method; +use crate::settings::types::PythonVersion; /// ## What it does /// Checks for explicit use of dunder methods. @@ -36,93 +37,35 @@ use crate::rules::pylint::helpers::is_known_dunder_method; #[violation] pub struct UnnecessaryDunderCall { call: String, + replacement: Option, } impl Violation for UnnecessaryDunderCall { const FIX_AVAILABILITY: FixAvailability = FixAvailability::Sometimes; #[derive_message_formats] fn message(&self) -> String { - let UnnecessaryDunderCall { call } = self; - format!("Unnecessary dunder call `{call}`") - } + let UnnecessaryDunderCall { call, replacement } = self; - fn fix_title(&self) -> Option { - Some(format!("Remove unnecessary dunder call")) + if let Some(replacement) = replacement { + format!("Unnecessary dunder call `{call}`. {replacement}",) + } else { + format!("Unnecessary dunder call `{call}`") + } } -} -fn get_operator(dunder_method: &str) -> Option<&str> { - match dunder_method { - "__add__" => Some("+"), - "__and__" => Some("&"), - "__contains__" => Some("in"), - "__eq__" => Some("=="), - "__floordiv__" => Some("//"), - "__ge__" => Some(">="), - "__gt__" => Some(">"), - "__iadd__" => Some("+="), - "__iand__" => Some("&="), - "__ifloordiv__" => Some("//="), - "__ilshift__" => Some("<<="), - "__imod__" => Some("%="), - "__imul__" => Some("*="), - "__ior__" => Some("|="), - "__ipow__" => Some("**="), - "__irshift__" => Some(">>="), - "__isub__" => Some("-="), - "__itruediv__" => Some("/="), - "__ixor__" => Some("^="), - "__le__" => Some("<="), - "__lshift__" => Some("<<"), - "__lt__" => Some("<"), - "__mod__" => Some("%"), - "__mul__" => Some("*"), - "__ne__" => Some("!="), - "__or__" => Some("|"), - "__rshift__" => Some(">>"), - "__sub__" => Some("-"), - "__truediv__" => Some("/"), - "__xor__" => Some("^"), - _ => None, - } -} - -fn get_r_operator(dunder_method: &str) -> Option<&str> { - match dunder_method { - "__radd__" => Some("+"), - "__rand__" => Some("&"), - "__rfloordiv__" => Some("//"), - "__rlshift__" => Some("<<"), - "__rmod__" => Some("%"), - "__rmul__" => Some("*"), - "__ror__" => Some("|"), - "__rrshift__" => Some(">>"), - "__rsub__" => Some("-"), - "__rtruediv__" => Some("/"), - "__rxor__" => Some("^"), - _ => None, + fn fix_title(&self) -> Option { + let UnnecessaryDunderCall { + replacement: title, .. + } = self; + title.clone() } } -fn get_builtin(dunder_method: &str) -> Option<&str> { - match dunder_method { - "__abs__" => Some("abs"), - "__bool__" => Some("bool"), - "__bytes__" => Some("bytes"), - "__complex__" => Some("complex"), - "__dir__" => Some("dir"), - "__float__" => Some("float"), - "__hash__" => Some("hash"), - "__int__" => Some("int"), - "__iter__" => Some("iter"), - "__len__" => Some("len"), - "__next__" => Some("next"), - "__repr__" => Some("repr"), - "__reversed__" => Some("reversed"), - "__round__" => Some("round"), - "__str__" => Some("str"), - _ => None, - } +enum DunderMethod { + Operator, + ROperator, + Builtin, + MessageOnly, // has no replacements implemented } /// PLC2801 @@ -142,47 +85,85 @@ pub(crate) fn unnecessary_dunder_call(checker: &mut Checker, expr: &Expr) { return; } - // skip common/irreplaceable dunder methods - if ["__init__", "__new__", "__init_subclass__", "__subclasses__"].contains(&attr.as_str()) { + if allowed_dunder_constants(attr) { + // if this is a dunder method that is allowed to be called explicitly, skip! + return; + } + + // ignore dunder methods used on "super" + if let Expr::Call(ast::ExprCall { func, .. }) = value.as_ref() { + if checker.semantic().is_builtin("super") { + if let Expr::Name(ast::ExprName { id, .. }) = func.as_ref() { + if id == "super" { + return; + } + } + } + } + + if is_excusable_lambda_exception(checker, attr) { + // if this is taking place within a lambda expression with a specific dunder method, skip! + return; + } + + if ignore_older_dunders(checker, attr) { + // if this is an older dunder method, skip! return; } let mut fixed: Option = None; + let mut title: Option = None; - match arguments.args.len() { - 0 => { - if let Some(builtin) = get_builtin(attr) { - if !checker.semantic().is_builtin(builtin) { + if let Some((replacement, message, dunder_type)) = dunder_constants(attr) { + match (arguments.args.len(), dunder_type) { + (0, DunderMethod::Builtin) => { + if !checker.semantic().is_builtin(replacement) { // duck out if the builtin was shadowed return; } - fixed = Some(format!("{}({})", builtin, checker.generator().expr(value))); + fixed = Some(format!( + "{}({})", + replacement, + checker.generator().expr(value) + )); + title = Some(message.to_string()); } - } - 1 => { - if let Some(operator) = get_operator(attr) { + (1, DunderMethod::Operator) => { fixed = Some(format!( "{} {} {}", checker.generator().expr(value), - operator, + replacement, checker.generator().expr(arguments.args.first().unwrap()), )); - } else if let Some(operator) = get_r_operator(attr) { + title = Some(message.to_string()); + } + (1, DunderMethod::ROperator) => { fixed = Some(format!( "{} {} {}", checker.generator().expr(arguments.args.first().unwrap()), - operator, + replacement, checker.generator().expr(value), )); + title = Some(message.to_string()); + } + _ => {} + } + } else if let Some((message, dunder_type)) = unimplemented_fix_dunder_constants(attr) { + match dunder_type { + DunderMethod::MessageOnly => { + title = Some(message.to_string()); + } + _ => { + panic!("Dunder methods in the `unimplemented_fix_dunder_constants` list must have the `MessageOnly` enum!") } } - _ => {} } let mut diagnostic = Diagnostic::new( UnnecessaryDunderCall { call: checker.generator().expr(expr), + replacement: title, }, expr.range(), ); @@ -193,3 +174,211 @@ pub(crate) fn unnecessary_dunder_call(checker: &mut Checker, expr: &Expr) { checker.diagnostics.push(diagnostic); } + +fn allowed_dunder_constants(dunder_method: &str) -> bool { + // these are dunder methods that are allowed to be called explicitly + // please keep this list tidy when adding/removing entries! + [ + "__aexit__", + "__await__", + "__class__", + "__class_getitem__", + "__dict__", + "__doc__", + "__exit__", + "__getnewargs__", + "__getnewargs_ex__", + "__getstate__", + "__index__", + "__init_subclass__", + "__missing__", + "__module__", + "__new__", + "__post_init__", + "__reduce__", + "__reduce_ex__", + "__set_name__", + "__setstate__", + "__sizeof__", + "__subclasses__", + "__subclasshook__", + "__weakref__", + ] + .contains(&dunder_method) +} + +fn dunder_constants(dunder_method: &str) -> Option<(&str, &str, DunderMethod)> { + // (replacement, message, dunder_type) + match dunder_method { + "__add__" => Some(("+", "Use `+` operator.", DunderMethod::Operator)), + "__and__" => Some(("&", "Use `&` operator.", DunderMethod::Operator)), + "__contains__" => Some(("in", "Use `in` operator.", DunderMethod::Operator)), + "__eq__" => Some(("==", "Use `==` operator.", DunderMethod::Operator)), + "__floordiv__" => Some(("//", "Use `//` operator.", DunderMethod::Operator)), + "__ge__" => Some((">=", "Use `>=` operator.", DunderMethod::Operator)), + "__gt__" => Some((">", "Use `>` operator.", DunderMethod::Operator)), + "__iadd__" => Some(("+=", "Use `+=` operator.", DunderMethod::Operator)), + "__iand__" => Some(("&=", "Use `&=` operator.", DunderMethod::Operator)), + "__ifloordiv__" => Some(("//=", "Use `//=` operator.", DunderMethod::Operator)), + "__ilshift__" => Some(("<<=", "Use `<<=` operator.", DunderMethod::Operator)), + "__imod__" => Some(("%=", "Use `%=` operator.", DunderMethod::Operator)), + "__imul__" => Some(("*=", "Use `*=` operator.", DunderMethod::Operator)), + "__ior__" => Some(("|=", "Use `|=` operator.", DunderMethod::Operator)), + "__ipow__" => Some(("**=", "Use `**=` operator.", DunderMethod::Operator)), + "__irshift__" => Some((">>=", "Use `>>=` operator.", DunderMethod::Operator)), + "__isub__" => Some(("-=", "Use `-=` operator.", DunderMethod::Operator)), + "__itruediv__" => Some(("/=", "Use `/=` operator.", DunderMethod::Operator)), + "__ixor__" => Some(("^=", "Use `^=` operator.", DunderMethod::Operator)), + "__le__" => Some(("<=", "Use `<=` operator.", DunderMethod::Operator)), + "__lshift__" => Some(("<<", "Use `<<` operator.", DunderMethod::Operator)), + "__lt__" => Some(("<", "Use `<` operator.", DunderMethod::Operator)), + "__mod__" => Some(("%", "Use `%` operator.", DunderMethod::Operator)), + "__mul__" => Some(("*", "Use `*` operator.", DunderMethod::Operator)), + "__ne__" => Some(("!=", "Use `!=` operator.", DunderMethod::Operator)), + "__or__" => Some(("|", "Use `|` operator.", DunderMethod::Operator)), + "__rshift__" => Some((">>", "Use `>>` operator.", DunderMethod::Operator)), + "__sub__" => Some(("-", "Use `-` operator.", DunderMethod::Operator)), + "__truediv__" => Some(("/", "Use `/` operator.", DunderMethod::Operator)), + "__xor__" => Some(("^", "Use `^` operator.", DunderMethod::Operator)), + + "__radd__" => Some(("+", "Use `+` operator.", DunderMethod::ROperator)), + "__rand__" => Some(("&", "Use `&` operator.", DunderMethod::ROperator)), + "__rfloordiv__" => Some(("//", "Use `//` operator.", DunderMethod::ROperator)), + "__rlshift__" => Some(("<<", "Use `<<` operator.", DunderMethod::ROperator)), + "__rmod__" => Some(("%", "Use `%` operator.", DunderMethod::ROperator)), + "__rmul__" => Some(("*", "Use `*` operator.", DunderMethod::ROperator)), + "__ror__" => Some(("|", "Use `|` operator.", DunderMethod::ROperator)), + "__rrshift__" => Some((">>", "Use `>>` operator.", DunderMethod::ROperator)), + "__rsub__" => Some(("-", "Use `-` operator.", DunderMethod::ROperator)), + "__rtruediv__" => Some(("/", "Use `/` operator.", DunderMethod::ROperator)), + "__rxor__" => Some(("^", "Use `^` operator.", DunderMethod::ROperator)), + + "__aiter__" => Some(("aiter", "Use `aiter()` builtin.", DunderMethod::Builtin)), + "__anext__" => Some(("anext", "Use `anext()` builtin.", DunderMethod::Builtin)), + "__abs__" => Some(("abs", "Use `abs()` builtin.", DunderMethod::Builtin)), + "__bool__" => Some(("bool", "Use `bool()` builtin.", DunderMethod::Builtin)), + "__bytes__" => Some(("bytes", "Use `bytes()` builtin.", DunderMethod::Builtin)), + "__complex__" => Some(("complex", "Use `complex()` builtin.", DunderMethod::Builtin)), + "__dir__" => Some(("dir", "Use `dir()` builtin.", DunderMethod::Builtin)), + "__float__" => Some(("float", "Use `float()` builtin.", DunderMethod::Builtin)), + "__hash__" => Some(("hash", "Use `hash()` builtin.", DunderMethod::Builtin)), + "__int__" => Some(("int", "Use `int()` builtin.", DunderMethod::Builtin)), + "__iter__" => Some(("iter", "Use `iter()` builtin.", DunderMethod::Builtin)), + "__len__" => Some(("len", "Use `len()` builtin.", DunderMethod::Builtin)), + "__next__" => Some(("next", "Use `next()` builtin.", DunderMethod::Builtin)), + "__repr__" => Some(("repr", "Use `repr()` builtin.", DunderMethod::Builtin)), + "__reversed__" => Some(( + "reversed", + "Use `reversed()` builtin.", + DunderMethod::Builtin, + )), + "__round__" => Some(("round", "Use `round()` builtin.", DunderMethod::Builtin)), + "__str__" => Some(("str", "Use `str()` builtin.", DunderMethod::Builtin)), + "__subclasscheck__" => Some(( + "issubclass", + "Use `issubclass()` builtin.", + DunderMethod::Builtin, + )), + + _ => None, + } +} + +fn unimplemented_fix_dunder_constants(dunder_method: &str) -> Option<(&str, DunderMethod)> { + // (replacement, dunder_type) + // these are dunder methods that have no replacements implemented + // please keep this list tidy when adding/removing entries! + match dunder_method { + "__aenter__" => Some(("Use `aenter()` builtin.", DunderMethod::MessageOnly)), + "__ceil__" => Some(("Use `math.ceil()` function.", DunderMethod::MessageOnly)), + "__copy__" => Some(("Use `copy.copy()` function.", DunderMethod::MessageOnly)), + "__deepcopy__" => Some(("Use `copy.deepcopy()` function.", DunderMethod::MessageOnly)), + "__del__" => Some(("Use `del` statement.", DunderMethod::MessageOnly)), + "__delattr__" => Some(("Use `del` statement.", DunderMethod::MessageOnly)), + "__delete__" => Some(("Use `del` statement.", DunderMethod::MessageOnly)), + "__delitem__" => Some(("Use `del` statement.", DunderMethod::MessageOnly)), + "__divmod__" => Some(("Use `divmod()` builtin.", DunderMethod::MessageOnly)), + "__format__" => Some(( + "Use `format` builtin, format string method, or f-string.", + DunderMethod::MessageOnly, + )), + "__fspath__" => Some(("Use `os.fspath` function.", DunderMethod::MessageOnly)), + "__get__" => Some(("Use `get` method.", DunderMethod::MessageOnly)), + "__getattr__" => Some(( + "Access attribute directly or use getattr built-in function.", + DunderMethod::MessageOnly, + )), + "__getattribute__" => Some(( + "Access attribute directly or use getattr built-in function.", + DunderMethod::MessageOnly, + )), + "__getitem__" => Some(("Access item via subscript.", DunderMethod::MessageOnly)), + "__init__" => Some(("Instantiate class directly.", DunderMethod::MessageOnly)), + "__instancecheck__" => Some(("Use `isinstance()` builtin.", DunderMethod::MessageOnly)), + "__invert__" => Some(("Use `~` operator.", DunderMethod::MessageOnly)), + "__neg__" => Some(("Multiply by -1 instead.", DunderMethod::MessageOnly)), + "__pos__" => Some(("Multiply by +1 instead.", DunderMethod::MessageOnly)), + "__pow__" => Some(( + "Use ** operator or `pow()` builtin.", + DunderMethod::MessageOnly, + )), + "__rdivmod__" => Some(("Use `divmod()` builtin.", DunderMethod::MessageOnly)), + "__rpow__" => Some(( + "Use ** operator or `pow()` builtin.", + DunderMethod::MessageOnly, + )), + "__set__" => Some(("Use subscript assignment.", DunderMethod::MessageOnly)), + "__setattr__" => Some(( + "Mutate attribute directly or use setattr built-in function.", + DunderMethod::MessageOnly, + )), + "__setitem__" => Some(("Use subscript assignment.", DunderMethod::MessageOnly)), + "__truncate__" => Some(("Use `math.trunc()` function.", DunderMethod::MessageOnly)), + _ => None, + } +} + +fn is_excusable_lambda_exception(checker: &mut Checker, dunder_name: &str) -> bool { + // if this is taking place within a lambda expression with a specific dunder method, return true! + // some dunder method replacements are unrepresentable in lambdas. + let is_parent_lambda = checker.semantic().current_scope().kind.is_lambda(); + + if !is_parent_lambda { + return false; + } + + let unnecessary_dunder_call_lambda_exceptions = [ + "__init__", + "__del__", + "__delattr__", + "__set__", + "__delete__", + "__setitem__", + "__delitem__", + "__iadd__", + "__isub__", + "__imul__", + "__imatmul__", + "__itruediv__", + "__ifloordiv__", + "__imod__", + "__ipow__", + "__ilshift__", + "__irshift__", + "__iand__", + "__ixor__", + "__ior__", + ]; + + unnecessary_dunder_call_lambda_exceptions.contains(&dunder_name) +} + +fn ignore_older_dunders(checker: &mut Checker, dunder_name: &str) -> bool { + if checker.settings.target_version < PythonVersion::Py310 { + if ["__aiter__", "__anext__"].contains(&dunder_name) { + return true; + } + } + + false +} diff --git a/crates/ruff_linter/src/rules/pylint/snapshots/ruff_linter__rules__pylint__tests__PLC2801_unnecessary_dunder_call.py.snap b/crates/ruff_linter/src/rules/pylint/snapshots/ruff_linter__rules__pylint__tests__PLC2801_unnecessary_dunder_call.py.snap index 87e9b9b552f70..d10a6b87fa4f0 100644 --- a/crates/ruff_linter/src/rules/pylint/snapshots/ruff_linter__rules__pylint__tests__PLC2801_unnecessary_dunder_call.py.snap +++ b/crates/ruff_linter/src/rules/pylint/snapshots/ruff_linter__rules__pylint__tests__PLC2801_unnecessary_dunder_call.py.snap @@ -1,307 +1,324 @@ --- source: crates/ruff_linter/src/rules/pylint/mod.rs --- -unnecessary_dunder_call.py:1:7: PLC2801 [*] Unnecessary dunder call `3.0.__add__(4.0)` +unnecessary_dunder_call.py:4:7: PLC2801 [*] Unnecessary dunder call `3.0.__add__(4.0)`. Use `+` operator. | -1 | print((3.0).__add__(4.0)) # PLC2801 +4 | print((3.0).__add__(4.0)) # PLC2801 | ^^^^^^^^^^^^^^^^^^ PLC2801 -2 | print((3.0).__sub__(4.0)) # PLC2801 -3 | print((3.0).__mul__(4.0)) # PLC2801 +5 | print((3.0).__sub__(4.0)) # PLC2801 +6 | print((3.0).__mul__(4.0)) # PLC2801 | - = help: Remove unnecessary dunder call + = help: Use `+` operator. ℹ Safe fix -1 |-print((3.0).__add__(4.0)) # PLC2801 - 1 |+print(3.0 + 4.0) # PLC2801 -2 2 | print((3.0).__sub__(4.0)) # PLC2801 -3 3 | print((3.0).__mul__(4.0)) # PLC2801 -4 4 | print((3.0).__truediv__(4.0)) # PLC2801 +1 1 | from typing import Any +2 2 | +3 3 | +4 |-print((3.0).__add__(4.0)) # PLC2801 + 4 |+print(3.0 + 4.0) # PLC2801 +5 5 | print((3.0).__sub__(4.0)) # PLC2801 +6 6 | print((3.0).__mul__(4.0)) # PLC2801 +7 7 | print((3.0).__truediv__(4.0)) # PLC2801 -unnecessary_dunder_call.py:2:7: PLC2801 [*] Unnecessary dunder call `3.0.__sub__(4.0)` +unnecessary_dunder_call.py:5:7: PLC2801 [*] Unnecessary dunder call `3.0.__sub__(4.0)`. Use `-` operator. | -1 | print((3.0).__add__(4.0)) # PLC2801 -2 | print((3.0).__sub__(4.0)) # PLC2801 +4 | print((3.0).__add__(4.0)) # PLC2801 +5 | print((3.0).__sub__(4.0)) # PLC2801 | ^^^^^^^^^^^^^^^^^^ PLC2801 -3 | print((3.0).__mul__(4.0)) # PLC2801 -4 | print((3.0).__truediv__(4.0)) # PLC2801 +6 | print((3.0).__mul__(4.0)) # PLC2801 +7 | print((3.0).__truediv__(4.0)) # PLC2801 | - = help: Remove unnecessary dunder call + = help: Use `-` operator. ℹ Safe fix -1 1 | print((3.0).__add__(4.0)) # PLC2801 -2 |-print((3.0).__sub__(4.0)) # PLC2801 - 2 |+print(3.0 - 4.0) # PLC2801 -3 3 | print((3.0).__mul__(4.0)) # PLC2801 -4 4 | print((3.0).__truediv__(4.0)) # PLC2801 -5 5 | print((3.0).__floordiv__(4.0)) # PLC2801 - -unnecessary_dunder_call.py:3:7: PLC2801 [*] Unnecessary dunder call `3.0.__mul__(4.0)` +2 2 | +3 3 | +4 4 | print((3.0).__add__(4.0)) # PLC2801 +5 |-print((3.0).__sub__(4.0)) # PLC2801 + 5 |+print(3.0 - 4.0) # PLC2801 +6 6 | print((3.0).__mul__(4.0)) # PLC2801 +7 7 | print((3.0).__truediv__(4.0)) # PLC2801 +8 8 | print((3.0).__floordiv__(4.0)) # PLC2801 + +unnecessary_dunder_call.py:6:7: PLC2801 [*] Unnecessary dunder call `3.0.__mul__(4.0)`. Use `*` operator. | -1 | print((3.0).__add__(4.0)) # PLC2801 -2 | print((3.0).__sub__(4.0)) # PLC2801 -3 | print((3.0).__mul__(4.0)) # PLC2801 +4 | print((3.0).__add__(4.0)) # PLC2801 +5 | print((3.0).__sub__(4.0)) # PLC2801 +6 | print((3.0).__mul__(4.0)) # PLC2801 | ^^^^^^^^^^^^^^^^^^ PLC2801 -4 | print((3.0).__truediv__(4.0)) # PLC2801 -5 | print((3.0).__floordiv__(4.0)) # PLC2801 +7 | print((3.0).__truediv__(4.0)) # PLC2801 +8 | print((3.0).__floordiv__(4.0)) # PLC2801 | - = help: Remove unnecessary dunder call + = help: Use `*` operator. ℹ Safe fix -1 1 | print((3.0).__add__(4.0)) # PLC2801 -2 2 | print((3.0).__sub__(4.0)) # PLC2801 -3 |-print((3.0).__mul__(4.0)) # PLC2801 - 3 |+print(3.0 * 4.0) # PLC2801 -4 4 | print((3.0).__truediv__(4.0)) # PLC2801 -5 5 | print((3.0).__floordiv__(4.0)) # PLC2801 -6 6 | print((3.0).__mod__(4.0)) # PLC2801 - -unnecessary_dunder_call.py:4:7: PLC2801 [*] Unnecessary dunder call `3.0.__truediv__(4.0)` +3 3 | +4 4 | print((3.0).__add__(4.0)) # PLC2801 +5 5 | print((3.0).__sub__(4.0)) # PLC2801 +6 |-print((3.0).__mul__(4.0)) # PLC2801 + 6 |+print(3.0 * 4.0) # PLC2801 +7 7 | print((3.0).__truediv__(4.0)) # PLC2801 +8 8 | print((3.0).__floordiv__(4.0)) # PLC2801 +9 9 | print((3.0).__mod__(4.0)) # PLC2801 + +unnecessary_dunder_call.py:7:7: PLC2801 [*] Unnecessary dunder call `3.0.__truediv__(4.0)`. Use `/` operator. | -2 | print((3.0).__sub__(4.0)) # PLC2801 -3 | print((3.0).__mul__(4.0)) # PLC2801 -4 | print((3.0).__truediv__(4.0)) # PLC2801 +5 | print((3.0).__sub__(4.0)) # PLC2801 +6 | print((3.0).__mul__(4.0)) # PLC2801 +7 | print((3.0).__truediv__(4.0)) # PLC2801 | ^^^^^^^^^^^^^^^^^^^^^^ PLC2801 -5 | print((3.0).__floordiv__(4.0)) # PLC2801 -6 | print((3.0).__mod__(4.0)) # PLC2801 +8 | print((3.0).__floordiv__(4.0)) # PLC2801 +9 | print((3.0).__mod__(4.0)) # PLC2801 | - = help: Remove unnecessary dunder call + = help: Use `/` operator. ℹ Safe fix -1 1 | print((3.0).__add__(4.0)) # PLC2801 -2 2 | print((3.0).__sub__(4.0)) # PLC2801 -3 3 | print((3.0).__mul__(4.0)) # PLC2801 -4 |-print((3.0).__truediv__(4.0)) # PLC2801 - 4 |+print(3.0 / 4.0) # PLC2801 -5 5 | print((3.0).__floordiv__(4.0)) # PLC2801 -6 6 | print((3.0).__mod__(4.0)) # PLC2801 -7 7 | print((3.0).__eq__(4.0)) # PLC2801 - -unnecessary_dunder_call.py:5:7: PLC2801 [*] Unnecessary dunder call `3.0.__floordiv__(4.0)` - | -3 | print((3.0).__mul__(4.0)) # PLC2801 -4 | print((3.0).__truediv__(4.0)) # PLC2801 -5 | print((3.0).__floordiv__(4.0)) # PLC2801 - | ^^^^^^^^^^^^^^^^^^^^^^^ PLC2801 -6 | print((3.0).__mod__(4.0)) # PLC2801 -7 | print((3.0).__eq__(4.0)) # PLC2801 - | - = help: Remove unnecessary dunder call +4 4 | print((3.0).__add__(4.0)) # PLC2801 +5 5 | print((3.0).__sub__(4.0)) # PLC2801 +6 6 | print((3.0).__mul__(4.0)) # PLC2801 +7 |-print((3.0).__truediv__(4.0)) # PLC2801 + 7 |+print(3.0 / 4.0) # PLC2801 +8 8 | print((3.0).__floordiv__(4.0)) # PLC2801 +9 9 | print((3.0).__mod__(4.0)) # PLC2801 +10 10 | print((3.0).__eq__(4.0)) # PLC2801 + +unnecessary_dunder_call.py:8:7: PLC2801 [*] Unnecessary dunder call `3.0.__floordiv__(4.0)`. Use `//` operator. + | + 6 | print((3.0).__mul__(4.0)) # PLC2801 + 7 | print((3.0).__truediv__(4.0)) # PLC2801 + 8 | print((3.0).__floordiv__(4.0)) # PLC2801 + | ^^^^^^^^^^^^^^^^^^^^^^^ PLC2801 + 9 | print((3.0).__mod__(4.0)) # PLC2801 +10 | print((3.0).__eq__(4.0)) # PLC2801 + | + = help: Use `//` operator. ℹ Safe fix -2 2 | print((3.0).__sub__(4.0)) # PLC2801 -3 3 | print((3.0).__mul__(4.0)) # PLC2801 -4 4 | print((3.0).__truediv__(4.0)) # PLC2801 -5 |-print((3.0).__floordiv__(4.0)) # PLC2801 - 5 |+print(3.0 // 4.0) # PLC2801 -6 6 | print((3.0).__mod__(4.0)) # PLC2801 -7 7 | print((3.0).__eq__(4.0)) # PLC2801 -8 8 | print((3.0).__ne__(4.0)) # PLC2801 - -unnecessary_dunder_call.py:6:7: PLC2801 [*] Unnecessary dunder call `3.0.__mod__(4.0)` - | -4 | print((3.0).__truediv__(4.0)) # PLC2801 -5 | print((3.0).__floordiv__(4.0)) # PLC2801 -6 | print((3.0).__mod__(4.0)) # PLC2801 - | ^^^^^^^^^^^^^^^^^^ PLC2801 -7 | print((3.0).__eq__(4.0)) # PLC2801 -8 | print((3.0).__ne__(4.0)) # PLC2801 - | - = help: Remove unnecessary dunder call +5 5 | print((3.0).__sub__(4.0)) # PLC2801 +6 6 | print((3.0).__mul__(4.0)) # PLC2801 +7 7 | print((3.0).__truediv__(4.0)) # PLC2801 +8 |-print((3.0).__floordiv__(4.0)) # PLC2801 + 8 |+print(3.0 // 4.0) # PLC2801 +9 9 | print((3.0).__mod__(4.0)) # PLC2801 +10 10 | print((3.0).__eq__(4.0)) # PLC2801 +11 11 | print((3.0).__ne__(4.0)) # PLC2801 + +unnecessary_dunder_call.py:9:7: PLC2801 [*] Unnecessary dunder call `3.0.__mod__(4.0)`. Use `%` operator. + | + 7 | print((3.0).__truediv__(4.0)) # PLC2801 + 8 | print((3.0).__floordiv__(4.0)) # PLC2801 + 9 | print((3.0).__mod__(4.0)) # PLC2801 + | ^^^^^^^^^^^^^^^^^^ PLC2801 +10 | print((3.0).__eq__(4.0)) # PLC2801 +11 | print((3.0).__ne__(4.0)) # PLC2801 + | + = help: Use `%` operator. ℹ Safe fix -3 3 | print((3.0).__mul__(4.0)) # PLC2801 -4 4 | print((3.0).__truediv__(4.0)) # PLC2801 -5 5 | print((3.0).__floordiv__(4.0)) # PLC2801 -6 |-print((3.0).__mod__(4.0)) # PLC2801 - 6 |+print(3.0 % 4.0) # PLC2801 -7 7 | print((3.0).__eq__(4.0)) # PLC2801 -8 8 | print((3.0).__ne__(4.0)) # PLC2801 -9 9 | print((3.0).__lt__(4.0)) # PLC2801 - -unnecessary_dunder_call.py:7:7: PLC2801 [*] Unnecessary dunder call `3.0.__eq__(4.0)` - | -5 | print((3.0).__floordiv__(4.0)) # PLC2801 -6 | print((3.0).__mod__(4.0)) # PLC2801 -7 | print((3.0).__eq__(4.0)) # PLC2801 - | ^^^^^^^^^^^^^^^^^ PLC2801 -8 | print((3.0).__ne__(4.0)) # PLC2801 -9 | print((3.0).__lt__(4.0)) # PLC2801 - | - = help: Remove unnecessary dunder call +6 6 | print((3.0).__mul__(4.0)) # PLC2801 +7 7 | print((3.0).__truediv__(4.0)) # PLC2801 +8 8 | print((3.0).__floordiv__(4.0)) # PLC2801 +9 |-print((3.0).__mod__(4.0)) # PLC2801 + 9 |+print(3.0 % 4.0) # PLC2801 +10 10 | print((3.0).__eq__(4.0)) # PLC2801 +11 11 | print((3.0).__ne__(4.0)) # PLC2801 +12 12 | print((3.0).__lt__(4.0)) # PLC2801 + +unnecessary_dunder_call.py:10:7: PLC2801 [*] Unnecessary dunder call `3.0.__eq__(4.0)`. Use `==` operator. + | + 8 | print((3.0).__floordiv__(4.0)) # PLC2801 + 9 | print((3.0).__mod__(4.0)) # PLC2801 +10 | print((3.0).__eq__(4.0)) # PLC2801 + | ^^^^^^^^^^^^^^^^^ PLC2801 +11 | print((3.0).__ne__(4.0)) # PLC2801 +12 | print((3.0).__lt__(4.0)) # PLC2801 + | + = help: Use `==` operator. ℹ Safe fix -4 4 | print((3.0).__truediv__(4.0)) # PLC2801 -5 5 | print((3.0).__floordiv__(4.0)) # PLC2801 -6 6 | print((3.0).__mod__(4.0)) # PLC2801 -7 |-print((3.0).__eq__(4.0)) # PLC2801 - 7 |+print(3.0 == 4.0) # PLC2801 -8 8 | print((3.0).__ne__(4.0)) # PLC2801 -9 9 | print((3.0).__lt__(4.0)) # PLC2801 -10 10 | print((3.0).__le__(4.0)) # PLC2801 - -unnecessary_dunder_call.py:8:7: PLC2801 [*] Unnecessary dunder call `3.0.__ne__(4.0)` +7 7 | print((3.0).__truediv__(4.0)) # PLC2801 +8 8 | print((3.0).__floordiv__(4.0)) # PLC2801 +9 9 | print((3.0).__mod__(4.0)) # PLC2801 +10 |-print((3.0).__eq__(4.0)) # PLC2801 + 10 |+print(3.0 == 4.0) # PLC2801 +11 11 | print((3.0).__ne__(4.0)) # PLC2801 +12 12 | print((3.0).__lt__(4.0)) # PLC2801 +13 13 | print((3.0).__le__(4.0)) # PLC2801 + +unnecessary_dunder_call.py:11:7: PLC2801 [*] Unnecessary dunder call `3.0.__ne__(4.0)`. Use `!=` operator. | - 6 | print((3.0).__mod__(4.0)) # PLC2801 - 7 | print((3.0).__eq__(4.0)) # PLC2801 - 8 | print((3.0).__ne__(4.0)) # PLC2801 + 9 | print((3.0).__mod__(4.0)) # PLC2801 +10 | print((3.0).__eq__(4.0)) # PLC2801 +11 | print((3.0).__ne__(4.0)) # PLC2801 | ^^^^^^^^^^^^^^^^^ PLC2801 - 9 | print((3.0).__lt__(4.0)) # PLC2801 -10 | print((3.0).__le__(4.0)) # PLC2801 +12 | print((3.0).__lt__(4.0)) # PLC2801 +13 | print((3.0).__le__(4.0)) # PLC2801 | - = help: Remove unnecessary dunder call + = help: Use `!=` operator. ℹ Safe fix -5 5 | print((3.0).__floordiv__(4.0)) # PLC2801 -6 6 | print((3.0).__mod__(4.0)) # PLC2801 -7 7 | print((3.0).__eq__(4.0)) # PLC2801 -8 |-print((3.0).__ne__(4.0)) # PLC2801 - 8 |+print(3.0 != 4.0) # PLC2801 -9 9 | print((3.0).__lt__(4.0)) # PLC2801 -10 10 | print((3.0).__le__(4.0)) # PLC2801 -11 11 | print((3.0).__gt__(4.0)) # PLC2801 - -unnecessary_dunder_call.py:9:7: PLC2801 [*] Unnecessary dunder call `3.0.__lt__(4.0)` +8 8 | print((3.0).__floordiv__(4.0)) # PLC2801 +9 9 | print((3.0).__mod__(4.0)) # PLC2801 +10 10 | print((3.0).__eq__(4.0)) # PLC2801 +11 |-print((3.0).__ne__(4.0)) # PLC2801 + 11 |+print(3.0 != 4.0) # PLC2801 +12 12 | print((3.0).__lt__(4.0)) # PLC2801 +13 13 | print((3.0).__le__(4.0)) # PLC2801 +14 14 | print((3.0).__gt__(4.0)) # PLC2801 + +unnecessary_dunder_call.py:12:7: PLC2801 [*] Unnecessary dunder call `3.0.__lt__(4.0)`. Use `<` operator. | - 7 | print((3.0).__eq__(4.0)) # PLC2801 - 8 | print((3.0).__ne__(4.0)) # PLC2801 - 9 | print((3.0).__lt__(4.0)) # PLC2801 +10 | print((3.0).__eq__(4.0)) # PLC2801 +11 | print((3.0).__ne__(4.0)) # PLC2801 +12 | print((3.0).__lt__(4.0)) # PLC2801 | ^^^^^^^^^^^^^^^^^ PLC2801 -10 | print((3.0).__le__(4.0)) # PLC2801 -11 | print((3.0).__gt__(4.0)) # PLC2801 +13 | print((3.0).__le__(4.0)) # PLC2801 +14 | print((3.0).__gt__(4.0)) # PLC2801 | - = help: Remove unnecessary dunder call + = help: Use `<` operator. ℹ Safe fix -6 6 | print((3.0).__mod__(4.0)) # PLC2801 -7 7 | print((3.0).__eq__(4.0)) # PLC2801 -8 8 | print((3.0).__ne__(4.0)) # PLC2801 -9 |-print((3.0).__lt__(4.0)) # PLC2801 - 9 |+print(3.0 < 4.0) # PLC2801 -10 10 | print((3.0).__le__(4.0)) # PLC2801 -11 11 | print((3.0).__gt__(4.0)) # PLC2801 -12 12 | print((3.0).__ge__(4.0)) # PLC2801 - -unnecessary_dunder_call.py:10:7: PLC2801 [*] Unnecessary dunder call `3.0.__le__(4.0)` +9 9 | print((3.0).__mod__(4.0)) # PLC2801 +10 10 | print((3.0).__eq__(4.0)) # PLC2801 +11 11 | print((3.0).__ne__(4.0)) # PLC2801 +12 |-print((3.0).__lt__(4.0)) # PLC2801 + 12 |+print(3.0 < 4.0) # PLC2801 +13 13 | print((3.0).__le__(4.0)) # PLC2801 +14 14 | print((3.0).__gt__(4.0)) # PLC2801 +15 15 | print((3.0).__ge__(4.0)) # PLC2801 + +unnecessary_dunder_call.py:13:7: PLC2801 [*] Unnecessary dunder call `3.0.__le__(4.0)`. Use `<=` operator. | - 8 | print((3.0).__ne__(4.0)) # PLC2801 - 9 | print((3.0).__lt__(4.0)) # PLC2801 -10 | print((3.0).__le__(4.0)) # PLC2801 +11 | print((3.0).__ne__(4.0)) # PLC2801 +12 | print((3.0).__lt__(4.0)) # PLC2801 +13 | print((3.0).__le__(4.0)) # PLC2801 | ^^^^^^^^^^^^^^^^^ PLC2801 -11 | print((3.0).__gt__(4.0)) # PLC2801 -12 | print((3.0).__ge__(4.0)) # PLC2801 +14 | print((3.0).__gt__(4.0)) # PLC2801 +15 | print((3.0).__ge__(4.0)) # PLC2801 | - = help: Remove unnecessary dunder call + = help: Use `<=` operator. ℹ Safe fix -7 7 | print((3.0).__eq__(4.0)) # PLC2801 -8 8 | print((3.0).__ne__(4.0)) # PLC2801 -9 9 | print((3.0).__lt__(4.0)) # PLC2801 -10 |-print((3.0).__le__(4.0)) # PLC2801 - 10 |+print(3.0 <= 4.0) # PLC2801 -11 11 | print((3.0).__gt__(4.0)) # PLC2801 -12 12 | print((3.0).__ge__(4.0)) # PLC2801 -13 13 | print((3.0).__str__()) # PLC2801 - -unnecessary_dunder_call.py:11:7: PLC2801 [*] Unnecessary dunder call `3.0.__gt__(4.0)` +10 10 | print((3.0).__eq__(4.0)) # PLC2801 +11 11 | print((3.0).__ne__(4.0)) # PLC2801 +12 12 | print((3.0).__lt__(4.0)) # PLC2801 +13 |-print((3.0).__le__(4.0)) # PLC2801 + 13 |+print(3.0 <= 4.0) # PLC2801 +14 14 | print((3.0).__gt__(4.0)) # PLC2801 +15 15 | print((3.0).__ge__(4.0)) # PLC2801 +16 16 | print((3.0).__str__()) # PLC2801 + +unnecessary_dunder_call.py:14:7: PLC2801 [*] Unnecessary dunder call `3.0.__gt__(4.0)`. Use `>` operator. | - 9 | print((3.0).__lt__(4.0)) # PLC2801 -10 | print((3.0).__le__(4.0)) # PLC2801 -11 | print((3.0).__gt__(4.0)) # PLC2801 +12 | print((3.0).__lt__(4.0)) # PLC2801 +13 | print((3.0).__le__(4.0)) # PLC2801 +14 | print((3.0).__gt__(4.0)) # PLC2801 | ^^^^^^^^^^^^^^^^^ PLC2801 -12 | print((3.0).__ge__(4.0)) # PLC2801 -13 | print((3.0).__str__()) # PLC2801 +15 | print((3.0).__ge__(4.0)) # PLC2801 +16 | print((3.0).__str__()) # PLC2801 | - = help: Remove unnecessary dunder call + = help: Use `>` operator. ℹ Safe fix -8 8 | print((3.0).__ne__(4.0)) # PLC2801 -9 9 | print((3.0).__lt__(4.0)) # PLC2801 -10 10 | print((3.0).__le__(4.0)) # PLC2801 -11 |-print((3.0).__gt__(4.0)) # PLC2801 - 11 |+print(3.0 > 4.0) # PLC2801 -12 12 | print((3.0).__ge__(4.0)) # PLC2801 -13 13 | print((3.0).__str__()) # PLC2801 -14 14 | print((3.0).__repr__()) # PLC2801 - -unnecessary_dunder_call.py:12:7: PLC2801 [*] Unnecessary dunder call `3.0.__ge__(4.0)` +11 11 | print((3.0).__ne__(4.0)) # PLC2801 +12 12 | print((3.0).__lt__(4.0)) # PLC2801 +13 13 | print((3.0).__le__(4.0)) # PLC2801 +14 |-print((3.0).__gt__(4.0)) # PLC2801 + 14 |+print(3.0 > 4.0) # PLC2801 +15 15 | print((3.0).__ge__(4.0)) # PLC2801 +16 16 | print((3.0).__str__()) # PLC2801 +17 17 | print((3.0).__repr__()) # PLC2801 + +unnecessary_dunder_call.py:15:7: PLC2801 [*] Unnecessary dunder call `3.0.__ge__(4.0)`. Use `>=` operator. | -10 | print((3.0).__le__(4.0)) # PLC2801 -11 | print((3.0).__gt__(4.0)) # PLC2801 -12 | print((3.0).__ge__(4.0)) # PLC2801 +13 | print((3.0).__le__(4.0)) # PLC2801 +14 | print((3.0).__gt__(4.0)) # PLC2801 +15 | print((3.0).__ge__(4.0)) # PLC2801 | ^^^^^^^^^^^^^^^^^ PLC2801 -13 | print((3.0).__str__()) # PLC2801 -14 | print((3.0).__repr__()) # PLC2801 +16 | print((3.0).__str__()) # PLC2801 +17 | print((3.0).__repr__()) # PLC2801 | - = help: Remove unnecessary dunder call + = help: Use `>=` operator. ℹ Safe fix -9 9 | print((3.0).__lt__(4.0)) # PLC2801 -10 10 | print((3.0).__le__(4.0)) # PLC2801 -11 11 | print((3.0).__gt__(4.0)) # PLC2801 -12 |-print((3.0).__ge__(4.0)) # PLC2801 - 12 |+print(3.0 >= 4.0) # PLC2801 -13 13 | print((3.0).__str__()) # PLC2801 -14 14 | print((3.0).__repr__()) # PLC2801 -15 15 | print([1, 2, 3].__len__()) # PLC2801 - -unnecessary_dunder_call.py:13:7: PLC2801 [*] Unnecessary dunder call `3.0.__str__()` +12 12 | print((3.0).__lt__(4.0)) # PLC2801 +13 13 | print((3.0).__le__(4.0)) # PLC2801 +14 14 | print((3.0).__gt__(4.0)) # PLC2801 +15 |-print((3.0).__ge__(4.0)) # PLC2801 + 15 |+print(3.0 >= 4.0) # PLC2801 +16 16 | print((3.0).__str__()) # PLC2801 +17 17 | print((3.0).__repr__()) # PLC2801 +18 18 | print([1, 2, 3].__len__()) # PLC2801 + +unnecessary_dunder_call.py:16:7: PLC2801 [*] Unnecessary dunder call `3.0.__str__()`. Use `str()` builtin. | -11 | print((3.0).__gt__(4.0)) # PLC2801 -12 | print((3.0).__ge__(4.0)) # PLC2801 -13 | print((3.0).__str__()) # PLC2801 +14 | print((3.0).__gt__(4.0)) # PLC2801 +15 | print((3.0).__ge__(4.0)) # PLC2801 +16 | print((3.0).__str__()) # PLC2801 | ^^^^^^^^^^^^^^^ PLC2801 -14 | print((3.0).__repr__()) # PLC2801 -15 | print([1, 2, 3].__len__()) # PLC2801 +17 | print((3.0).__repr__()) # PLC2801 +18 | print([1, 2, 3].__len__()) # PLC2801 | - = help: Remove unnecessary dunder call + = help: Use `str()` builtin. ℹ Safe fix -10 10 | print((3.0).__le__(4.0)) # PLC2801 -11 11 | print((3.0).__gt__(4.0)) # PLC2801 -12 12 | print((3.0).__ge__(4.0)) # PLC2801 -13 |-print((3.0).__str__()) # PLC2801 - 13 |+print(str(3.0)) # PLC2801 -14 14 | print((3.0).__repr__()) # PLC2801 -15 15 | print([1, 2, 3].__len__()) # PLC2801 -16 16 | - -unnecessary_dunder_call.py:14:7: PLC2801 [*] Unnecessary dunder call `3.0.__repr__()` +13 13 | print((3.0).__le__(4.0)) # PLC2801 +14 14 | print((3.0).__gt__(4.0)) # PLC2801 +15 15 | print((3.0).__ge__(4.0)) # PLC2801 +16 |-print((3.0).__str__()) # PLC2801 + 16 |+print(str(3.0)) # PLC2801 +17 17 | print((3.0).__repr__()) # PLC2801 +18 18 | print([1, 2, 3].__len__()) # PLC2801 +19 19 | print((1).__neg__()) # PLC2801 + +unnecessary_dunder_call.py:17:7: PLC2801 [*] Unnecessary dunder call `3.0.__repr__()`. Use `repr()` builtin. | -12 | print((3.0).__ge__(4.0)) # PLC2801 -13 | print((3.0).__str__()) # PLC2801 -14 | print((3.0).__repr__()) # PLC2801 +15 | print((3.0).__ge__(4.0)) # PLC2801 +16 | print((3.0).__str__()) # PLC2801 +17 | print((3.0).__repr__()) # PLC2801 | ^^^^^^^^^^^^^^^^ PLC2801 -15 | print([1, 2, 3].__len__()) # PLC2801 +18 | print([1, 2, 3].__len__()) # PLC2801 +19 | print((1).__neg__()) # PLC2801 | - = help: Remove unnecessary dunder call + = help: Use `repr()` builtin. ℹ Safe fix -11 11 | print((3.0).__gt__(4.0)) # PLC2801 -12 12 | print((3.0).__ge__(4.0)) # PLC2801 -13 13 | print((3.0).__str__()) # PLC2801 -14 |-print((3.0).__repr__()) # PLC2801 - 14 |+print(repr(3.0)) # PLC2801 -15 15 | print([1, 2, 3].__len__()) # PLC2801 -16 16 | -17 17 | - -unnecessary_dunder_call.py:15:7: PLC2801 [*] Unnecessary dunder call `[1, 2, 3].__len__()` +14 14 | print((3.0).__gt__(4.0)) # PLC2801 +15 15 | print((3.0).__ge__(4.0)) # PLC2801 +16 16 | print((3.0).__str__()) # PLC2801 +17 |-print((3.0).__repr__()) # PLC2801 + 17 |+print(repr(3.0)) # PLC2801 +18 18 | print([1, 2, 3].__len__()) # PLC2801 +19 19 | print((1).__neg__()) # PLC2801 +20 20 | + +unnecessary_dunder_call.py:18:7: PLC2801 [*] Unnecessary dunder call `[1, 2, 3].__len__()`. Use `len()` builtin. | -13 | print((3.0).__str__()) # PLC2801 -14 | print((3.0).__repr__()) # PLC2801 -15 | print([1, 2, 3].__len__()) # PLC2801 +16 | print((3.0).__str__()) # PLC2801 +17 | print((3.0).__repr__()) # PLC2801 +18 | print([1, 2, 3].__len__()) # PLC2801 | ^^^^^^^^^^^^^^^^^^^ PLC2801 +19 | print((1).__neg__()) # PLC2801 | - = help: Remove unnecessary dunder call + = help: Use `len()` builtin. ℹ Safe fix -12 12 | print((3.0).__ge__(4.0)) # PLC2801 -13 13 | print((3.0).__str__()) # PLC2801 -14 14 | print((3.0).__repr__()) # PLC2801 -15 |-print([1, 2, 3].__len__()) # PLC2801 - 15 |+print(len([1, 2, 3])) # PLC2801 -16 16 | -17 17 | -18 18 | class Thing: +15 15 | print((3.0).__ge__(4.0)) # PLC2801 +16 16 | print((3.0).__str__()) # PLC2801 +17 17 | print((3.0).__repr__()) # PLC2801 +18 |-print([1, 2, 3].__len__()) # PLC2801 + 18 |+print(len([1, 2, 3])) # PLC2801 +19 19 | print((1).__neg__()) # PLC2801 +20 20 | +21 21 | + +unnecessary_dunder_call.py:19:7: PLC2801 Unnecessary dunder call `(1).__neg__()`. Multiply by -1 instead. + | +17 | print((3.0).__repr__()) # PLC2801 +18 | print([1, 2, 3].__len__()) # PLC2801 +19 | print((1).__neg__()) # PLC2801 + | ^^^^^^^^^^^^^ PLC2801 + | + = help: Multiply by -1 instead.