Skip to content

Commit

Permalink
Add Option to extend the list of immutable calls (#204)
Browse files Browse the repository at this point in the history
* add option to extend the list of immutable calls

* update README.rst about `extend-immutable-calls` option

Co-authored-by: Tobias Klare <[email protected]>
Co-authored-by: Cooper Lees <[email protected]>
  • Loading branch information
3 people authored Nov 27, 2021
1 parent c90fa65 commit c452048
Show file tree
Hide file tree
Showing 4 changed files with 62 additions and 2 deletions.
8 changes: 8 additions & 0 deletions README.rst
Original file line number Diff line number Diff line change
Expand Up @@ -206,6 +206,14 @@ by default. Those get enabled as soon as there is an ``ignore =`` line
in your configuration. I think this behavior is surprising so Bugbear's
opinionated warnings require explicit selection.

Configuration
-------------

The plugin currently has one setting:

``extend-immutable-calls``: Specify a list of additional immutable calls.
This could be useful, when using other libraries that provide more immutable calls,
beside those already handled by ``flake8-bugbear``. Calls to these method will no longer raise a ``B008`` warning.

Tests
-----
Expand Down
25 changes: 23 additions & 2 deletions bugbear.py
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,17 @@ class BugBearChecker:
def run(self):
if not self.tree or not self.lines:
self.load_file()
visitor = self.visitor(filename=self.filename, lines=self.lines)

if self.options and hasattr(self.options, "extend_immutable_calls"):
b008_extend_immutable_calls = set(self.options.extend_immutable_calls)
else:
b008_extend_immutable_calls = set()

visitor = self.visitor(
filename=self.filename,
lines=self.lines,
b008_extend_immutable_calls=b008_extend_immutable_calls,
)
visitor.visit(self.tree)
for e in itertools.chain(visitor.errors, self.gen_line_based_checks()):
if self.should_warn(e.message[:4]):
Expand Down Expand Up @@ -73,6 +83,13 @@ def load_file(self):
def add_options(optmanager):
"""Informs flake8 to ignore B9xx by default."""
optmanager.extend_default_ignore(disabled_by_default)
optmanager.add_option(
"--extend-immutable-calls",
comma_separated_list=True,
parse_from_config=True,
default=[],
help="Skip B008 test for additional immutable calls.",
)

@lru_cache()
def should_warn(self, code):
Expand Down Expand Up @@ -146,6 +163,7 @@ def _typesafe_issubclass(cls, class_or_tuple):
class BugBearVisitor(ast.NodeVisitor):
filename = attr.ib()
lines = attr.ib()
b008_extend_immutable_calls = attr.ib(default=attr.Factory(set))
node_stack = attr.ib(default=attr.Factory(list))
node_window = attr.ib(default=attr.Factory(list))
errors = attr.ib(default=attr.Factory(list))
Expand Down Expand Up @@ -338,7 +356,10 @@ def check_for_b006(self, node):
call_path = ".".join(self.compose_call_path(default.func))
if call_path in B006.mutable_calls:
self.errors.append(B006(default.lineno, default.col_offset))
elif call_path not in B008.immutable_calls:
elif (
call_path
not in B008.immutable_calls | self.b008_extend_immutable_calls
):
# Check if function call is actually a float infinity/NaN literal
if call_path == "float" and len(default.args) == 1:
float_arg = default.args[0]
Expand Down
16 changes: 16 additions & 0 deletions tests/b008_extended.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
from typing import List

import fastapi
from fastapi import Query


def this_is_okay_extended(db=fastapi.Depends(get_db)):
...


def this_is_okay_extended_second(data: List[str] = fastapi.Query(None)):
...


def this_is_not_okay_relative_import_not_listed(data: List[str] = Query(None)):
...
15 changes: 15 additions & 0 deletions tests/test_bugbear.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
import sys
import unittest
from pathlib import Path
from unittest.mock import Mock

from hypothesis import HealthCheck, given, settings
from hypothesmith import from_grammar
Expand Down Expand Up @@ -125,6 +126,20 @@ def test_b007(self):
),
)

def test_b008_extended(self):
filename = Path(__file__).absolute().parent / "b008_extended.py"

mock_options = Mock()
mock_options.extend_immutable_calls = ["fastapi.Depends", "fastapi.Query"]

bbc = BugBearChecker(filename=str(filename), options=mock_options)
errors = list(bbc.run())

self.assertEqual(
errors,
self.errors(B008(15, 66)),
)

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

0 comments on commit c452048

Please sign in to comment.