diff --git a/resources/test/fixtures/flake8_bugbear/B009_B010.py b/resources/test/fixtures/flake8_bugbear/B009_B010.py index b344783014..611d6bc9df 100644 --- a/resources/test/fixtures/flake8_bugbear/B009_B010.py +++ b/resources/test/fixtures/flake8_bugbear/B009_B010.py @@ -20,6 +20,8 @@ getattr(foo, "_123abc") getattr(foo, "abc123") getattr(foo, r"abc123") _ = lambda x: getattr(x, "bar") +if getattr(x, "bar"): + pass # Valid setattr usage setattr(foo, bar, None) @@ -28,6 +30,8 @@ setattr(foo, "123abc", None) setattr(foo, r"123\abc", None) setattr(foo, "except", None) _ = lambda x: setattr(x, "bar", 1) +if setattr(x, "bar", 1): + pass # Invalid usage setattr(foo, "bar", None) diff --git a/src/check_ast.rs b/src/check_ast.rs index 5840908e2d..86035a4aae 100644 --- a/src/check_ast.rs +++ b/src/check_ast.rs @@ -1557,14 +1557,7 @@ where flake8_bugbear::plugins::getattr_with_constant(self, expr, func, args); } if self.settings.enabled.contains(&CheckCode::B010) { - if !self - .scope_stack - .iter() - .rev() - .any(|index| matches!(self.scopes[*index].kind, ScopeKind::Lambda(..))) - { - flake8_bugbear::plugins::setattr_with_constant(self, expr, func, args); - } + flake8_bugbear::plugins::setattr_with_constant(self, expr, func, args); } if self.settings.enabled.contains(&CheckCode::B022) { flake8_bugbear::plugins::useless_contextlib_suppress(self, expr, args); diff --git a/src/flake8_bugbear/plugins/setattr_with_constant.rs b/src/flake8_bugbear/plugins/setattr_with_constant.rs index b81f8b7179..6ebb1a5d17 100644 --- a/src/flake8_bugbear/plugins/setattr_with_constant.rs +++ b/src/flake8_bugbear/plugins/setattr_with_constant.rs @@ -56,16 +56,23 @@ pub fn setattr_with_constant(checker: &mut Checker, expr: &Expr, func: &Expr, ar if KWLIST.contains(&name.as_str()) { return; } - let mut check = Check::new(CheckKind::SetAttrWithConstant, Range::from_located(expr)); - if checker.patch(check.kind.code()) { - match assignment(obj, name, value) { - Ok(content) => check.amend(Fix::replacement( - content, - expr.location, - expr.end_location.unwrap(), - )), - Err(e) => error!("Failed to fix invalid comparison: {e}"), - }; + // We can only replace a `setattr` call (which is an `Expr`) with an assignment + // (which is a `Stmt`) if the `Expr` is already being used as a `Stmt` + // (i.e., it's directly within an `StmtKind::Expr`). + if let StmtKind::Expr { value: child } = &checker.current_parent().0.node { + if expr == child.as_ref() { + let mut check = Check::new(CheckKind::SetAttrWithConstant, Range::from_located(expr)); + if checker.patch(check.kind.code()) { + match assignment(obj, name, value) { + Ok(content) => check.amend(Fix::replacement( + content, + expr.location, + expr.end_location.unwrap(), + )), + Err(e) => error!("Failed to fix invalid comparison: {e}"), + }; + } + checker.add_check(check); + } } - checker.add_check(check); } diff --git a/src/flake8_bugbear/snapshots/ruff__flake8_bugbear__tests__B009_B009_B010.py.snap b/src/flake8_bugbear/snapshots/ruff__flake8_bugbear__tests__B009_B009_B010.py.snap index 49fcace529..176b93dafc 100644 --- a/src/flake8_bugbear/snapshots/ruff__flake8_bugbear__tests__B009_B009_B010.py.snap +++ b/src/flake8_bugbear/snapshots/ruff__flake8_bugbear__tests__B009_B009_B010.py.snap @@ -77,4 +77,19 @@ expression: checks end_location: row: 22 column: 31 +- kind: GetAttrWithConstant + location: + row: 23 + column: 3 + end_location: + row: 23 + column: 20 + fix: + content: x.bar + location: + row: 23 + column: 3 + end_location: + row: 23 + column: 20 diff --git a/src/flake8_bugbear/snapshots/ruff__flake8_bugbear__tests__B010_B009_B010.py.snap b/src/flake8_bugbear/snapshots/ruff__flake8_bugbear__tests__B010_B009_B010.py.snap index 26d438ef97..33eb83221c 100644 --- a/src/flake8_bugbear/snapshots/ruff__flake8_bugbear__tests__B010_B009_B010.py.snap +++ b/src/flake8_bugbear/snapshots/ruff__flake8_bugbear__tests__B010_B009_B010.py.snap @@ -4,77 +4,77 @@ expression: checks --- - kind: SetAttrWithConstant location: - row: 33 + row: 37 column: 0 end_location: - row: 33 + row: 37 column: 25 fix: content: foo.bar = None location: - row: 33 + row: 37 column: 0 end_location: - row: 33 + row: 37 column: 25 - kind: SetAttrWithConstant location: - row: 34 + row: 38 column: 0 end_location: - row: 34 + row: 38 column: 29 fix: content: foo._123abc = None location: - row: 34 + row: 38 column: 0 end_location: - row: 34 + row: 38 column: 29 - kind: SetAttrWithConstant location: - row: 35 + row: 39 column: 0 end_location: - row: 35 + row: 39 column: 28 fix: content: foo.abc123 = None location: - row: 35 + row: 39 column: 0 end_location: - row: 35 + row: 39 column: 28 - kind: SetAttrWithConstant location: - row: 36 + row: 40 column: 0 end_location: - row: 36 + row: 40 column: 29 fix: content: foo.abc123 = None location: - row: 36 + row: 40 column: 0 end_location: - row: 36 + row: 40 column: 29 - kind: SetAttrWithConstant location: - row: 37 + row: 41 column: 0 end_location: - row: 37 + row: 41 column: 30 fix: content: foo.bar.baz = None location: - row: 37 + row: 41 column: 0 end_location: - row: 37 + row: 41 column: 30