Skip to content

Commit ab0868d

Browse files
authored
Remove Python Compatibility Warnings (#182)
- The world has move to Python 3 - If people need these checks they can pin to 21.4.3 Tests: Ensure all remaining tests still pass Fixes #177
1 parent ceffb5e commit ab0868d

File tree

6 files changed

+2
-262
lines changed

6 files changed

+2
-262
lines changed

Diff for: README.rst

-39
Original file line numberDiff line numberDiff line change
@@ -131,45 +131,6 @@ Either assert for a more specific exception (builtin or custom), use
131131
data available in ``ex``.
132132

133133

134-
Python 3 compatibility warnings
135-
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
136-
137-
These have higher risk of false positives but discover regressions that
138-
are dangerous to slip through when test coverage is not great. Let me
139-
know if a popular library is triggering any of the following warnings
140-
for valid code.
141-
142-
**B301**: Python 3 does not include ``.iter*`` methods on dictionaries.
143-
The default behavior is to return iterables. Simply remove the ``iter``
144-
prefix from the method. For Python 2 compatibility, also prefer the
145-
Python 3 equivalent if you expect that the size of the dict to be small
146-
and bounded. The performance regression on Python 2 will be negligible
147-
and the code is going to be the clearest. Alternatively, use
148-
``six.iter*`` or ``future.utils.iter*``.
149-
150-
**B302**: Python 3 does not include ``.view*`` methods on dictionaries.
151-
The default behavior is to return viewables. Simply remove the ``view``
152-
prefix from the method. For Python 2 compatibility, also prefer the
153-
Python 3 equivalent if you expect that the size of the dict to be small
154-
and bounded. The performance regression on Python 2 will be negligible
155-
and the code is going to be the clearest. Alternatively, use
156-
``six.view*`` or ``future.utils.view*``.
157-
158-
**B303**: The ``__metaclass__`` attribute on a class definition does
159-
nothing on Python 3. Use ``class MyClass(BaseClass, metaclass=...)``.
160-
For Python 2 compatibility, use ``six.add_metaclass``.
161-
162-
**B304**: ``sys.maxint`` is not a thing on Python 3. Use
163-
``sys.maxsize``.
164-
165-
**B305**: ``.next()`` is not a thing on Python 3. Use the ``next()``
166-
builtin. For Python 2 compatibility, use ``six.next()``.
167-
168-
**B306**: ``BaseException.message`` has been deprecated as of Python 2.6
169-
and is removed in Python 3. Use ``str(e)`` to access the user-readable
170-
message. Use ``e.args`` to access arguments passed to the exception.
171-
172-
173134
Opinionated warnings
174135
~~~~~~~~~~~~~~~~~~~~
175136

Diff for: bugbear.py

+2-80
Original file line numberDiff line numberDiff line change
@@ -226,14 +226,7 @@ def visit_UAdd(self, node):
226226

227227
def visit_Call(self, node):
228228
if isinstance(node.func, ast.Attribute):
229-
for bug in (B301, B302, B305):
230-
if node.func.attr in bug.methods:
231-
call_path = ".".join(self.compose_call_path(node.func.value))
232-
if call_path not in bug.valid_paths:
233-
self.errors.append(bug(node.lineno, node.col_offset))
234-
break
235-
else:
236-
self.check_for_b005(node)
229+
self.check_for_b005(node)
237230
else:
238231
with suppress(AttributeError, IndexError):
239232
if (
@@ -258,25 +251,8 @@ def visit_Call(self, node):
258251

259252
self.generic_visit(node)
260253

261-
def visit_Attribute(self, node):
262-
call_path = list(self.compose_call_path(node))
263-
if ".".join(call_path) == "sys.maxint":
264-
self.errors.append(B304(node.lineno, node.col_offset))
265-
elif len(call_path) == 2 and call_path[1] == "message":
266-
name = call_path[0]
267-
for elem in reversed(self.node_stack[:-1]):
268-
if isinstance(elem, ast.ExceptHandler) and elem.name == name:
269-
self.errors.append(B306(node.lineno, node.col_offset))
270-
break
271-
272254
def visit_Assign(self, node):
273-
if isinstance(self.node_stack[-2], ast.ClassDef):
274-
# note: by hasattr below we're ignoring starred arguments, slices
275-
# and tuples for simplicity.
276-
assign_targets = {t.id for t in node.targets if hasattr(t, "id")}
277-
if "__metaclass__" in assign_targets:
278-
self.errors.append(B303(node.lineno, node.col_offset))
279-
elif len(node.targets) == 1:
255+
if len(node.targets) == 1:
280256
t = node.targets[0]
281257
if isinstance(t, ast.Attribute) and isinstance(t.value, ast.Name):
282258
if (t.value.id, t.attr) == ("os", "environ"):
@@ -771,60 +747,6 @@ def visit(self, node):
771747
)
772748
)
773749

