Skip to content

Commit

Permalink
add b905: require strict= argument to zip()
Browse files Browse the repository at this point in the history
  • Loading branch information
jakkdl committed Dec 6, 2022
1 parent 356f0dc commit e4de78e
Show file tree
Hide file tree
Showing 4 changed files with 44 additions and 3 deletions.
5 changes: 4 additions & 1 deletion README.rst
Expand Up @@ -200,6 +200,8 @@ or ``raise ... from None`` to distinguish them from errors in exception handling
See `the exception chaining tutorial <https://docs.python.org/3/tutorial/errors.html#exception-chaining>`_
for details.

**B905**: `zip()` without an explicit `strict=` parameter. Added with python3.10, so don't enable this flag for code that should work on previous versions. https://peps.python.org/pep-0618/

**B950**: Line too long. This is a pragmatic equivalent of
``pycodestyle``'s ``E501``: it considers "max-line-length" but only triggers
when the value has been exceeded by **more than 10%**. You will no
Expand Down Expand Up @@ -299,7 +301,8 @@ Change Log

Future
~~~~~~~~~
* B027: ignore @overload when typing is import with other names
* B027: ignore @overload when typing is imported with other names
* Add B905: `zip()` without an explicit `strict=` parameter.

22.10.27
~~~~~~~~~
Expand Down
13 changes: 12 additions & 1 deletion bugbear.py
Expand Up @@ -356,6 +356,7 @@ def visit_Call(self, node):

self.check_for_b026(node)

self.check_for_b905(node)
self.generic_visit(node)

def visit_Assign(self, node):
Expand Down Expand Up @@ -960,6 +961,14 @@ def check_for_b025(self, node):
for duplicate in duplicates:
self.errors.append(B025(node.lineno, node.col_offset, vars=(duplicate,)))

def check_for_b905(self, node):
if (
isinstance(node.func, ast.Name)
and node.func.id == "zip"
and not any(kw.arg == "strict" for kw in node.keywords)
):
self.errors.append(B905(node.lineno, node.col_offset))


def compose_call_path(node):
if isinstance(node, ast.Attribute):
Expand Down Expand Up @@ -1360,6 +1369,8 @@ def visit_Lambda(self, node):
)
)

B905 = Error(message="B905 `zip()` without an explicit `strict=` parameter.")

B950 = Error(message="B950 line too long ({} > {} characters)")

disabled_by_default = ["B901", "B902", "B903", "B904", "B950"]
disabled_by_default = ["B901", "B902", "B903", "B904", "B905", "B950"]
10 changes: 10 additions & 0 deletions tests/b905_py310.py
@@ -0,0 +1,10 @@
zip()
zip(range(3))
zip("a", "b")
zip("a", "b", *zip("c"))
zip(zip("a"), strict=False)
zip(zip("a", strict=True))

zip(range(3), strict=True)
zip("a", "b", strict=False)
zip("a", "b", "c", strict=True)
19 changes: 18 additions & 1 deletion tests/test_bugbear.py
Expand Up @@ -42,6 +42,7 @@
B902,
B903,
B904,
B905,
B950,
BugBearChecker,
BugBearVisitor,
Expand Down Expand Up @@ -297,7 +298,7 @@ def test_b019(self):
def test_b020(self):
filename = Path(__file__).absolute().parent / "b020.py"
bbc = BugBearChecker(filename=str(filename))
errors = list(bbc.run())
errors = list(e for e in bbc.run() if e[2][:4] == "B020")
self.assertEqual(
errors,
self.errors(
Expand Down Expand Up @@ -484,6 +485,22 @@ def test_b904(self):
]
self.assertEqual(errors, self.errors(*expected))

@unittest.skipIf(sys.version_info < (3, 10), "requires 3.10+")
def test_b905(self):
filename = Path(__file__).absolute().parent / "b905_py310.py"
bbc = BugBearChecker(filename=str(filename))
errors = list(bbc.run())
expected = [
B905(1, 0),
B905(2, 0),
B905(3, 0),
B905(4, 0),
B905(4, 15),
B905(5, 4),
B905(6, 0),
]
self.assertEqual(errors, self.errors(*expected))

def test_b950(self):
filename = Path(__file__).absolute().parent / "b950.py"
bbc = BugBearChecker(filename=str(filename))
Expand Down

0 comments on commit e4de78e

Please sign in to comment.