diff --git a/pyproject.toml b/pyproject.toml new file mode 100644 index 0000000..9f8f13d --- /dev/null +++ b/pyproject.toml @@ -0,0 +1,28 @@ +[tool.ruff] +line-length = 120 +target-version = "py312" +[tool.ruff.lint] +select = [ + "E", "F", # pycodestyle errors, pyflakes (unused imports/variables, undefined names) + "I", # import sorting (replaces isort) + "B", # bugbear: likely bugs + "ASYNC", # async mistakes + "RUF006", # un-referenced asyncio.create_task (tasks can be garbage-collected) +] +ignore = ["E501"] + +[tool.ruff.lint.isort] +known-first-party = ["db_module", "metrics_server", "rabbitmq_handler", "secret_manager", + "simple_logger_handler", "uvicorn_logger_config", "validator"] + +[tool.ruff.format] +indent-style = "tab" + +[tool.ruff.lint.flake8-bugbear] +extend-immutable-calls = [ + "fastapi.Depends", + "fastapi.Query", + "fastapi.Header", + "fastapi.Body", + "fastapi.Security", +] \ No newline at end of file diff --git a/requirements-dev.txt b/requirements-dev.txt new file mode 100644 index 0000000..92a80f4 --- /dev/null +++ b/requirements-dev.txt @@ -0,0 +1 @@ +ruff==0.17.0 diff --git a/src/dockerhub_api.py b/src/dockerhub_api.py index d0f4194..bebba64 100644 --- a/src/dockerhub_api.py +++ b/src/dockerhub_api.py @@ -1,4 +1,5 @@ import requests + from secret_manager import return_credentials from simple_logger_handler import setup_logger diff --git a/src/github_api.py b/src/github_api.py index afb8720..13deafe 100644 --- a/src/github_api.py +++ b/src/github_api.py @@ -1,4 +1,5 @@ import requests + from secret_manager import return_credentials from simple_logger_handler import setup_logger diff --git a/src/main.py b/src/main.py index 426922d..62048b0 100644 --- a/src/main.py +++ b/src/main.py @@ -1,16 +1,17 @@ -from fastapi import FastAPI, Depends, HTTPException, Response, Request -import uvicorn -from github_api import find_package_version_with_tag as find_package_version_with_tag_github -from dockerhub_api import find_package_version_with_tag as find_package_version_with_tag_dockerhub -import uvicorn -from contextlib import asynccontextmanager -from db_module import get_db, create_connection_pool, close_connection_pool, start_healthcheck_thread -from simple_logger_handler import setup_logger, LOG_LEVEL -from send_notification import send_notification -from metrics_server import REQUEST_COUNTER import asyncio -from uvicorn_logger_config import LOGGING_CONFIG +from contextlib import asynccontextmanager + +import uvicorn +from fastapi import Depends, FastAPI, HTTPException, Request, Response + +from db_module import close_connection_pool, create_connection_pool, get_db, start_healthcheck_thread +from dockerhub_api import find_package_version_with_tag as find_package_version_with_tag_dockerhub +from github_api import find_package_version_with_tag as find_package_version_with_tag_github +from metrics_server import REQUEST_COUNTER from secret_manager import cleanup_secret_files +from send_notification import send_notification +from simple_logger_handler import LOG_LEVEL, setup_logger +from uvicorn_logger_config import LOGGING_CONFIG logger = setup_logger(__name__) @@ -103,7 +104,7 @@ def handle_suwayomi( except Exception as e: logger.error(f"[App] Error in Suwayomi handler: {e}", exc_info=True) - raise HTTPException(status_code=500, detail=str(e)) + raise HTTPException(status_code=500, detail=str(e)) from e @@ -138,7 +139,7 @@ def handle_pihole( except Exception as e: logger.error(f"[App] Error in Pi-hole handler: {e}", exc_info=True) - raise HTTPException(status_code=500, detail=str(e)) + raise HTTPException(status_code=500, detail=str(e)) from e async def start_servers(): diff --git a/src/metrics_server.py b/src/metrics_server.py index c3fdc9b..15e7fd1 100644 --- a/src/metrics_server.py +++ b/src/metrics_server.py @@ -1,5 +1,5 @@ from fastapi import FastAPI, Response -from prometheus_client import generate_latest, CONTENT_TYPE_LATEST, Counter +from prometheus_client import CONTENT_TYPE_LATEST, Counter, generate_latest metrics_api = FastAPI(title="Metrics Server", description="Prometheus metrics endpoint") diff --git a/src/send_notification.py b/src/send_notification.py index 40ee006..e14d28e 100644 --- a/src/send_notification.py +++ b/src/send_notification.py @@ -1,11 +1,12 @@ -import requests -from requests.exceptions import RequestException, Timeout, ConnectionError, HTTPError -from fastapi import HTTPException -from secret_manager import return_credentials import os import time -from simple_logger_handler import setup_logger +import requests +from fastapi import HTTPException +from requests.exceptions import ConnectionError, HTTPError, RequestException, Timeout + +from secret_manager import return_credentials +from simple_logger_handler import setup_logger backend_api_url=os.getenv("BACKEND_API_URL","localhost:8101/internal/receive-notifications") api_key= return_credentials("/etc/secrets/api_key") @@ -50,15 +51,15 @@ def send_notification(notification:str,max_retries: int = 5,timeout: int = 5)->s logger.warning(f"[Notify] Attempt {attempt}/{max_retries} failed: {type(e).__name__}") if attempt == max_retries: logger.error(f"[Notify] All retry attempts failed for '{notification}'") - raise HTTPException(status_code=503, detail=f"Notification service unavailable: {type(e).__name__}") + raise HTTPException(status_code=503, detail=f"Notification service unavailable: {type(e).__name__}") from e sleep_time = 2 ** (attempt - 1) logger.debug(f"[Notify] Retrying in {sleep_time} seconds...") time.sleep(sleep_time) except HTTPError as e: logger.error(f"[Notify] HTTP {e.response.status_code}: {e.response.text}") - raise HTTPException(status_code=e.response.status_code, detail=e.response.text) + raise HTTPException(status_code=e.response.status_code, detail=e.response.text) from e except RequestException as e: logger.error(f"[Notify] Unexpected request failure: {e}") - raise HTTPException(status_code=500, detail=f"Request failed: {str(e)}") + raise HTTPException(status_code=500, detail=f"Request failed: {str(e)}") from e