Skip to content

Commit e07f651

Browse files
authored
B031: don't count store-context references as generator uses (#558)
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).
1 parent 7dc12da commit e07f651

3 files changed

Lines changed: 16 additions & 2 deletions

File tree

README.rst

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -499,6 +499,7 @@ UNRELEASED
499499
~~~~~~~~~~
500500

501501
* B018: handle also useless calls such as `isinstance(x, int)` without assigning or using the result
502+
* B031: don't count a store-context reference (e.g. an annotation target like `group: T`) as a use of the `groupby` generator (#465)
502503

503504
25.11.29
504505
~~~~~~~~

bugbear.py

Lines changed: 9 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1215,11 +1215,18 @@ def check_for_b031(self, loop_node: ast.For) -> None: # noqa: C901
12151215
if (
12161216
isinstance(nested_node, ast.Name)
12171217
and nested_node.id == group_name
1218+
and isinstance(nested_node.ctx, ast.Load)
12181219
):
12191220
self.add_error("B031", nested_node, nested_node.id)
12201221

1221-
# Handle multiple uses
1222-
if isinstance(node, ast.Name) and node.id == group_name:
1222+
# Handle multiple uses. Count only loads: a store-context
1223+
# reference, such as an annotation target (`group: T`), is
1224+
# not a read of the generator (#465).
1225+
if (
1226+
isinstance(node, ast.Name)
1227+
and node.id == group_name
1228+
and isinstance(node.ctx, ast.Load)
1229+
):
12231230
num_usages += 1
12241231
if num_usages > 1:
12251232
self.add_error("B031", node, node.id)

tests/eval_files/b031.py

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -63,3 +63,9 @@ def collect_shop_items(shopper, items):
6363
):
6464
collect_shop_items("Jane", group[1])
6565
collect_shop_items("Joe", group[1])
66+
67+
68+
# Annotating the loop variable is not a second usage of the generator (#465)
69+
for _section, section_items in groupby(items, key=lambda p: p[1]):
70+
section_items: list
71+
collect_shop_items("Jane", section_items)

0 commit comments

Comments
 (0)