Skip to content

Commit a4dc2b7

Browse files
authored
B020: Fix comprehension false postives (#238)
1 parent 77dc992 commit a4dc2b7

File tree

3 files changed

+34
-2
lines changed

3 files changed

+34
-2
lines changed

bugbear.py

+17-1
Original file line numberDiff line numberDiff line change
@@ -557,7 +557,7 @@ def check_for_b020(self, node):
557557
targets.visit(node.target)
558558
ctrl_names = set(targets.names)
559559

560-
iterset = NameFinder()
560+
iterset = B020NameFinder()
561561
iterset.visit(node.iter)
562562
iterset_names = set(iterset.names)
563563

@@ -778,6 +778,22 @@ def visit(self, node):
778778
return node
779779

780780

781+
class B020NameFinder(NameFinder):
782+
"""Ignore names defined within the local scope of a comprehension."""
783+
784+
def visit_GeneratorExp(self, node):
785+
self.visit(node.generators)
786+
787+
def visit_ListComp(self, node):
788+
self.visit(node.generators)
789+
790+
def visit_DictComp(self, node):
791+
self.visit(node.generators)
792+
793+
def visit_comprehension(self, node):
794+
self.visit(node.iter)
795+
796+
781797
error = namedtuple("error", "lineno col message type vars")
782798
Error = partial(partial, error, type=BugBearChecker, vars=())
783799

tests/b020.py

+16-1
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
"""
22
Should emit:
3-
B020 - on lines 8 and 21
3+
B020 - on lines 8, 21, and 36
44
"""
55

66
items = [1, 2, 3]
@@ -20,3 +20,18 @@
2020

2121
for key, values in values.items():
2222
print(f"{key}, {values}")
23+
24+
# Variables defined in a comprehension are local in scope
25+
# to that comprehension and are therefore allowed.
26+
for var in [var for var in range(10)]:
27+
print(var)
28+
29+
for var in (var for var in range(10)):
30+
print(var)
31+
32+
for k, v in {k: v for k, v in zip(range(10), range(10, 20))}.items():
33+
print(k, v)
34+
35+
# However we still call out reassigning the iterable in the comprehension.
36+
for vars in [i for i in vars]:
37+
print(vars)

tests/test_bugbear.py

+1
Original file line numberDiff line numberDiff line change
@@ -284,6 +284,7 @@ def test_b020(self):
284284
self.errors(
285285
B020(8, 4, vars=("items",)),
286286
B020(21, 9, vars=("values",)),
287+
B020(36, 4, vars=("vars",)),
287288
),
288289
)
289290

0 commit comments

Comments
 (0)