From 25deff302440e70a606116c0e9ea669b4c31ce91 Mon Sep 17 00:00:00 2001 From: Don Yin Date: Fri, 23 Oct 2026 07:41:36 +0100 Subject: [PATCH 1/2] B909: visit if conditions and alternate branches Visit the test and orelse nodes while keeping conditional mutation blocks separate, preserving the existing handling of unconditional breaks. Signed-off-by: Don Yin --- bugbear.py | 3 +++ tests/eval_files/b909.py | 30 ++++++++++++++++++++++++++++++ 2 files changed, 33 insertions(+) diff --git a/bugbear.py b/bugbear.py index 218afe0..5b65b23 100644 --- a/bugbear.py +++ b/bugbear.py @@ -3318,9 +3318,12 @@ def visit_Call(self, node: ast.Call) -> None: self.generic_visit(node) def visit_If(self, node: ast.If) -> None: + self.visit(node.test) self._conditional_block += 1 self.visit(node.body) self._conditional_block += 1 + self.visit(node.orelse) + self._conditional_block += 1 def visit(self, node: ast.AST | list[ast.stmt]) -> ast.AST | list[ast.stmt] | None: """Like super-visit but supports iteration over lists.""" diff --git a/tests/eval_files/b909.py b/tests/eval_files/b909.py index fcea105..1fe2d91 100644 --- a/tests/eval_files/b909.py +++ b/tests/eval_files/b909.py @@ -177,3 +177,33 @@ def __init__(self, ls): for key in list(some_dict.keys()): some_dict.pop(key) # no error + + +# Visit every branch and the condition of an if statement. +some_list = [1, 2, 3] +for elem in some_list: + if elem == 1: + pass + elif elem == 2: + some_list.remove(elem) # B909: 8 + else: + some_list.clear() # B909: 8 + +for _ in some_list: + if some_list.pop(): # B909: 7 + break + +for elem in some_list: + if elem == 1: + some_list.remove(elem) # B909: 8 + else: + some_list.clear() + break + +for elem in some_list: + if elem == 1: + pass + else: + some_list.remove(elem) # B909: 8 + if elem == 2: + break From 8a37d0b1cc18865c9890851cd628e9e506faf111 Mon Sep 17 00:00:00 2001 From: Cooper Lees Date: Sat, 24 Oct 2026 20:14:47 +0000 Subject: [PATCH 2/2] Add changelog entry for B909 if-condition/branch fix (#606) --- README.rst | 2 ++ 1 file changed, 2 insertions(+) diff --git a/README.rst b/README.rst index edcc363..8c8c725 100644 --- a/README.rst +++ b/README.rst @@ -611,6 +611,8 @@ UNRELEASED * B018: also report ``map()``, ``filter()``, ``reversed()``, ``zip()`` and ``enumerate()`` calls used as statements. They return lazy iterators, so ``map(print, items)`` on its own line never calls ``print`` (#452) +* B909: also check mutations in ``if`` conditions and ``elif``/``else`` + branches inside loops (#606) 26.9.30 ~~~~~~~