diff --git a/bbot/cli.py b/bbot/cli.py index 97d7488088..ba4a243b35 100755 --- a/bbot/cli.py +++ b/bbot/cli.py @@ -28,7 +28,13 @@ scan_name = "" -async def _main(): +async def _main(): # noqa: C901,PLR0911,PLR0915 + """ + Future modifications should consider refactoring to reduce complexity. + * The McCabe cyclomatiic complexity is currently 43 vs 10 recommended. + * There are currently 13 return statements vs 6 recommended. + * There are currently 148 statements vs 50 recommended. + """ import asyncio import traceback from contextlib import suppress diff --git a/bbot/core/helpers/misc.py b/bbot/core/helpers/misc.py index f128cf004a..e8ac4ee015 100644 --- a/bbot/core/helpers/misc.py +++ b/bbot/core/helpers/misc.py @@ -1684,7 +1684,7 @@ def clean_old(d, keep=10, filter=lambda x: True, key=latest_mtime, reverse=True, except Exception as e: msg = f"Failed to delete directory: {path}, {e}" if raise_error: - raise errors.DirectoryDeletionError() + raise errors.DirectoryDeletionError log.warning(msg) diff --git a/bbot/core/modules.py b/bbot/core/modules.py index c83d34a96f..905f1b9ac1 100644 --- a/bbot/core/modules.py +++ b/bbot/core/modules.py @@ -267,7 +267,7 @@ def find_and_replace(self, **kwargs): def check_type(self, module, type): return self._preloaded[module]["type"] == type - def preload_module(self, module_file): + def preload_module(self, module_file): # noqa: C901,PLR0912 """ Preloads a BBOT module to gather its meta-information and dependencies. @@ -315,6 +315,10 @@ def preload_module(self, module_file): }, "sudo": false } + + Future modifications should consider refactoring to reduce complexity. + * The McCabe cyclomatiic complexity is currently 43 vs 10 recommended. + * There are currently 42 branches vs 12 recommended. """ watched_events = set() produced_events = set() diff --git a/bbot/modules/bucket_google.py b/bbot/modules/bucket_google.py index 1b87f639ee..32dccc516a 100644 --- a/bbot/modules/bucket_google.py +++ b/bbot/modules/bucket_google.py @@ -46,7 +46,7 @@ def build_url(self, bucket_name, base_domain, region): async def check_bucket_open(self, bucket_name, url): bad_permissions = [] try: - list_permissions = "&".join(["=".join(("permissions", p)) for p in self.bad_permissions]) + list_permissions = "&".join(f"permissions={p}" for p in self.bad_permissions) url = f"https://www.googleapis.com/storage/v1/b/{bucket_name}/iam/testPermissions?" + list_permissions response = await self.helpers.request(url) permissions = response.json() diff --git a/bbot/modules/docker_pull.py b/bbot/modules/docker_pull.py index 22888bce3c..2347815bd5 100644 --- a/bbot/modules/docker_pull.py +++ b/bbot/modules/docker_pull.py @@ -24,7 +24,7 @@ class docker_pull(BaseModule): async def setup(self): self.headers = { - "Accept": ",".join( + "Accept": ",".join( # noqa: FLY002 [ "application/vnd.docker.distribution.manifest.v2+json", "application/vnd.docker.distribution.manifest.list.v2+json", diff --git a/bbot/modules/filedownload.py b/bbot/modules/filedownload.py index 35287252bf..05cc8bb7e4 100644 --- a/bbot/modules/filedownload.py +++ b/bbot/modules/filedownload.py @@ -100,7 +100,7 @@ async def setup(self): with open(self.mime_db_file) as f: mime_db = json.load(f) for content_type, attrs in mime_db.items(): - if "extensions" in attrs and attrs["extensions"]: + if attrs.get("extensions"): self.mime_db[content_type] = attrs["extensions"][0].lower() return True diff --git a/bbot/modules/url_manipulation.py b/bbot/modules/url_manipulation.py index c36b7c39d5..5b0e1c94f8 100644 --- a/bbot/modules/url_manipulation.py +++ b/bbot/modules/url_manipulation.py @@ -53,7 +53,7 @@ async def handle_event(self, event): try: if not await compare_helper.canary_check(event.data, mode="getparam"): - raise HttpCompareError() + raise HttpCompareError except HttpCompareError: self.verbose(f'Aborting "{event.data}" due to failed canary check') return diff --git a/bbot/scanner/manager.py b/bbot/scanner/manager.py index 4b129d5243..51edc86117 100644 --- a/bbot/scanner/manager.py +++ b/bbot/scanner/manager.py @@ -137,7 +137,7 @@ async def get_incoming_event(self): return q.get_nowait() except (asyncio.queues.QueueEmpty, AttributeError): continue - raise asyncio.queues.QueueEmpty() + raise asyncio.queues.QueueEmpty def is_incoming_duplicate(self, event, add=False): """ diff --git a/bbot/test/fastapi_test.py b/bbot/test/fastapi_test.py index f0c7b2d789..c41174d9c2 100644 --- a/bbot/test/fastapi_test.py +++ b/bbot/test/fastapi_test.py @@ -1,4 +1,4 @@ -from typing import List +from typing import Annotated, List from bbot import Scanner from fastapi import FastAPI, Query @@ -6,7 +6,7 @@ @app.get("/start") -async def start(targets: List[str] = Query(...)): +async def start(targets: Annotated[List[str], Query(...)]): scanner = Scanner(*targets, modules=["httpx"]) events = [e async for e in scanner.async_start()] return [e.json() for e in events] diff --git a/bbot/test/test_step_2/module_tests/test_module_baddns.py b/bbot/test/test_step_2/module_tests/test_module_baddns.py index 288af7ae79..48b4df821d 100644 --- a/bbot/test/test_step_2/module_tests/test_module_baddns.py +++ b/bbot/test/test_step_2/module_tests/test_module_baddns.py @@ -6,7 +6,7 @@ class BaseTestBaddns(ModuleTestBase): targets = ["bad.dns"] config_overrides = {"dns": {"minimal": False}} - async def dispatchWHOIS(x): + async def dispatchWHOIS(self): return None def select_modules(self): diff --git a/bbot/test/test_step_2/module_tests/test_module_baddns_zone.py b/bbot/test/test_step_2/module_tests/test_module_baddns_zone.py index d8138a3f7c..ab6fa509b3 100644 --- a/bbot/test/test_step_2/module_tests/test_module_baddns_zone.py +++ b/bbot/test/test_step_2/module_tests/test_module_baddns_zone.py @@ -7,7 +7,7 @@ class BaseTestBaddns_zone(ModuleTestBase): targets = ["bad.dns"] config_overrides = {"dns": {"minimal": False}} - async def dispatchWHOIS(x): + async def dispatchWHOIS(self): return None diff --git a/bbot/test/test_step_2/module_tests/test_module_bucket_amazon.py b/bbot/test/test_step_2/module_tests/test_module_bucket_amazon.py index 7a5499b2e0..5615597b4e 100644 --- a/bbot/test/test_step_2/module_tests/test_module_bucket_amazon.py +++ b/bbot/test/test_step_2/module_tests/test_module_bucket_amazon.py @@ -3,7 +3,7 @@ from .base import ModuleTestBase from bbot.core.helpers.misc import rand_string -__all__ = ["random_bucket_name_1", "random_bucket_name_2", "random_bucket_name_3", "Bucket_Amazon_Base"] +__all__ = ["Bucket_Amazon_Base", "random_bucket_name_1", "random_bucket_name_2", "random_bucket_name_3"] # first one is a normal bucket random_bucket_name_1 = rand_string(15, digits=False) diff --git a/bbot/test/test_step_2/module_tests/test_module_neo4j.py b/bbot/test/test_step_2/module_tests/test_module_neo4j.py index c5df1e4748..9e18326f41 100644 --- a/bbot/test/test_step_2/module_tests/test_module_neo4j.py +++ b/bbot/test/test_step_2/module_tests/test_module_neo4j.py @@ -12,7 +12,7 @@ async def setup_before_prep(self, module_test): self.neo4j_used = False class MockResult: - async def data(s): + async def data(self): self.neo4j_used = True return [ { @@ -22,7 +22,7 @@ async def data(s): ] class MockSession: - async def run(s, *args, **kwargs): + async def run(self, *args, **kwargs): return MockResult() async def close(self): diff --git a/pyproject.toml b/pyproject.toml index 34974e1d3b..edc9b9dcb7 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -102,7 +102,82 @@ skip = "./docs/javascripts/vega*.js,./bbot/wordlists/*" [tool.ruff] line-length = 119 format.exclude = ["bbot/test/test_step_1/test_manager_*"] -lint.ignore = ["E402", "E721", "E741", "F401", "F403", "F405"] + +[tool.ruff.lint] +ignore = ["E402", "E501", "E721", "E741", "F401", "F403", "F405"] +mccabe.max-complexity = 31 +select = [ + "AIR", # Airflow + "C4", # flake8-comprehensions + "C90", # McCabe cyclomatic complexity + "DJ", # flake8-django + "E", # pycodestyle + "F", # Pyflakes + "FAST", # FastAPI + "FLY", # flynt + "ICN", # flake8-import-conventions + "INT", # flake8-gettext + "LOG", # flake8-logging + "NPY", # NumPy-specific rules + "PD", # pandas-vet + "PLR091", # Pylint Refactor just for max-args, max-branches, etc. + "PYI", # flake8-pyi + "RSE", # flake8-raise + "SLOT", # flake8-slots + "T10", # flake8-debugger + "TC", # flake8-type-checking + "W", # pycodestyle + "YTT", # flake8-2020 + # "A", # flake8-builtins + # "ANN", # flake8-annotations + # "ARG", # flake8-unused-arguments + # "ASYNC", # flake8-async + # "B", # flake8-bugbear + # "BLE", # flake8-blind-except + # "COM", # flake8-commas + # "CPY", # flake8-copyright + # "D", # pydocstyle + # "DOC", # pydoclint + # "DTZ", # flake8-datetimez + # "EM", # flake8-errmsg + # "ERA", # eradicate + # "EXE", # flake8-executable + # "FA", # flake8-future-annotations + # "FBT", # flake8-boolean-trap + # "FIX", # flake8-fixme + # "FURB", # refurb + # "G", # flake8-logging-format + # "I", # isort + # "INP", # flake8-no-pep420 + # "ISC", # flake8-implicit-str-concat + # "N", # pep8-naming + # "PERF", # Perflint + # "PGH", # pygrep-hooks + # "PIE", # flake8-pie + # "PL", # Pylint + # "PT", # flake8-pytest-style + # "PTH", # flake8-use-pathlib + # "Q", # flake8-quotes + # "RET", # flake8-return + # "RUF", # Ruff-specific rules + # "S", # flake8-bandit + # "SIM", # flake8-simplify + # "SLF", # flake8-self + # "T20", # flake8-print + # "TD", # flake8-todos + # "TID", # flake8-tidy-imports + # "TRY", # tryceratops + # "UP", # pyupgrade +] + +[tool.ruff.lint.per-file-ignores] +"bbot/test/test_step_1/test_*" = ["PLR0915"] + +[tool.ruff.lint.pylint] +max-args = 21 # Default is 5 +max-branches = 31 # Default is 12 +max-returns = 10 # Default is 6 +max-statements = 100 # Default is 50 [tool.poetry-dynamic-versioning] enable = true