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 ef313aa609d2f..beec9c7b7472b 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 @@ -30,6 +30,11 @@ def __getattribute__(self, item): def do_thing(self, item): return object.__getattribute__(self, item) # PLC2801 + def use_descriptor(self, item): + item.__get__(self, type(self)) # OK + item.__set__(self, 1) # OK + item.__delete__(self) # 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 f3174b170d487..6e2257d45e086 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 @@ -171,9 +171,11 @@ fn allowed_dunder_constants(dunder_method: &str, target_version: PythonVersion) | "__await__" | "__class__" | "__class_getitem__" + | "__delete__" | "__dict__" | "__doc__" | "__exit__" + | "__get__" | "__getnewargs__" | "__getnewargs_ex__" | "__getstate__" @@ -185,6 +187,7 @@ fn allowed_dunder_constants(dunder_method: &str, target_version: PythonVersion) | "__post_init__" | "__reduce__" | "__reduce_ex__" + | "__set__" | "__set_name__" | "__setstate__" | "__sizeof__" @@ -285,14 +288,12 @@ impl DunderReplacement { "__deepcopy__" => Some(Self::MessageOnly("Use `copy.deepcopy()` function")), "__del__" => Some(Self::MessageOnly("Use `del` statement")), "__delattr__" => Some(Self::MessageOnly("Use `del` statement")), - "__delete__" => Some(Self::MessageOnly("Use `del` statement")), "__delitem__" => Some(Self::MessageOnly("Use `del` statement")), "__divmod__" => Some(Self::MessageOnly("Use `divmod()` builtin")), "__format__" => Some(Self::MessageOnly( "Use `format` builtin, format string method, or f-string", )), "__fspath__" => Some(Self::MessageOnly("Use `os.fspath` function")), - "__get__" => Some(Self::MessageOnly("Use `get` method")), "__getattr__" => Some(Self::MessageOnly( "Access attribute directly or use getattr built-in function", )), @@ -308,7 +309,6 @@ impl DunderReplacement { "__pow__" => Some(Self::MessageOnly("Use ** operator or `pow()` builtin")), "__rdivmod__" => Some(Self::MessageOnly("Use `divmod()` builtin")), "__rpow__" => Some(Self::MessageOnly("Use ** operator or `pow()` builtin")), - "__set__" => Some(Self::MessageOnly("Use subscript assignment")), "__setattr__" => Some(Self::MessageOnly( "Mutate attribute directly or use setattr built-in function", )), @@ -331,8 +331,6 @@ fn allow_nested_expression(dunder_name: &str, semantic: &SemanticModel) -> bool "__init__" | "__del__" | "__delattr__" - | "__set__" - | "__delete__" | "__setitem__" | "__delitem__" | "__iadd__" 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 33d29996185c5..d8a2c8f1d4c9f 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 @@ -326,6 +326,8 @@ unnecessary_dunder_call.py:31:16: PLC2801 Unnecessary dunder call to `__getattri 30 | def do_thing(self, item): 31 | return object.__getattribute__(self, item) # PLC2801 | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ PLC2801 +32 | +33 | def use_descriptor(self, item): | = help: Access attribute directly or use getattr built-in function