774-
# Those could be false positives but it's more dangerous to let them slip
775-
# through if they're not.
776-
B301 = Error(
777-
message=(
778-
"B301 Python 3 does not include `.iter*` methods on dictionaries. "
779-
"Remove the `iter` prefix from the method name. For Python 2 "
780-
"compatibility, prefer the Python 3 equivalent unless you expect "
781-
"the size of the container to be large or unbounded. Then use "
782-
"`six.iter*` or `future.utils.iter*`."
783-
)
784-
)
785-
B301.methods = {"iterkeys", "itervalues", "iteritems", "iterlists"}
786-
B301.valid_paths = {"six", "future.utils", "builtins"}
787-
788-
B302 = Error(
789-
message=(
790-
"B302 Python 3 does not include `.view*` methods on dictionaries. "
791-
"Remove the `view` prefix from the method name. For Python 2 "
792-
"compatibility, prefer the Python 3 equivalent unless you expect "
793-
"the size of the container to be large or unbounded. Then use "
794-
"`six.view*` or `future.utils.view*`."
795-
)
796-
)
797-
B302.methods = {"viewkeys", "viewvalues", "viewitems", "viewlists"}
798-
B302.valid_paths = {"six", "future.utils", "builtins"}
799-
800-
B303 = Error(
801-
message=(
802-
"B303 `__metaclass__` does nothing on Python 3. Use "
803-
"`class MyClass(BaseClass, metaclass=...)`. For Python 2 "
804-
"compatibility, use `six.add_metaclass`."
805-
)
806-
)
807-
808-
B304 = Error(message="B304 `sys.maxint` is not a thing on Python 3. Use `sys.maxsize`.")
809-
810-
B305 = Error(
811-
message=(
812-
"B305 `.next()` is not a thing on Python 3. Use the `next()` "
813-
"builtin. For Python 2 compatibility, use `six.next()`."
814-
)
815-
)
816-
B305.methods = {"next"}
817-
B305.valid_paths = {"six", "future.utils", "builtins"}
818-
819-
B306 = Error(
820-
message=(
821-
"B306 `BaseException.message` has been deprecated as of Python "
822-
"2.6 and is removed in Python 3. Use `str(e)` to access the "
823-
"user-readable message. Use `e.args` to access arguments passed "
824-
"to the exception."
825-
)
826-
)
827-
828750
# Warnings disabled by default.
829751
B901 = Error(
830752
message=(

Diff for: tests/b301_b302_b305.py

-48
This file was deleted.

Diff for: tests/b303_b304.py

-46
This file was deleted.

Diff for: tests/b306.py

-11
This file was deleted.

Diff for: tests/test_bugbear.py

-38
Original file line numberDiff line numberDiff line change
@@ -28,12 +28,6 @@
2828
B015,
2929
B016,
3030
B017,
31-
B301,
32-
B302,
33-
B303,
34-
B304,
35-
B305,
36-
B306,
3731
B901,
3832
B902,
3933
B903,
@@ -213,38 +207,6 @@ def test_b017(self):
213207
expected = self.errors(B017(22, 8))
214208
self.assertEqual(errors, expected)
215209

216-
def test_b301_b302_b305(self):
217-
filename = Path(__file__).absolute().parent / "b301_b302_b305.py"
218-
bbc = BugBearChecker(filename=str(filename))
219-
errors = list(bbc.run())
220-
self.assertEqual(
221-
errors,
222-
self.errors(
223-
B301(39, 4),
224-
B301(40, 4),
225-
B301(41, 4),
226-
B301(42, 4),
227-
B302(43, 4),
228-
B302(44, 4),
229-
B302(45, 4),
230-
B302(46, 4),
231-
B305(47, 4),
232-
B305(48, 4),
233-
),
234-
)
235-
236-
def test_b303_b304(self):
237-
filename = Path(__file__).absolute().parent / "b303_b304.py"
238-
bbc = BugBearChecker(filename=str(filename))
239-
errors = list(bbc.run())
240-
self.assertEqual(errors, self.errors(B303(25, 4), B304(46, 4)))
241-
242-
def test_b306(self):
243-
filename = Path(__file__).absolute().parent / "b306.py"
244-
bbc = BugBearChecker(filename=str(filename))
245-
errors = list(bbc.run())
246-
self.assertEqual(errors, self.errors(B306(9, 10)))
247-
248210
def test_b901(self):
249211
filename = Path(__file__).absolute().parent / "b901.py"
250212
bbc = BugBearChecker(filename=str(filename))

0 commit comments

Comments
 (0)