From 4802c7c7d892967c5a583598c1381257a24e6e2d Mon Sep 17 00:00:00 2001 From: Charlie Marsh Date: Fri, 28 Jul 2023 23:35:26 -0400 Subject: [PATCH] Avoid key-in-dict violations for `self` accesses (#6165) Closes https://github.com/astral-sh/ruff/issues/6163. --- .../test/fixtures/flake8_simplify/SIM118.py | 10 ++++++++++ .../src/rules/flake8_simplify/rules/key_in_dict.rs | 14 +++++++++++++- ...__flake8_simplify__tests__SIM118_SIM118.py.snap | 6 ++++++ 3 files changed, 29 insertions(+), 1 deletion(-) diff --git a/crates/ruff/resources/test/fixtures/flake8_simplify/SIM118.py b/crates/ruff/resources/test/fixtures/flake8_simplify/SIM118.py index 308cd2e8571d2..6f86a62204bec 100644 --- a/crates/ruff/resources/test/fixtures/flake8_simplify/SIM118.py +++ b/crates/ruff/resources/test/fixtures/flake8_simplify/SIM118.py @@ -30,3 +30,13 @@ (k for k in obj.keys()) # SIM118 key in (obj or {}).keys() # SIM118 + +from typing import KeysView + + +class Foo: + def keys(self) -> KeysView[object]: + ... + + def __contains__(self, key: object) -> bool: + return key in self.keys() # OK diff --git a/crates/ruff/src/rules/flake8_simplify/rules/key_in_dict.rs b/crates/ruff/src/rules/flake8_simplify/rules/key_in_dict.rs index f1b6c7488eca6..d77a6479a5860 100644 --- a/crates/ruff/src/rules/flake8_simplify/rules/key_in_dict.rs +++ b/crates/ruff/src/rules/flake8_simplify/rules/key_in_dict.rs @@ -82,13 +82,25 @@ fn key_in_dict( return; } - let Expr::Attribute(ast::ExprAttribute { attr, .. }) = func.as_ref() else { + let Expr::Attribute(ast::ExprAttribute { attr, value, .. }) = func.as_ref() else { return; }; if attr != "keys" { return; } + // Ignore `self.keys()`, which will almost certainly be intentional, as in: + // ```python + // def __contains__(self, key: object) -> bool: + // return key in self.keys() + // ``` + if value + .as_name_expr() + .map_or(false, |name| matches!(name.id.as_str(), "self")) + { + return; + } + // Slice exact content to preserve formatting. let left_content = checker.locator().slice(left.range()); let Ok(value_content) = diff --git a/crates/ruff/src/rules/flake8_simplify/snapshots/ruff__rules__flake8_simplify__tests__SIM118_SIM118.py.snap b/crates/ruff/src/rules/flake8_simplify/snapshots/ruff__rules__flake8_simplify__tests__SIM118_SIM118.py.snap index 972ccb6d590d3..05cdf5c898408 100644 --- a/crates/ruff/src/rules/flake8_simplify/snapshots/ruff__rules__flake8_simplify__tests__SIM118_SIM118.py.snap +++ b/crates/ruff/src/rules/flake8_simplify/snapshots/ruff__rules__flake8_simplify__tests__SIM118_SIM118.py.snap @@ -265,6 +265,7 @@ SIM118.py:30:8: SIM118 [*] Use `k in obj` instead of `k in obj.keys()` 30 |+(k for k in obj) # SIM118 31 31 | 32 32 | key in (obj or {}).keys() # SIM118 +33 33 | SIM118.py:32:1: SIM118 [*] Use `key in (obj or {})` instead of `key in (obj or {}).keys()` | @@ -272,6 +273,8 @@ SIM118.py:32:1: SIM118 [*] Use `key in (obj or {})` instead of `key in (obj or { 31 | 32 | key in (obj or {}).keys() # SIM118 | ^^^^^^^^^^^^^^^^^^^^^^^^^ SIM118 +33 | +34 | from typing import KeysView | = help: Convert to `key in (obj or {})` @@ -281,5 +284,8 @@ SIM118.py:32:1: SIM118 [*] Use `key in (obj or {})` instead of `key in (obj or { 31 31 | 32 |-key in (obj or {}).keys() # SIM118 32 |+key in (obj or {}) # SIM118 +33 33 | +34 34 | from typing import KeysView +35 35 |