Skip to content

Commit eb300be

Browse files
FozzieHicooperlees
andauthored
Add B033: Duplicate items in sets (#373)
* Add B033: Duplicate items in sets * Simplify by checking lengths --------- Co-authored-by: Cooper Lees <[email protected]>
1 parent 3f16173 commit eb300be

File tree

4 files changed

+55
-0
lines changed

4 files changed

+55
-0
lines changed

README.rst

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -186,6 +186,8 @@ second usage. Save the result to a list if the result is needed multiple times.
186186

187187
**B032**: Possible unintentional type annotation (using ``:``). Did you mean to assign (using ``=``)?
188188

189+
**B033**: Sets should not contain duplicate items. Duplicate items will be replaced with a single item at runtime.
190+
189191
Opinionated warnings
190192
~~~~~~~~~~~~~~~~~~~~
191193

@@ -337,6 +339,7 @@ Unreleased
337339
* flake8-bugbear is now >= 3.8.1 project like flake8>=6.0.0
338340
* This has allowed some more modern AST usage cleanup and less CI running etc.
339341
* B030: Fix crash on certain unusual except handlers (e.g. ``except a[0].b:``)
342+
* Add B033: Check for duplicate items in sets.
340343

341344
23.3.12
342345
~~~~~~~~

bugbear.py

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -527,6 +527,10 @@ def visit_Import(self, node):
527527
self.check_for_b005(node)
528528
self.generic_visit(node)
529529

530+
def visit_Set(self, node):
531+
self.check_for_b033(node)
532+
self.generic_visit(node)
533+
530534
def check_for_b005(self, node):
531535
if isinstance(node, ast.Import):
532536
for name in node.names:
@@ -1346,6 +1350,14 @@ def check_for_b032(self, node):
13461350
):
13471351
self.errors.append(B032(node.lineno, node.col_offset))
13481352

1353+
def check_for_b033(self, node):
1354+
constants = [
1355+
item.value
1356+
for item in filter(lambda x: isinstance(x, ast.Constant), node.elts)
1357+
]
1358+
if len(constants) != len(set(constants)):
1359+
self.errors.append(B033(node.lineno, node.col_offset))
1360+
13491361

13501362
def compose_call_path(node):
13511363
if isinstance(node, ast.Attribute):
@@ -1743,6 +1755,13 @@ def visit_Lambda(self, node):
17431755
)
17441756
)
17451757

1758+
B033 = Error(
1759+
message=(
1760+
"B033 Sets should not contain duplicate items. Duplicate items will be replaced"
1761+
" with a single item at runtime."
1762+
)
1763+
)
1764+
17461765
# Warnings disabled by default.
17471766
B901 = Error(
17481767
message=(

tests/b033.py

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
"""
2+
Should emit:
3+
B033 - on lines 6-12
4+
"""
5+
6+
test = {1, 2, 3, 3, 5}
7+
test = {"a", "b", "c", "c", "e"}
8+
test = {True, False, True}
9+
test = {None, True, None}
10+
test = {3, 3.0}
11+
test = {1, True}
12+
test = {0, False}
13+
14+
test = {1, 2, 3, 3.5, 5}
15+
test = {"a", "b", "c", "d", "e"}
16+
test = {True, False}
17+
test = {None}

tests/test_bugbear.py

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -44,6 +44,7 @@
4444
B030,
4545
B031,
4646
B032,
47+
B033,
4748
B901,
4849
B902,
4950
B903,
@@ -487,6 +488,21 @@ def test_b032(self):
487488
)
488489
self.assertEqual(errors, expected)
489490

491+
def test_b033(self):
492+
filename = Path(__file__).absolute().parent / "b033.py"
493+
bbc = BugBearChecker(filename=str(filename))
494+
errors = list(bbc.run())
495+
expected = self.errors(
496+
B033(6, 7),
497+
B033(7, 7),
498+
B033(8, 7),
499+
B033(9, 7),
500+
B033(10, 7),
501+
B033(11, 7),
502+
B033(12, 7),
503+
)
504+
self.assertEqual(errors, expected)
505+
490506
def test_b908(self):
491507
filename = Path(__file__).absolute().parent / "b908.py"
492508
bbc = BugBearChecker(filename=str(filename))

0 commit comments

Comments
 (0)