Skip to content

Commit c045a45

Browse files
authored
Merge branch 'master' into more_implicit_cls_methods
2 parents 817004b + 9f7c082 commit c045a45

File tree

5 files changed

+47
-3
lines changed

5 files changed

+47
-3
lines changed

Diff for: README.rst

+9
Original file line numberDiff line numberDiff line change
@@ -90,6 +90,9 @@ ahead of time.
9090
property access: ``x.attr = val``. There is no additional safety in
9191
using ``setattr`` if you know the attribute name ahead of time.
9292

93+
**B011**: Do not call `assert False` since `python -O` removes these calls.
94+
Instead callers should `raise AssertionError()`.
95+
9396

9497
Python 3 compatibility warnings
9598
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
@@ -233,6 +236,12 @@ MIT
233236
Change Log
234237
----------
235238

239+
19.3.0
240+
~~~~~~
241+
242+
* For B902, the first argument for metaclass class methods can be
243+
"mcs", matching the name preferred by PyCharm.
244+
236245
18.2.0
237246
~~~~~~
238247

Diff for: bugbear.py

+13-2
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,3 @@
1-
#!/usr/bin/env python3
21
import ast
32
from collections import namedtuple
43
from contextlib import suppress
@@ -208,6 +207,10 @@ def visit_For(self, node):
208207
self.check_for_b007(node)
209208
self.generic_visit(node)
210209

210+
def visit_Assert(self, node):
211+
self.check_for_b011(node)
212+
self.generic_visit(node)
213+
211214
def visit_AsyncFunctionDef(self, node):
212215
self.check_for_b902(node)
213216
self.check_for_b006(node)
@@ -273,6 +276,10 @@ def check_for_b007(self, node):
273276
n = targets.names[name][0]
274277
self.errors.append(B007(n.lineno, n.col_offset, vars=(name,)))
275278

279+
def check_for_b011(self, node):
280+
if isinstance(node.test, ast.NameConstant) and node.test.value is False:
281+
self.errors.append(B011(node.lineno, node.col_offset))
282+
276283
def check_for_b901(self, node):
277284
xs = list(node.body)
278285
has_yield = False
@@ -494,6 +501,10 @@ def visit(self, node):
494501
message="B010 Do not call setattr with a constant attribute value, "
495502
"it is not any safer than normal property access."
496503
)
504+
B011 = Error(
505+
message="B011 Do not call assert False since python -O removes these calls. "
506+
"Instead callers should raise AssertionError()."
507+
)
497508

498509

499510
# Those could be false positives but it's more dangerous to let them slip
@@ -552,7 +563,7 @@ def visit(self, node):
552563
B902.implicit_classmethods = {"__new__", "__init_subclass__", "__class_getitem__"}
553564
B902.self = ["self"] # it's a list because the first is preferred
554565
B902.cls = ["cls", "klass"] # ditto.
555-
B902.metacls = ["metacls", "metaclass", "typ"] # ditto.
566+
B902.metacls = ["metacls", "metaclass", "typ", "mcs"] # ditto.
556567

557568
B903 = Error(
558569
message="B903 Data class should either be immutable or use __slots__ to "

Diff for: tests/b011.py

+10
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
"""
2+
Should emit:
3+
B011 - on line 8
4+
B011 - on line 10
5+
"""
6+
7+
assert 1 != 2
8+
assert False
9+
assert 1 != 2, "message"
10+
assert False, "message"

Diff for: tests/b902.py

+5-1
Original file line numberDiff line numberDiff line change
@@ -72,6 +72,10 @@ def __init__(self, name, bases, d):
7272
def __prepare__(cls, name, bases):
7373
return {}
7474

75+
@classmethod
76+
def first_arg_mcs_allowed(mcs, value):
77+
...
78+
7579

7680
def type_factory():
7781
return object
@@ -95,4 +99,4 @@ def __init_subclass__(cls, *args, **kwargs):
9599
...
96100

97101
def __class_getitem__(cls, key):
98-
...
102+
...

Diff for: tests/test_bugbear.py

+10
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@
1414
B008,
1515
B009,
1616
B010,
17+
B011,
1718
B301,
1819
B302,
1920
B303,
@@ -110,6 +111,15 @@ def test_b009_b010(self):
110111
errors = list(bbc.run())
111112
self.assertEqual(errors, self.errors(B009(15, 0), B010(22, 0)))
112113

114+
def test_b011(self):
115+
filename = Path(__file__).absolute().parent / 'b011.py'
116+
bbc = BugBearChecker(filename=str(filename))
117+
errors = list(bbc.run())
118+
self.assertEqual(
119+
errors,
120+
self.errors(B011(8, 0, vars=('i',)), B011(10, 0, vars=('k',))),
121+
)
122+
113123
def test_b301_b302_b305(self):
114124
filename = Path(__file__).absolute().parent / "b301_b302_b305.py"
115125
bbc = BugBearChecker(filename=str(filename))

0 commit comments

Comments
 (0)