From 319b15501d0d81ad67548eb2883dbbf5e1897565 Mon Sep 17 00:00:00 2001 From: StressTestor <212606152+StressTestor@users.noreply.github.com> Date: Mon, 15 Jun 2026 19:10:23 -0600 Subject: [PATCH] B031: don't count store-context references as generator uses A reference to the groupby loop variable in store context (an annotation target like `group: T`, or an assignment target) was counted as a use of the generator, so a single real use plus an annotation tripped a false-positive B031. Count only loads. Addresses #465 (the annotation/store-context case; the if/else case is handled separately by #557). --- README.rst | 1 + bugbear.py | 11 +++++++++-- tests/eval_files/b031.py | 6 ++++++ 3 files changed, 16 insertions(+), 2 deletions(-) diff --git a/README.rst b/README.rst index d8cfd18..c806a12 100644 --- a/README.rst +++ b/README.rst @@ -499,6 +499,7 @@ UNRELEASED ~~~~~~~~~~ * B018: handle also useless calls such as `isinstance(x, int)` without assigning or using the result +* B031: don't count a store-context reference (e.g. an annotation target like `group: T`) as a use of the `groupby` generator (#465) 25.11.29 ~~~~~~~~ diff --git a/bugbear.py b/bugbear.py index 329c435..c7d67cc 100644 --- a/bugbear.py +++ b/bugbear.py @@ -1215,11 +1215,18 @@ def check_for_b031(self, loop_node: ast.For) -> None: # noqa: C901 if ( isinstance(nested_node, ast.Name) and nested_node.id == group_name + and isinstance(nested_node.ctx, ast.Load) ): self.add_error("B031", nested_node, nested_node.id) - # Handle multiple uses - if isinstance(node, ast.Name) and node.id == group_name: + # Handle multiple uses. Count only loads: a store-context + # reference, such as an annotation target (`group: T`), is + # not a read of the generator (#465). + if ( + isinstance(node, ast.Name) + and node.id == group_name + and isinstance(node.ctx, ast.Load) + ): num_usages += 1 if num_usages > 1: self.add_error("B031", node, node.id) diff --git a/tests/eval_files/b031.py b/tests/eval_files/b031.py index 6580076..fd51a70 100644 --- a/tests/eval_files/b031.py +++ b/tests/eval_files/b031.py @@ -63,3 +63,9 @@ def collect_shop_items(shopper, items): ): collect_shop_items("Jane", group[1]) collect_shop_items("Joe", group[1]) + + +# Annotating the loop variable is not a second usage of the generator (#465) +for _section, section_items in groupby(items, key=lambda p: p[1]): + section_items: list + collect_shop_items("Jane", section_items)