Skip to content

Commit e389294

Browse files
authored
B022: No arguments passed to contextlib.suppress (#231)
* B022: No arguments passed to contextlib.suppress * Update README.rst * Disclaimer note on rule scope
1 parent 4a92ce5 commit e389294

File tree

4 files changed

+54
-0
lines changed

4 files changed

+54
-0
lines changed

README.rst

+6
Original file line numberDiff line numberDiff line change
@@ -141,6 +141,12 @@ garbage collection.
141141
**B021**: f-string used as docstring. This will be interpreted by python
142142
as a joined string rather than a docstring.
143143

144+
**B022**: No arguments passed to `contextlib.suppress`.
145+
No exceptions will be suppressed and therefore this context manager is redundant.
146+
N.B. this rule currently does not flag `suppress` calls to avoid potential false
147+
positives due to similarly named user-defined functions.
148+
149+
144150
Opinionated warnings
145151
~~~~~~~~~~~~~~~~~~~~
146152

bugbear.py

+22
Original file line numberDiff line numberDiff line change
@@ -387,6 +387,7 @@ def visit_Raise(self, node):
387387

388388
def visit_With(self, node):
389389
self.check_for_b017(node)
390+
self.check_for_b022(node)
390391
self.generic_visit(node)
391392

392393
def compose_call_path(self, node):
@@ -739,6 +740,20 @@ def check_for_b021(self, node):
739740
B021(node.body[0].value.lineno, node.body[0].value.col_offset)
740741
)
741742

743+
def check_for_b022(self, node):
744+
item = node.items[0]
745+
item_context = item.context_expr
746+
if (
747+
hasattr(item_context, "func")
748+
and hasattr(item_context.func, "value")
749+
and hasattr(item_context.func.value, "id")
750+
and item_context.func.value.id == "contextlib"
751+
and hasattr(item_context.func, "attr")
752+
and item_context.func.attr == "suppress"
753+
and len(item_context.args) == 0
754+
):
755+
self.errors.append(B022(node.lineno, node.col_offset))
756+
742757

743758
@attr.s
744759
class NameFinder(ast.NodeVisitor):
@@ -965,6 +980,13 @@ def visit(self, node):
965980
"This will be interpreted by python as a joined string rather than a docstring."
966981
)
967982
)
983+
B022 = Error(
984+
message=(
985+
"B022 No arguments passed to `contextlib.suppress`."
986+
"No exceptions will be suppressed and therefore this"
987+
"context manager is redundant."
988+
)
989+
)
968990

969991
# Warnings disabled by default.
970992
B901 = Error(

tests/b022.py

+19
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
"""
2+
Should emit:
3+
B022 - on lines 8
4+
"""
5+
6+
import contextlib
7+
8+
with contextlib.suppress():
9+
raise ValueError
10+
11+
with contextlib.suppress(ValueError):
12+
raise ValueError
13+
14+
exceptions_to_suppress = []
15+
if True:
16+
exceptions_to_suppress.append(ValueError)
17+
18+
with contextlib.suppress(*exceptions_to_suppress):
19+
raise ValueError

tests/test_bugbear.py

+7
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,7 @@
3232
B019,
3333
B020,
3434
B021,
35+
B022,
3536
B901,
3637
B902,
3738
B903,
@@ -303,6 +304,12 @@ def test_b021_classes(self):
303304
)
304305
self.assertEqual(errors, expected)
305306

307+
def test_b022(self):
308+
filename = Path(__file__).absolute().parent / "b022.py"
309+
bbc = BugBearChecker(filename=str(filename))
310+
errors = list(bbc.run())
311+
self.assertEqual(errors, self.errors(B022(8, 0)))
312+
306313
def test_b901(self):
307314
filename = Path(__file__).absolute().parent / "b901.py"
308315
bbc = BugBearChecker(filename=str(filename))

0 commit comments

Comments
 (0)