Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions README.rst
Original file line number Diff line number Diff line change
Expand Up @@ -177,6 +177,8 @@ limitations make it difficult.
stacklevel of 1 by default. This will only show a stack trace for the line on which the warn method is called.
It is therefore recommended to use a stacklevel of 2 or greater to provide more information to the user.

**B029**: Using ``except: ()`` with an empty tuple does not handle/catch anything. Add exceptions to handle.

Opinionated warnings
~~~~~~~~~~~~~~~~~~~~

Expand Down Expand Up @@ -325,6 +327,7 @@ Future
order to maintain backwards compatibility with Python 3.7.
* B016: Warn when raising f-strings.
* Add B028: Check for an explicit stacklevel keyword argument on the warn method from the warnings module.
* Add B029: Check when trying to use ``except`` with an empty tuple i.e. ``except: ()``.

23.1.20
~~~~~~~~~
Expand Down
15 changes: 9 additions & 6 deletions bugbear.py
Original file line number Diff line number Diff line change
Expand Up @@ -276,15 +276,12 @@ def visit(self, node):

def visit_ExceptHandler(self, node):
if node.type is None:
self.errors.append(
B001(node.lineno, node.col_offset, vars=("bare `except:`",))
)
self.errors.append(B001(node.lineno, node.col_offset))
elif isinstance(node.type, ast.Tuple):
names = [_to_name_str(e) for e in node.type.elts]
as_ = " as " + node.name if node.name is not None else ""
if len(names) == 0:
vs = (f"`except (){as_}:`",)
self.errors.append(B001(node.lineno, node.col_offset, vars=vs))
self.errors.append(B029(node.lineno, node.col_offset))
elif len(names) == 1:
self.errors.append(B013(node.lineno, node.col_offset, vars=names))
else:
Expand Down Expand Up @@ -1285,7 +1282,7 @@ def visit_Lambda(self, node):

B001 = Error(
message=(
"B001 Do not use {}, it also catches unexpected "
"B001 Do not use bare `except:`, it also catches unexpected "
"events like memory errors, interrupts, system exit, and so on. "
"Prefer `except Exception:`. If you're sure what you're doing, "
"be explicit and write `except BaseException:`."
Expand Down Expand Up @@ -1530,6 +1527,12 @@ def visit_Lambda(self, node):
" greater to provide more information to the user."
)
)
B029 = Error(
message=(
"B029 Using `except: ()` with an empty tuple does not handle/catch "
"anything. Add exceptions to handle."
)
)

# Warnings disabled by default.
B901 = Error(
Expand Down
9 changes: 1 addition & 8 deletions tests/b001.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
"""
Should emit:
B001 - on lines 8, 40, and 54
B001 - on lines 8 and 40
"""

try:
Expand Down Expand Up @@ -40,10 +40,3 @@ def func(**kwargs):
except:
# should be except KeyError:
return


try:
pass
except ():
# Literal empty tuple is just like bare except:
pass
14 changes: 14 additions & 0 deletions tests/b029.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
"""
Should emit:
B029 - on lines 8 and 13
"""

try:
pass
except ():
pass

try:
pass
except () as e:
pass
16 changes: 13 additions & 3 deletions tests/test_bugbear.py
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,7 @@
B026,
B027,
B028,
B029,
B901,
B902,
B903,
Expand All @@ -64,9 +65,8 @@ def test_b001(self):
bbc = BugBearChecker(filename=str(filename))
errors = list(bbc.run())
expected = self.errors(
B001(8, 0, vars=("bare `except:`",)),
B001(40, 4, vars=("bare `except:`",)),
B001(47, 0, vars=("`except ():`",)),
B001(8, 0),
B001(40, 4),
)
self.assertEqual(errors, expected)

Expand Down Expand Up @@ -438,6 +438,16 @@ def test_b028(self):
expected = self.errors(B028(8, 0), B028(9, 0))
self.assertEqual(errors, expected)

def test_b029(self):
filename = Path(__file__).absolute().parent / "b029.py"
bbc = BugBearChecker(filename=str(filename))
errors = list(bbc.run())
expected = self.errors(
B029(8, 0),
B029(13, 0),
)
self.assertEqual(errors, expected)

@unittest.skipIf(sys.version_info < (3, 8), "not implemented for <3.8")
def test_b907(self):
filename = Path(__file__).absolute().parent / "b907.py"
Expand Down