From 7531009337e9fa9add5f47e07ebbc1ff61dbd4ad Mon Sep 17 00:00:00 2001 From: Martin Imre Date: Thu, 8 Feb 2024 20:07:28 +0100 Subject: [PATCH] feat(b909): Add more cases to detect for b909 This commit takes care of detecting mutations stemming from AugAssign and Assign. Also removes incorrect detection of "del foo". --- bugbear.py | 13 ++++++++++- tests/b909.py | 51 ++++++++++++++++++++++++++++++------------- tests/test_bugbear.py | 11 +++++++++- 3 files changed, 58 insertions(+), 17 deletions(-) diff --git a/bugbear.py b/bugbear.py index e9b0c91..1fc7e1d 100644 --- a/bugbear.py +++ b/bugbear.py @@ -1622,12 +1622,23 @@ def __init__(self, name: str): self.name = name self.mutations = [] + def visit_Assign(self, node: ast.Assign): + for target in node.targets: + if isinstance(target, ast.Subscript) and _to_name_str(target.value): + self.mutations.append(node) + self.generic_visit(node) + + def visit_AugAssign(self, node: ast.AugAssign): + if _to_name_str(node.target) == self.name: + self.mutations.append(node) + self.generic_visit(node) + def visit_Delete(self, node: ast.Delete): for target in node.targets: if isinstance(target, ast.Subscript): name = _to_name_str(target.value) elif isinstance(target, (ast.Attribute, ast.Name)): - name = _to_name_str(target) + name = "" # ignore "del foo" else: name = "" # fallback self.generic_visit(target) diff --git a/tests/b909.py b/tests/b909.py index ad6e819..06f35c6 100644 --- a/tests/b909.py +++ b/tests/b909.py @@ -3,7 +3,7 @@ B999 - on lines 11, 25, 26, 40, 46 """ -## lists +# lists some_list = [1, 2, 3] some_other_list = [1, 2, 3] @@ -19,11 +19,11 @@ some_list.insert(1, 1) some_list.pop(1) some_list.pop() - + # conditional break should error if elem == 2: some_list.remove(elem) - if elem ==3: + if elem == 3: break # non-errors @@ -39,12 +39,12 @@ break -## dicts +# dicts mydicts = {'a': {'foo': 1, 'bar': 2}} for elem in mydicts: # errors - mydicts.popitem() + mydicts.popitem() mydicts.setdefault('foo', 1) mydicts.update({'foo': 'bar'}) @@ -53,32 +53,53 @@ elem.setdefault('foo', 1) elem.update({'foo': 'bar'}) -## sets +# sets -myset = { 1, 2, 3 } +myset = {1, 2, 3} for elem in myset: # errors - myset.update({4,5}) - myset.intersection_update({4,5}) - myset.difference_update({4,5}) - myset.symmetric_difference_update({4,5}) + myset.update({4, 5}) + myset.intersection_update({4, 5}) + myset.difference_update({4, 5}) + myset.symmetric_difference_update({4, 5}) myset.add(4) myset.discard(3) - # no errors del myset -## members +# members class A: some_list: list + def __init__(self, ls): self.some_list = list(ls) + a = A((1, 2, 3)) # ensure member accesses are handled for elem in a.some_list: - a.some_list.remove(elem) - del a.some_list[2] + a.some_list.remove(elem) + del a.some_list[2] + + +# Augassign + +foo = [1, 2, 3] +bar = [4, 5, 6] +for _ in foo: + foo *= 2 + foo += bar + foo[1] = 9 #todo + foo[1:2] = bar + foo[1:2:3] = bar + +foo = {1,2,3} +bar = {4,5,6} +for _ in foo: + foo |= bar + foo &= bar + foo -= bar + foo ^= bar diff --git a/tests/test_bugbear.py b/tests/test_bugbear.py index ed0b650..fc3d7cb 100644 --- a/tests/test_bugbear.py +++ b/tests/test_bugbear.py @@ -996,8 +996,17 @@ def test_b909(self): B909(65, 4), B909(66, 4), B909(67, 4), - B909(83, 4), B909(84, 4), + B909(85, 4), + B909(93, 4), + B909(94, 4), + B909(95, 4), + B909(96, 4), + B909(97, 4), + B909(102, 4), + B909(103, 4), + B909(104, 4), + B909(105, 4), ] self.assertEqual(errors, self.errors(*expected))