From 47432c8ce4751a24a0399aec9df4109258811662 Mon Sep 17 00:00:00 2001 From: CarterPerez-dev Date: Wed, 18 Feb 2026 19:47:47 -0500 Subject: [PATCH] issue 77 pt2 ruff --- .github/workflows/lint.yml | 165 +++++++----------- .pre-commit-config.yaml | 91 +++++++++- .../backend/app/core/detection/rules.py | 2 +- .../backend/tests/test_api.py | 2 +- .../advanced/api-rate-limiter/examples/app.py | 2 - .../api-rate-limiter/tests/conftest.py | 17 +- .../api-rate-limiter/tests/test_algorithms.py | 6 +- .../tests/test_fingerprinting.py | 6 +- .../api-rate-limiter/tests/test_limiter.py | 4 +- .../api-rate-limiter/tests/test_storage.py | 4 - .../bug-bounty-platform/backend/app/config.py | 5 +- .../backend/app/factory.py | 4 +- .../backend/app/api/encryption.py | 1 - .../c2-beacon/backend/tests/conftest.py | 1 - .../c2-beacon/backend/tests/test_encoding.py | 1 - .../c2-beacon/backend/tests/test_protocol.py | 1 - .../c2-beacon/backend/tests/test_tasking.py | 3 +- .../beginner/dns-lookup/dnslookup/resolver.py | 5 +- .../scripts/generate_png_tests.py | 1 - .../src/commands/read.py | 1 - .../src/commands/scrub.py | 1 - .../src/commands/verify.py | 1 - .../src/core/png_metadata.py | 2 +- .../src/services/batch_processor.py | 1 - .../src/utils/display.py | 1 - .../tests/e2e/test_read_command.py | 1 - .../tests/e2e/test_scrub_command.py | 1 - .../tests/e2e/test_verify_command.py | 1 - .../integration/test_metadata_factory.py | 2 +- .../tests/test_filters.py | 6 +- .../tests/test_models.py | 67 +++---- .../backend/core/database.py | 2 +- .../backend/app/engine/normalizer.py | 3 +- 33 files changed, 209 insertions(+), 202 deletions(-) diff --git a/.github/workflows/lint.yml b/.github/workflows/lint.yml index a81d7d6c..2e6d18f1 100644 --- a/.github/workflows/lint.yml +++ b/.github/workflows/lint.yml @@ -21,18 +21,53 @@ jobs: fail-fast: false matrix: include: - - name: api-rate-limiter - type: python - path: PROJECTS/advanced/api-rate-limiter - - name: dns-lookup - type: python - path: PROJECTS/beginner/dns-lookup + # Python (ruff) - Beginner + - name: caesar-cipher + type: ruff + path: PROJECTS/beginner/caesar-cipher - name: keylogger - type: python + type: ruff path: PROJECTS/beginner/keylogger - - name: docker-security-audit - type: go - path: PROJECTS/beginner/docker-security-audit + - name: dns-lookup + type: ruff + path: PROJECTS/beginner/dns-lookup + - name: metadata-scrubber-tool + type: ruff + path: PROJECTS/beginner/metadata-scrubber-tool + - name: network-traffic-analyzer + type: ruff + path: PROJECTS/beginner/network-traffic-analyzer + - name: base64-tool + type: ruff + path: PROJECTS/beginner/base64-tool + - name: c2-beacon-backend + type: ruff + path: PROJECTS/beginner/c2-beacon/backend + # Python (ruff) - Intermediate + - name: api-security-scanner-backend + type: ruff + path: PROJECTS/intermediate/api-security-scanner/backend + - name: siem-dashboard-backend + type: ruff + path: PROJECTS/intermediate/siem-dashboard/backend + # Python (ruff) - Advanced + - name: bug-bounty-platform-backend + type: ruff + path: PROJECTS/advanced/bug-bounty-platform/backend + - name: encrypted-p2p-chat-backend + type: ruff + path: PROJECTS/advanced/encrypted-p2p-chat/backend + - name: api-rate-limiter + type: ruff + path: PROJECTS/advanced/api-rate-limiter + - name: ai-threat-detection-backend + type: ruff + path: PROJECTS/advanced/ai-threat-detection/backend + # Python (ruff) - Templates + - name: fullstack-template-backend + type: ruff + path: TEMPLATES/fullstack-template/backend + # Biome (frontend) - name: bug-bounty-platform-frontend type: biome path: PROJECTS/advanced/bug-bounty-platform/frontend @@ -51,6 +86,10 @@ jobs: - name: fullstack-template-frontend type: biome path: TEMPLATES/fullstack-template/frontend + # Go + - name: docker-security-audit + type: go + path: PROJECTS/beginner/docker-security-audit defaults: run: @@ -60,28 +99,16 @@ jobs: - name: Checkout code uses: actions/checkout@v4 - # Python Setup + # Ruff Setup - name: Set up Python - if: matrix.type == 'python' + if: matrix.type == 'ruff' uses: actions/setup-python@v5 with: python-version: '3.12' - - name: Cache pip dependencies - if: matrix.type == 'python' - uses: actions/cache@v4 - with: - path: ~/.cache/pip - key: ${{ runner.os }}-pip-${{ matrix.name }}-${{ hashFiles(format('{0}/pyproject.toml', matrix.path)) }} - restore-keys: | - ${{ runner.os }}-pip-${{ matrix.name }}- - ${{ runner.os }}-pip- - - - name: Install Python dependencies - if: matrix.type == 'python' - run: | - python -m pip install --upgrade pip - pip install -e ".[dev]" + - name: Install ruff + if: matrix.type == 'ruff' + run: pip install ruff # Biome Setup - name: Setup Node.js @@ -118,24 +145,9 @@ jobs: go-version: '1.21' cache-dependency-path: ${{ matrix.path }}/go.sum - # Python Linting - - name: Run pylint - if: matrix.type == 'python' - id: pylint - run: | - echo "Running pylint..." - if pylint . > pylint-output.txt 2>&1; then - echo "PYLINT_PASSED=true" >> $GITHUB_ENV - echo "No pylint errors found!" - else - echo "PYLINT_PASSED=false" >> $GITHUB_ENV - echo "Pylint found issues!" - fi - cat pylint-output.txt - continue-on-error: true - + # Ruff Linting - name: Run ruff - if: matrix.type == 'python' + if: matrix.type == 'ruff' id: ruff run: | echo "Running ruff check..." @@ -149,21 +161,6 @@ jobs: cat ruff-output.txt continue-on-error: true - - name: Run mypy - if: matrix.type == 'python' - id: mypy - run: | - echo "Running mypy..." - if mypy . > mypy-output.txt 2>&1; then - echo "MYPY_PASSED=true" >> $GITHUB_ENV - echo "No mypy errors found" - else - echo "MYPY_PASSED=false" >> $GITHUB_ENV - echo "Mypy found issues" - fi - cat mypy-output.txt - continue-on-error: true - # Biome Linting - name: Run Biome if: matrix.type == 'biome' @@ -196,30 +193,14 @@ jobs: cat golangci-output.txt continue-on-error: true - # Create Summary for Python - - name: Create Python Lint Summary - if: matrix.type == 'python' && github.event_name == 'pull_request' + # Create Summary for Ruff + - name: Create Ruff Lint Summary + if: matrix.type == 'ruff' && github.event_name == 'pull_request' run: | { echo "## Lint Results: ${{ matrix.name }}" echo '' - # Pylint Status - if [[ "${{ env.PYLINT_PASSED }}" == "true" ]]; then - echo '### Pylint: **Passed**' - echo 'No pylint issues found.' - else - echo '### Pylint: **Issues Found**' - echo '
View pylint output' - echo '' - echo '```' - head -100 pylint-output.txt - echo '```' - echo '
' - fi - echo '' - - # Ruff Status if [[ "${{ env.RUFF_PASSED }}" == "true" ]]; then echo '### Ruff: **Passed**' echo 'No ruff issues found.' @@ -234,23 +215,7 @@ jobs: fi echo '' - # Mypy Status - if [[ "${{ env.MYPY_PASSED }}" == "true" ]]; then - echo '### Mypy: **Passed**' - echo 'No mypy issues found.' - else - echo '### Mypy: **Issues Found**' - echo '
View mypy output' - echo '' - echo '```' - head -100 mypy-output.txt - echo '```' - echo '
' - fi - echo '' - - # Overall Summary - if [[ "${{ env.PYLINT_PASSED }}" == "true" ]] && [[ "${{ env.RUFF_PASSED }}" == "true" ]] && [[ "${{ env.MYPY_PASSED }}" == "true" ]]; then + if [[ "${{ env.RUFF_PASSED }}" == "true" ]]; then echo '---' echo '### All checks passed!' else @@ -269,7 +234,6 @@ jobs: echo "## Lint Results: ${{ matrix.name }}" echo '' - # Biome Status if [[ "${{ env.BIOME_PASSED }}" == "true" ]]; then echo '### Biome: **Passed**' echo 'No Biome issues found.' @@ -284,7 +248,6 @@ jobs: fi echo '' - # Overall Summary if [[ "${{ env.BIOME_PASSED }}" == "true" ]]; then echo '---' echo '### All checks passed!' @@ -304,7 +267,6 @@ jobs: echo "## Lint Results: ${{ matrix.name }}" echo '' - # golangci-lint Status if [[ "${{ env.GOLANGCI_PASSED }}" == "true" ]]; then echo '### golangci-lint: **Passed**' echo 'No golangci-lint issues found.' @@ -319,7 +281,6 @@ jobs: fi echo '' - # Overall Summary if [[ "${{ env.GOLANGCI_PASSED }}" == "true" ]]; then echo '---' echo '### All checks passed!' @@ -344,9 +305,9 @@ jobs: # Exit with proper status - name: Check lint status run: | - if [[ "${{ matrix.type }}" == "python" ]]; then - if [[ "${{ env.PYLINT_PASSED }}" == "false" ]] || [[ "${{ env.RUFF_PASSED }}" == "false" ]] || [[ "${{ env.MYPY_PASSED }}" == "false" ]]; then - echo "Python lint checks failed" + if [[ "${{ matrix.type }}" == "ruff" ]]; then + if [[ "${{ env.RUFF_PASSED }}" == "false" ]]; then + echo "Ruff lint checks failed" exit 1 fi elif [[ "${{ matrix.type }}" == "biome" ]]; then diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index eaae4495..8ee84f61 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -1,16 +1,95 @@ repos: - # Python Backend Ruff Checks + # Python Ruff Checks - repo: https://github.com/astral-sh/ruff-pre-commit - rev: v0.15.0 + rev: v0.15.1 hooks: + # Beginner projects - id: ruff - name: ruff check (backend) + name: ruff check (caesar-cipher) args: [--fix, --exit-non-zero-on-fix] - files: ^PROJECTS/api-security-scanner/backend/ - exclude: ^PROJECTS/api-security-scanner/backend/(\.venv|__pycache__|\.pytest_cache)/ + files: ^PROJECTS/beginner/caesar-cipher/ + exclude: (\.venv|__pycache__|\.pytest_cache)/ + - id: ruff + name: ruff check (keylogger) + args: [--fix, --exit-non-zero-on-fix] + files: ^PROJECTS/beginner/keylogger/ + exclude: (\.venv|__pycache__|\.pytest_cache)/ - # TODO: add additional ruff checks for remaining projects + - id: ruff + name: ruff check (dns-lookup) + args: [--fix, --exit-non-zero-on-fix] + files: ^PROJECTS/beginner/dns-lookup/ + exclude: (\.venv|__pycache__|\.pytest_cache)/ + + - id: ruff + name: ruff check (metadata-scrubber-tool) + args: [--fix, --exit-non-zero-on-fix] + files: ^PROJECTS/beginner/metadata-scrubber-tool/ + exclude: (\.venv|__pycache__|\.pytest_cache)/ + + - id: ruff + name: ruff check (network-traffic-analyzer) + args: [--fix, --exit-non-zero-on-fix] + files: ^PROJECTS/beginner/network-traffic-analyzer/ + exclude: (\.venv|__pycache__|\.pytest_cache)/ + + - id: ruff + name: ruff check (base64-tool) + args: [--fix, --exit-non-zero-on-fix] + files: ^PROJECTS/beginner/base64-tool/ + exclude: (\.venv|__pycache__|\.pytest_cache)/ + + - id: ruff + name: ruff check (c2-beacon backend) + args: [--fix, --exit-non-zero-on-fix] + files: ^PROJECTS/beginner/c2-beacon/backend/ + exclude: (\.venv|__pycache__|\.pytest_cache)/ + + # Intermediate projects + - id: ruff + name: ruff check (api-security-scanner backend) + args: [--fix, --exit-non-zero-on-fix] + files: ^PROJECTS/intermediate/api-security-scanner/backend/ + exclude: (\.venv|__pycache__|\.pytest_cache)/ + + - id: ruff + name: ruff check (siem-dashboard backend) + args: [--fix, --exit-non-zero-on-fix] + files: ^PROJECTS/intermediate/siem-dashboard/backend/ + exclude: (\.venv|__pycache__|\.pytest_cache)/ + + # Advanced projects + - id: ruff + name: ruff check (bug-bounty-platform backend) + args: [--fix, --exit-non-zero-on-fix] + files: ^PROJECTS/advanced/bug-bounty-platform/backend/ + exclude: (\.venv|__pycache__|\.pytest_cache)/ + + - id: ruff + name: ruff check (encrypted-p2p-chat backend) + args: [--fix, --exit-non-zero-on-fix] + files: ^PROJECTS/advanced/encrypted-p2p-chat/backend/ + exclude: (\.venv|__pycache__|\.pytest_cache)/ + + - id: ruff + name: ruff check (api-rate-limiter) + args: [--fix, --exit-non-zero-on-fix] + files: ^PROJECTS/advanced/api-rate-limiter/ + exclude: (\.venv|__pycache__|\.pytest_cache)/ + + - id: ruff + name: ruff check (ai-threat-detection backend) + args: [--fix, --exit-non-zero-on-fix] + files: ^PROJECTS/advanced/ai-threat-detection/backend/ + exclude: (\.venv|__pycache__|\.pytest_cache)/ + + # Templates + - id: ruff + name: ruff check (fullstack-template backend) + args: [--fix, --exit-non-zero-on-fix] + files: ^TEMPLATES/fullstack-template/backend/ + exclude: (\.venv|__pycache__|\.pytest_cache)/ # TODO: add golangci checks for GO projects diff --git a/PROJECTS/advanced/ai-threat-detection/backend/app/core/detection/rules.py b/PROJECTS/advanced/ai-threat-detection/backend/app/core/detection/rules.py index 92b41e8f..04a86c77 100644 --- a/PROJECTS/advanced/ai-threat-detection/backend/app/core/detection/rules.py +++ b/PROJECTS/advanced/ai-threat-detection/backend/app/core/detection/rules.py @@ -115,7 +115,7 @@ class RuleEngine: for trule in _THRESHOLD_RULES: value = features.get(trule.feature_key, 0) - if isinstance(value, (int, float)) and value > trule.threshold: + if isinstance(value, int | float) and value > trule.threshold: matched.append((trule.name, trule.score)) if not matched: diff --git a/PROJECTS/advanced/ai-threat-detection/backend/tests/test_api.py b/PROJECTS/advanced/ai-threat-detection/backend/tests/test_api.py index 8441e262..45b33567 100644 --- a/PROJECTS/advanced/ai-threat-detection/backend/tests/test_api.py +++ b/PROJECTS/advanced/ai-threat-detection/backend/tests/test_api.py @@ -26,7 +26,7 @@ async def test_health_returns_200() -> None: data = response.json() assert data["status"] == "healthy" assert "uptime_seconds" in data - assert isinstance(data["uptime_seconds"], (int, float)) + assert isinstance(data["uptime_seconds"], int | float) assert "pipeline_running" in data diff --git a/PROJECTS/advanced/api-rate-limiter/examples/app.py b/PROJECTS/advanced/api-rate-limiter/examples/app.py index 142af93c..1b0ffd8d 100644 --- a/PROJECTS/advanced/api-rate-limiter/examples/app.py +++ b/PROJECTS/advanced/api-rate-limiter/examples/app.py @@ -6,7 +6,6 @@ app.py from __future__ import annotations import uvicorn -from typing import Annotated from contextlib import asynccontextmanager from fastapi import ( @@ -17,7 +16,6 @@ from fastapi import ( from fastapi_420 import ( RateLimiter, RateLimiterSettings, - RateLimitMiddleware, ScopedRateLimiter, FingerprintSettings, StorageSettings, diff --git a/PROJECTS/advanced/api-rate-limiter/tests/conftest.py b/PROJECTS/advanced/api-rate-limiter/tests/conftest.py index 0473431c..9370889f 100644 --- a/PROJECTS/advanced/api-rate-limiter/tests/conftest.py +++ b/PROJECTS/advanced/api-rate-limiter/tests/conftest.py @@ -10,15 +10,12 @@ import time from collections.abc import AsyncGenerator, Generator from dataclasses import dataclass, field from typing import Any -from unittest.mock import MagicMock import pytest from fastapi import FastAPI, Request from httpx import ASGITransport, AsyncClient from starlette.testclient import TestClient -from fastapi_420.algorithms import create_algorithm -from fastapi_420.algorithms.base import BaseAlgorithm from fastapi_420.algorithms.fixed_window import FixedWindowAlgorithm from fastapi_420.algorithms.sliding_window import SlidingWindowAlgorithm from fastapi_420.algorithms.token_bucket import TokenBucketAlgorithm @@ -50,7 +47,6 @@ from fastapi_420.types import ( RateLimitKey, RateLimitResult, RateLimitRule, - StorageType, TokenBucketState, WindowState, ) @@ -687,7 +683,7 @@ def rate_limiter_settings( @pytest.fixture -async def memory_storage() -> AsyncGenerator[MemoryStorage, None]: +async def memory_storage() -> AsyncGenerator[MemoryStorage]: """ Create and manage MemoryStorage instance """ @@ -791,8 +787,7 @@ async def circuit_breaker() -> CircuitBreaker: async def rate_limiter( rate_limiter_settings: RateLimiterSettings, memory_storage: MemoryStorage, -) -> AsyncGenerator[RateLimiter, - None]: +) -> AsyncGenerator[RateLimiter]: """ Create and manage RateLimiter instance """ @@ -922,8 +917,7 @@ async def test_app_with_limiter( @pytest.fixture -async def async_client(test_app: FastAPI) -> AsyncGenerator[AsyncClient, - None]: +async def async_client(test_app: FastAPI) -> AsyncGenerator[AsyncClient]: """ Create async HTTP client for testing """ @@ -937,8 +931,7 @@ async def async_client(test_app: FastAPI) -> AsyncGenerator[AsyncClient, @pytest.fixture async def rate_limited_client( test_app_with_limiter: FastAPI, -) -> AsyncGenerator[AsyncClient, - None]: +) -> AsyncGenerator[AsyncClient]: """ Create async HTTP client with rate limiting """ @@ -950,7 +943,7 @@ async def rate_limited_client( @pytest.fixture -def sync_client(test_app: FastAPI) -> Generator[TestClient, None, None]: +def sync_client(test_app: FastAPI) -> Generator[TestClient]: """ Create sync test client """ diff --git a/PROJECTS/advanced/api-rate-limiter/tests/test_algorithms.py b/PROJECTS/advanced/api-rate-limiter/tests/test_algorithms.py index 70d68e6a..681966d5 100644 --- a/PROJECTS/advanced/api-rate-limiter/tests/test_algorithms.py +++ b/PROJECTS/advanced/api-rate-limiter/tests/test_algorithms.py @@ -4,7 +4,6 @@ test_algorithms.py """ from __future__ import annotations -import time import pytest @@ -17,7 +16,6 @@ from fastapi_420.types import Algorithm from tests.conftest import ( WINDOW_MINUTE, - WINDOW_SECOND, RuleFactory, ) @@ -75,8 +73,8 @@ class TestSlidingWindowAlgorithm: storage = MemoryStorage() rule = RuleFactory.per_minute(100) - for i in range(50): - result = await algo.check(storage, f"multi_key", rule) + for _i in range(50): + result = await algo.check(storage, "multi_key", rule) assert result.allowed is True assert result.remaining == 50 diff --git a/PROJECTS/advanced/api-rate-limiter/tests/test_fingerprinting.py b/PROJECTS/advanced/api-rate-limiter/tests/test_fingerprinting.py index 09a68b9a..d0d3bbff 100644 --- a/PROJECTS/advanced/api-rate-limiter/tests/test_fingerprinting.py +++ b/PROJECTS/advanced/api-rate-limiter/tests/test_fingerprinting.py @@ -67,7 +67,7 @@ class TestIPExtractor: def test_ipv6_custom_prefix_length(self) -> None: extractor = IPExtractor(ipv6_prefix_length = 48) request = RequestFactory.create(client_ip = TEST_IP_V6) - raw_ip, normalized_ip = extractor.extract(request) + _, normalized_ip = extractor.extract(request) assert "::" in normalized_ip or normalized_ip != TEST_IP_V6 @@ -75,7 +75,7 @@ class TestIPExtractor: extractor = IPExtractor() ipv4_mapped = "::ffff:192.168.1.100" request = RequestFactory.create(client_ip = ipv4_mapped) - raw_ip, normalized_ip = extractor.extract(request) + _, normalized_ip = extractor.extract(request) assert normalized_ip == "192.168.1.100" @@ -323,7 +323,7 @@ class TestAuthExtractor: extractor = AuthExtractor(hash_identifiers = False) request = RequestFactory.with_auth( auth_type = "bearer", - token = "invalid" + token = "invalid" # noqa: S106 ) identifier = extractor.extract(request) diff --git a/PROJECTS/advanced/api-rate-limiter/tests/test_limiter.py b/PROJECTS/advanced/api-rate-limiter/tests/test_limiter.py index 3694f7b6..874f1a92 100644 --- a/PROJECTS/advanced/api-rate-limiter/tests/test_limiter.py +++ b/PROJECTS/advanced/api-rate-limiter/tests/test_limiter.py @@ -10,11 +10,9 @@ from fastapi_420.config import RateLimiterSettings from fastapi_420.exceptions import EnhanceYourCalm, HTTP_420_ENHANCE_YOUR_CALM from fastapi_420.limiter import RateLimiter from fastapi_420.storage import MemoryStorage -from fastapi_420.types import Algorithm, FingerprintLevel +from fastapi_420.types import Algorithm from tests.conftest import ( - WINDOW_MINUTE, - DEFAULT_LIMIT_REQUESTS, RequestFactory, ) diff --git a/PROJECTS/advanced/api-rate-limiter/tests/test_storage.py b/PROJECTS/advanced/api-rate-limiter/tests/test_storage.py index 349b7245..397196df 100644 --- a/PROJECTS/advanced/api-rate-limiter/tests/test_storage.py +++ b/PROJECTS/advanced/api-rate-limiter/tests/test_storage.py @@ -15,8 +15,6 @@ from fastapi_420.types import StorageType from tests.conftest import ( WINDOW_MINUTE, - WINDOW_SECOND, - DEFAULT_LIMIT_REQUESTS, ) @@ -163,7 +161,6 @@ class TestMemoryStorageSlidingWindow: previous_window = current_window - 1 prev_key = f"{key}:{previous_window}" - curr_key = f"{key}:{current_window}" storage._windows[prev_key] = storage._windows.__class__().__class__ from fastapi_420.storage.memory import WindowEntry @@ -360,7 +357,6 @@ class TestMemoryStorageCleanup: storage = MemoryStorage(cleanup_interval = 1) await storage.start_cleanup_task() - task = storage._cleanup_task await storage.close() assert storage._cleanup_task is None diff --git a/PROJECTS/advanced/bug-bounty-platform/backend/app/config.py b/PROJECTS/advanced/bug-bounty-platform/backend/app/config.py index 77261727..89cafe19 100644 --- a/PROJECTS/advanced/bug-bounty-platform/backend/app/config.py +++ b/PROJECTS/advanced/bug-bounty-platform/backend/app/config.py @@ -188,9 +188,8 @@ class Settings(BaseSettings): """ Enforce security constraints in production environment. """ - if self.ENVIRONMENT == Environment.PRODUCTION: - if self.DEBUG: - raise ValueError("DEBUG must be False in production") + if self.ENVIRONMENT == Environment.PRODUCTION and self.DEBUG: + raise ValueError("DEBUG must be False in production") return self diff --git a/PROJECTS/advanced/bug-bounty-platform/backend/app/factory.py b/PROJECTS/advanced/bug-bounty-platform/backend/app/factory.py index c8f790e4..87024b26 100644 --- a/PROJECTS/advanced/bug-bounty-platform/backend/app/factory.py +++ b/PROJECTS/advanced/bug-bounty-platform/backend/app/factory.py @@ -12,7 +12,7 @@ from fastapi.responses import JSONResponse from slowapi import _rate_limit_exceeded_handler from slowapi.errors import RateLimitExceeded -from config import settings, Environment, API_PREFIX +from config import settings, API_PREFIX from core.database import sessionmanager from core.exceptions import BaseAppException from core.logging import configure_logging @@ -74,8 +74,6 @@ def create_app() -> FastAPI: """ Application factory """ - is_production = settings.ENVIRONMENT == Environment.PRODUCTION - app = FastAPI( title = settings.APP_NAME, summary = settings.APP_SUMMARY, diff --git a/PROJECTS/advanced/encrypted-p2p-chat/backend/app/api/encryption.py b/PROJECTS/advanced/encrypted-p2p-chat/backend/app/api/encryption.py index 1a30faf2..355e7504 100644 --- a/PROJECTS/advanced/encrypted-p2p-chat/backend/app/api/encryption.py +++ b/PROJECTS/advanced/encrypted-p2p-chat/backend/app/api/encryption.py @@ -4,7 +4,6 @@ Encryption endpoints for X3DH prekey bundles """ import logging -from typing import Optional from uuid import UUID from fastapi import APIRouter, Depends, status diff --git a/PROJECTS/beginner/c2-beacon/backend/tests/conftest.py b/PROJECTS/beginner/c2-beacon/backend/tests/conftest.py index 196689ea..2acc3424 100644 --- a/PROJECTS/beginner/c2-beacon/backend/tests/conftest.py +++ b/PROJECTS/beginner/c2-beacon/backend/tests/conftest.py @@ -3,7 +3,6 @@ AngelaMos | 2026 conftest.py """ -import tempfile from pathlib import Path import pytest diff --git a/PROJECTS/beginner/c2-beacon/backend/tests/test_encoding.py b/PROJECTS/beginner/c2-beacon/backend/tests/test_encoding.py index 4c4027f8..02ee1842 100644 --- a/PROJECTS/beginner/c2-beacon/backend/tests/test_encoding.py +++ b/PROJECTS/beginner/c2-beacon/backend/tests/test_encoding.py @@ -3,7 +3,6 @@ AngelaMos | 2026 test_encoding.py """ -import pytest from core.encoding import decode, encode, xor_bytes diff --git a/PROJECTS/beginner/c2-beacon/backend/tests/test_protocol.py b/PROJECTS/beginner/c2-beacon/backend/tests/test_protocol.py index a837c453..53604bde 100644 --- a/PROJECTS/beginner/c2-beacon/backend/tests/test_protocol.py +++ b/PROJECTS/beginner/c2-beacon/backend/tests/test_protocol.py @@ -8,7 +8,6 @@ import pytest from core.models import CommandType from core.protocol import Message, MessageType, pack, unpack - TEST_KEY = "test-protocol-key" diff --git a/PROJECTS/beginner/c2-beacon/backend/tests/test_tasking.py b/PROJECTS/beginner/c2-beacon/backend/tests/test_tasking.py index 631639cd..8d56f224 100644 --- a/PROJECTS/beginner/c2-beacon/backend/tests/test_tasking.py +++ b/PROJECTS/beginner/c2-beacon/backend/tests/test_tasking.py @@ -172,11 +172,12 @@ class TestTaskManager: await asyncio.sleep(0.1) await task_manager.submit(_make_task("delayed"), db) - asyncio.create_task(delayed_submit()) + background_task = asyncio.create_task(delayed_submit()) retrieved = await asyncio.wait_for( task_manager.get_next("beacon-t"), timeout=2.0 ) assert retrieved.id == "delayed" + await background_task def test_remove_queue(self, task_manager: TaskManager) -> None: """ diff --git a/PROJECTS/beginner/dns-lookup/dnslookup/resolver.py b/PROJECTS/beginner/dns-lookup/dnslookup/resolver.py index 31a121b5..165b94d1 100644 --- a/PROJECTS/beginner/dns-lookup/dnslookup/resolver.py +++ b/PROJECTS/beginner/dns-lookup/dnslookup/resolver.py @@ -9,10 +9,7 @@ from __future__ import annotations import asyncio import time -from dataclasses import ( - dataclass, - field -) +from dataclasses import dataclass, field from enum import StrEnum from typing import Any diff --git a/PROJECTS/beginner/metadata-scrubber-tool/scripts/generate_png_tests.py b/PROJECTS/beginner/metadata-scrubber-tool/scripts/generate_png_tests.py index 7cab3219..ac1a6d6b 100644 --- a/PROJECTS/beginner/metadata-scrubber-tool/scripts/generate_png_tests.py +++ b/PROJECTS/beginner/metadata-scrubber-tool/scripts/generate_png_tests.py @@ -5,7 +5,6 @@ from pathlib import Path from PIL import Image, PngImagePlugin - dest_dir = Path("tests/assets/test_images") # Generate 45 PNG images with various metadata diff --git a/PROJECTS/beginner/metadata-scrubber-tool/src/commands/read.py b/PROJECTS/beginner/metadata-scrubber-tool/src/commands/read.py index c827b0da..01ba37ff 100644 --- a/PROJECTS/beginner/metadata-scrubber-tool/src/commands/read.py +++ b/PROJECTS/beginner/metadata-scrubber-tool/src/commands/read.py @@ -15,7 +15,6 @@ from src.services.metadata_factory import MetadataFactory from src.utils.display import print_metadata_table from src.utils.get_target_files import get_target_files - console = Console() log = logging.getLogger("metadata-scrubber") diff --git a/PROJECTS/beginner/metadata-scrubber-tool/src/commands/scrub.py b/PROJECTS/beginner/metadata-scrubber-tool/src/commands/scrub.py index ef6f3b1c..c580f33e 100644 --- a/PROJECTS/beginner/metadata-scrubber-tool/src/commands/scrub.py +++ b/PROJECTS/beginner/metadata-scrubber-tool/src/commands/scrub.py @@ -27,7 +27,6 @@ from src.services.batch_processor import BatchProcessor from src.utils.display import print_batch_summary from src.utils.get_target_files import get_target_files - console = Console() log = logging.getLogger("metadata-scrubber") diff --git a/PROJECTS/beginner/metadata-scrubber-tool/src/commands/verify.py b/PROJECTS/beginner/metadata-scrubber-tool/src/commands/verify.py index 2b40810f..f0a99c9b 100644 --- a/PROJECTS/beginner/metadata-scrubber-tool/src/commands/verify.py +++ b/PROJECTS/beginner/metadata-scrubber-tool/src/commands/verify.py @@ -14,7 +14,6 @@ from rich.console import Console from src.services.metadata_factory import MetadataFactory from src.services.report_generator import ReportGenerator - console = Console() log = logging.getLogger("metadata-scrubber") diff --git a/PROJECTS/beginner/metadata-scrubber-tool/src/core/png_metadata.py b/PROJECTS/beginner/metadata-scrubber-tool/src/core/png_metadata.py index f970a28a..30cf78d9 100644 --- a/PROJECTS/beginner/metadata-scrubber-tool/src/core/png_metadata.py +++ b/PROJECTS/beginner/metadata-scrubber-tool/src/core/png_metadata.py @@ -91,7 +91,7 @@ class PngProcessor: if key in ("icc_profile", "exif", "transparency", "gamma"): continue - if isinstance(value, (str, bytes)): + if isinstance(value, str | bytes): found_metadata = True if isinstance(value, bytes): try: diff --git a/PROJECTS/beginner/metadata-scrubber-tool/src/services/batch_processor.py b/PROJECTS/beginner/metadata-scrubber-tool/src/services/batch_processor.py index b7bee94a..222452de 100644 --- a/PROJECTS/beginner/metadata-scrubber-tool/src/services/batch_processor.py +++ b/PROJECTS/beginner/metadata-scrubber-tool/src/services/batch_processor.py @@ -19,7 +19,6 @@ from rich.console import Console from src.services.metadata_factory import MetadataFactory - log = logging.getLogger("metadata-scrubber") console = Console() diff --git a/PROJECTS/beginner/metadata-scrubber-tool/src/utils/display.py b/PROJECTS/beginner/metadata-scrubber-tool/src/utils/display.py index 04ea030b..531d8e4f 100644 --- a/PROJECTS/beginner/metadata-scrubber-tool/src/utils/display.py +++ b/PROJECTS/beginner/metadata-scrubber-tool/src/utils/display.py @@ -15,7 +15,6 @@ from rich.text import Text from src.utils.formatter import clean_value - console = Console() diff --git a/PROJECTS/beginner/metadata-scrubber-tool/tests/e2e/test_read_command.py b/PROJECTS/beginner/metadata-scrubber-tool/tests/e2e/test_read_command.py index bc4cb48a..4640b6ec 100644 --- a/PROJECTS/beginner/metadata-scrubber-tool/tests/e2e/test_read_command.py +++ b/PROJECTS/beginner/metadata-scrubber-tool/tests/e2e/test_read_command.py @@ -22,7 +22,6 @@ from tests.conftest import ( get_xlsx_test_file, ) - runner = CliRunner() # Test file paths (cross-platform) diff --git a/PROJECTS/beginner/metadata-scrubber-tool/tests/e2e/test_scrub_command.py b/PROJECTS/beginner/metadata-scrubber-tool/tests/e2e/test_scrub_command.py index d9e77734..b00cb35c 100644 --- a/PROJECTS/beginner/metadata-scrubber-tool/tests/e2e/test_scrub_command.py +++ b/PROJECTS/beginner/metadata-scrubber-tool/tests/e2e/test_scrub_command.py @@ -22,7 +22,6 @@ from tests.conftest import ( get_xlsx_test_file, ) - runner = CliRunner() # Test file paths (cross-platform) diff --git a/PROJECTS/beginner/metadata-scrubber-tool/tests/e2e/test_verify_command.py b/PROJECTS/beginner/metadata-scrubber-tool/tests/e2e/test_verify_command.py index 0d9592ac..0da4bad0 100644 --- a/PROJECTS/beginner/metadata-scrubber-tool/tests/e2e/test_verify_command.py +++ b/PROJECTS/beginner/metadata-scrubber-tool/tests/e2e/test_verify_command.py @@ -13,7 +13,6 @@ from typer.testing import CliRunner from src.main import app - runner = CliRunner() diff --git a/PROJECTS/beginner/metadata-scrubber-tool/tests/integration/test_metadata_factory.py b/PROJECTS/beginner/metadata-scrubber-tool/tests/integration/test_metadata_factory.py index 78a62220..bd46ac79 100644 --- a/PROJECTS/beginner/metadata-scrubber-tool/tests/integration/test_metadata_factory.py +++ b/PROJECTS/beginner/metadata-scrubber-tool/tests/integration/test_metadata_factory.py @@ -44,7 +44,7 @@ def test_read_image_metadata(x): assert handler.metadata == metadata assert isinstance(metadata, dict) - if isinstance(handler, (JpegProcessor, PngProcessor)): + if isinstance(handler, JpegProcessor | PngProcessor): assert ( handler.tags_to_delete is not None or handler.text_keys_to_delete is not None ) diff --git a/PROJECTS/beginner/network-traffic-analyzer/tests/test_filters.py b/PROJECTS/beginner/network-traffic-analyzer/tests/test_filters.py index 8ecf2c4a..eda0abf3 100644 --- a/PROJECTS/beginner/network-traffic-analyzer/tests/test_filters.py +++ b/PROJECTS/beginner/network-traffic-analyzer/tests/test_filters.py @@ -91,7 +91,7 @@ class TestFilterBuilder: Verify OR operator joins expressions """ result = ( - FilterBuilder().port(80).port(443).build(operator = "or") + FilterBuilder().port(80).port(443).build(operator="or") ) assert result == "port 80 or port 443" @@ -137,14 +137,14 @@ class TestCombineFilters: """ Verify multiple filters combine with AND """ - result = combine_filters(["tcp", "port 80"], operator = "and") + result = combine_filters(["tcp", "port 80"], operator="and") assert result == "(tcp) and (port 80)" def test_combine_multiple_or(self): """ Verify multiple filters combine with OR """ - result = combine_filters(["port 80", "port 443"], operator = "or") + result = combine_filters(["port 80", "port 443"], operator="or") assert result == "(port 80) or (port 443)" diff --git a/PROJECTS/beginner/network-traffic-analyzer/tests/test_models.py b/PROJECTS/beginner/network-traffic-analyzer/tests/test_models.py index 73e691c6..1f68ebc4 100644 --- a/PROJECTS/beginner/network-traffic-analyzer/tests/test_models.py +++ b/PROJECTS/beginner/network-traffic-analyzer/tests/test_models.py @@ -5,6 +5,7 @@ test_models.py Basic happy path tests for data models """ + import pytest from netanal.models import ( @@ -43,16 +44,16 @@ class TestPacketInfo: Verify PacketInfo stores all fields correctly """ packet = PacketInfo( - timestamp = 1234567890.123, - src_ip = "192.168.1.1", - dst_ip = "192.168.1.2", - protocol = Protocol.TCP, - size = 1500, - src_port = 443, - dst_port = 54321, + timestamp=1234567890.123, + src_ip="192.168.1.1", + dst_ip="192.168.1.2", + protocol=Protocol.TCP, + size=1500, + src_port=443, + dst_port=54321, ) - assert packet.timestamp == 1234567890.123 + assert packet.timestamp == pytest.approx(1234567890.123) assert packet.src_ip == "192.168.1.1" assert packet.dst_ip == "192.168.1.2" assert packet.protocol == Protocol.TCP @@ -65,11 +66,11 @@ class TestPacketInfo: Verify optional fields default to None """ packet = PacketInfo( - timestamp = 0.0, - src_ip = "10.0.0.1", - dst_ip = "10.0.0.2", - protocol = Protocol.ICMP, - size = 64, + timestamp=0.0, + src_ip="10.0.0.1", + dst_ip="10.0.0.2", + protocol=Protocol.ICMP, + size=64, ) assert packet.src_port is None @@ -99,16 +100,16 @@ class TestCaptureConfig: Verify custom configuration is stored correctly """ config = CaptureConfig( - interface = "eth0", - bpf_filter = "tcp port 80", - packet_count = 100, - timeout_seconds = 30.0, + interface="eth0", + bpf_filter="tcp port 80", + packet_count=100, + timeout_seconds=30.0, ) assert config.interface == "eth0" assert config.bpf_filter == "tcp port 80" assert config.packet_count == 100 - assert config.timeout_seconds == 30.0 + assert config.timeout_seconds == pytest.approx(30.0) class TestEndpointStats: @@ -119,7 +120,7 @@ class TestEndpointStats: """ Verify total_packets and total_bytes computed properties """ - endpoint = EndpointStats(ip_address = "192.168.1.100") + endpoint = EndpointStats(ip_address="192.168.1.100") endpoint.packets_sent = 50 endpoint.packets_received = 30 endpoint.bytes_sent = 5000 @@ -149,36 +150,36 @@ class TestCaptureStatistics: Verify duration_seconds computed property """ stats = CaptureStatistics( - start_time = 1000.0, - end_time = 1010.0, + start_time=1000.0, + end_time=1010.0, ) - assert stats.duration_seconds == 10.0 + assert stats.duration_seconds == pytest.approx(10.0) def test_average_bandwidth(self): """ Verify average_bandwidth calculation (bytes/second) """ stats = CaptureStatistics( - start_time = 1000.0, - end_time = 1010.0, - total_bytes = 10000, + start_time=1000.0, + end_time=1010.0, + total_bytes=10000, ) - assert stats.average_bandwidth == 1000.0 + assert stats.average_bandwidth == pytest.approx(1000.0) def test_protocol_percentages(self): """ Verify get_protocol_percentages returns correct distribution """ - stats = CaptureStatistics(total_packets = 100) + stats = CaptureStatistics(total_packets=100) stats.protocol_distribution[Protocol.TCP] = 70 stats.protocol_distribution[Protocol.UDP] = 30 percentages = stats.get_protocol_percentages() - assert percentages[Protocol.TCP] == 70.0 - assert percentages[Protocol.UDP] == 30.0 + assert percentages[Protocol.TCP] == pytest.approx(70.0) + assert percentages[Protocol.UDP] == pytest.approx(30.0) def test_top_talkers(self): """ @@ -186,15 +187,15 @@ class TestCaptureStatistics: """ stats = CaptureStatistics() - endpoint1 = EndpointStats(ip_address = "192.168.1.1") + endpoint1 = EndpointStats(ip_address="192.168.1.1") endpoint1.bytes_sent = 1000 endpoint1.bytes_received = 500 - endpoint2 = EndpointStats(ip_address = "192.168.1.2") + endpoint2 = EndpointStats(ip_address="192.168.1.2") endpoint2.bytes_sent = 5000 endpoint2.bytes_received = 2000 - endpoint3 = EndpointStats(ip_address = "192.168.1.3") + endpoint3 = EndpointStats(ip_address="192.168.1.3") endpoint3.bytes_sent = 100 endpoint3.bytes_received = 50 @@ -202,7 +203,7 @@ class TestCaptureStatistics: stats.endpoints["192.168.1.2"] = endpoint2 stats.endpoints["192.168.1.3"] = endpoint3 - top = stats.get_top_talkers(limit = 2) + top = stats.get_top_talkers(limit=2) assert len(top) == 2 assert top[0].ip_address == "192.168.1.2" diff --git a/PROJECTS/intermediate/api-security-scanner/backend/core/database.py b/PROJECTS/intermediate/api-security-scanner/backend/core/database.py index d90feeae..3f6e273c 100644 --- a/PROJECTS/intermediate/api-security-scanner/backend/core/database.py +++ b/PROJECTS/intermediate/api-security-scanner/backend/core/database.py @@ -28,7 +28,7 @@ SessionLocal = sessionmaker( Base = declarative_base() -def get_db() -> Generator[Session, None, None]: +def get_db() -> Generator[Session]: """ FastAPI dependency for database sessions """ diff --git a/PROJECTS/intermediate/siem-dashboard/backend/app/engine/normalizer.py b/PROJECTS/intermediate/siem-dashboard/backend/app/engine/normalizer.py index 968db07c..184bf0e8 100644 --- a/PROJECTS/intermediate/siem-dashboard/backend/app/engine/normalizer.py +++ b/PROJECTS/intermediate/siem-dashboard/backend/app/engine/normalizer.py @@ -4,7 +4,8 @@ normalizer.py """ from datetime import datetime, UTC -from typing import Any, Callable +from typing import Any +from collections.abc import Callable from app.models.LogEvent import SourceType