Skip to content

Commit c90fa65

Browse files
authored
B014: catch binascii.Error and ValueError redundancy + cleanup (#206)
I am honestly a bit embarrassed by my old code. Let's fix it up with better comments and clearer names.
1 parent 71091f9 commit c90fa65

File tree

4 files changed

+34
-16
lines changed

4 files changed

+34
-16
lines changed

README.rst

+6
Original file line numberDiff line numberDiff line change
@@ -224,6 +224,12 @@ MIT
224224
Change Log
225225
----------
226226

227+
Unreleased
228+
~~~~~~~~~~
229+
230+
* Update B014: ``binascii.Error`` is now treated as a subclass of ``ValueError``
231+
(#206)
232+
227233
21.9.2
228234
~~~~~~~~~~
229235

bugbear.py

+12-9
Original file line numberDiff line numberDiff line change
@@ -193,13 +193,12 @@ def visit_ExceptHandler(self, node):
193193
good = sorted(set(names), key=names.index)
194194
if "BaseException" in good:
195195
good = ["BaseException"]
196-
# Find and remove aliases exceptions and only leave the primary alone
197-
primaries = filter(
198-
lambda primary: primary in good, B014.exception_aliases.keys()
199-
)
200-
for primary in primaries:
201-
aliases = B014.exception_aliases[primary]
202-
good = list(filter(lambda e: e not in aliases, good))
196+
# Remove redundant exceptions that the automatic system either handles
197+
# poorly (usually aliases) or can't be checked (e.g. it's not an
198+
# built-in exception).
199+
for primary, equivalents in B014.redundant_exceptions.items():
200+
if primary in good:
201+
good = [g for g in good if g not in equivalents]
203202

204203
for name, other in itertools.permutations(tuple(good), 2):
205204
if _typesafe_issubclass(
@@ -758,15 +757,19 @@ def visit(self, node):
758757
"Write `except {2}{1}:`, which catches exactly the same exceptions."
759758
)
760759
)
761-
B014.exception_aliases = {
760+
B014.redundant_exceptions = {
762761
"OSError": {
762+
# All of these are actually aliases of OSError since Python 3.3
763763
"IOError",
764764
"EnvironmentError",
765765
"WindowsError",
766766
"mmap.error",
767767
"socket.error",
768768
"select.error",
769-
}
769+
},
770+
"ValueError": {
771+
"binascii.Error",
772+
},
770773
}
771774
B015 = Error(
772775
message=(

tests/b014.py

+9-1
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,9 @@
11
"""
22
Should emit:
3-
B014 - on lines 10, 16, 27, 41, 48, and 55
3+
B014 - on lines 11, 17, 28, 42, 49, 56, and 74.
44
"""
55

6+
import binascii
67
import re
78

89
try:
@@ -66,3 +67,10 @@ class MyError(Exception):
6667
except (MyException, NotImplemented):
6768
# NotImplemented is not an exception, let's not crash on it.
6869
pass
70+
71+
72+
try:
73+
pass
74+
except (ValueError, binascii.Error):
75+
# binascii.Error is a subclass of ValueError.
76+
pass

tests/test_bugbear.py

+7-6
Original file line numberDiff line numberDiff line change
@@ -179,16 +179,17 @@ def test_b014(self):
179179
bbc = BugBearChecker(filename=str(filename))
180180
errors = list(bbc.run())
181181
expected = self.errors(
182-
B014(10, 0, vars=("Exception, TypeError", "", "Exception")),
183-
B014(16, 0, vars=("OSError, OSError", " as err", "OSError")),
184-
B014(27, 0, vars=("MyError, MyError", "", "MyError")),
185-
B014(41, 0, vars=("MyError, BaseException", " as e", "BaseException")),
186-
B014(48, 0, vars=("re.error, re.error", "", "re.error")),
182+
B014(11, 0, vars=("Exception, TypeError", "", "Exception")),
183+
B014(17, 0, vars=("OSError, OSError", " as err", "OSError")),
184+
B014(28, 0, vars=("MyError, MyError", "", "MyError")),
185+
B014(42, 0, vars=("MyError, BaseException", " as e", "BaseException")),
186+
B014(49, 0, vars=("re.error, re.error", "", "re.error")),
187187
B014(
188-
55,
188+
56,
189189
0,
190190
vars=("IOError, EnvironmentError, OSError", "", "OSError"),
191191
),
192+
B014(74, 0, vars=("ValueError, binascii.Error", "", "ValueError")),
192193
)
193194
self.assertEqual(errors, expected)
194195

0 commit comments

Comments
 (0)