From 4e088547ff205d38310d4f11df250c9aeb13b146 Mon Sep 17 00:00:00 2001 From: Florian Date: Tue, 13 Oct 2026 10:07:01 +0200 Subject: [PATCH] Added Ruff linting --- pyproject.toml | 28 +++++++++++++++++++++++++ requirements-dev.txt | 1 + src/main.py | 48 ++++++++++++++++++++++--------------------- src/metrics_server.py | 2 +- src/validator.py | 4 +++- 5 files changed, 58 insertions(+), 25 deletions(-) create mode 100644 pyproject.toml create mode 100644 requirements-dev.txt 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/main.py b/src/main.py index e5950ed..b4f8856 100644 --- a/src/main.py +++ b/src/main.py @@ -1,23 +1,25 @@ -from fastapi import FastAPI, Depends, HTTPException, Request +import asyncio +import os +import uuid +from contextlib import asynccontextmanager +from hashlib import sha256 +from typing import List, Optional + +import httpx +import uvicorn +from fastapi import Depends, FastAPI, HTTPException, Request from fastapi.responses import JSONResponse from fastapi.security.api_key import APIKeyHeader -from starlette.exceptions import HTTPException as StarletteHTTPException -from typing import Optional,List from pydantic import BaseModel -from validator import is_valid_platform,is_valid_token,verify_api_key -from secret_manager.fernet_encryption import encrypt_token -from secret_manager import cleanup_secret_files, return_credentials -from db_module import get_db, create_connection_pool, close_connection_pool, start_healthcheck_thread -from simple_logger_handler import setup_logger, LOG_LEVEL -import uuid -from hashlib import sha256 -import uvicorn -from contextlib import asynccontextmanager +from starlette.exceptions import HTTPException as StarletteHTTPException + +from db_module import close_connection_pool, create_connection_pool, get_db, start_healthcheck_thread from metrics_server import REQUEST_COUNTER -import asyncio +from secret_manager import cleanup_secret_files, return_credentials +from secret_manager.fernet_encryption import encrypt_token +from simple_logger_handler import LOG_LEVEL, setup_logger from uvicorn_logger_config import LOGGING_CONFIG -import httpx -import os +from validator import is_valid_platform, is_valid_token, verify_api_key logger = setup_logger(__name__) api_key_header = APIKeyHeader(name="X-API-Key") @@ -168,7 +170,7 @@ def register_token( cursor = db.cursor() cursor.execute( "SELECT * FROM device_tokens WHERE user_id=%s AND hashed_token=%s", - (user_id,hashed_token)) + (user_id,hashed_token)) existing = cursor.fetchone() logger.debug(f"[FastAPI] Existing token fetched: {existing}") @@ -178,8 +180,8 @@ def register_token( UPDATE device_tokens SET platform=%s, app_ver=%s, locale=%s, topics=%s, last_seen_at=NOW() WHERE user_id=%s AND hashed_token=%s - """, (request_data.platform, - request_data.app_ver, + """,(request_data.platform, + request_data.app_ver, request_data.locale, request_data.topics, user_id, @@ -193,7 +195,7 @@ def register_token( (token_id, user_id, platform, token, hashed_token, status, app_ver, locale, topics, created_at) VALUES (%s,%s,%s,%s,%s,%s,%s,%s,%s,NOW()) """, (token_id, - user_id, + user_id, request_data.platform, secure_token, hashed_token, @@ -207,7 +209,7 @@ def register_token( logger.info(f"[FastAPI] Success: Registering token for user_id={user_id}, platform={request_data.platform}") except Exception as e: logger.exception(f"[FastAPI] Failed to register token for user_id={user_id}: {e}") - raise HTTPException(status_code=500, detail=str(e)) + raise HTTPException(status_code=500, detail=str(e)) from e return {"status":"registered"} @@ -230,7 +232,7 @@ def unregister_token( """, ('expired', hashed_token)) except Exception as e: logger.exception(f"[FastAPI] Failed to unregister token for user_id={user_id}: {e}") - raise HTTPException(status_code=500, detail=str(e)) + raise HTTPException(status_code=500, detail=str(e)) from e logger.info(f"[FastAPI] Success: Unregistering token for user_id={user_id}, platform={request_data.platform}") return {"status":"unregistered"} @@ -248,10 +250,10 @@ async def pull_notifications( data = PullResponse.model_validate(resp.json()) except httpx.HTTPStatusError as e: logger.error(f"[FastAPI] Upstream returned {e.response.status_code} for user_id={user_id}") - raise HTTPException(status_code=502, detail="Backend-API-Internal unavailable") + raise HTTPException(status_code=502, detail="Backend-API-Internal unavailable") from e except ValueError as e: logger.error(f"[FastAPI] Backend-API-Internal call failed with ValueError for user_id={user_id}: {e!r}") - raise HTTPException(status_code=502, detail="Backend-API-Internal unavailable") + raise HTTPException(status_code=502, detail="Backend-API-Internal unavailable") from e logger.info(f"[FastAPI] Returning {len(data.messages)} message(s) for user_id={user_id}, has_more={data.has_more}") return data 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/validator.py b/src/validator.py index 6cfa5f9..9949b50 100644 --- a/src/validator.py +++ b/src/validator.py @@ -1,5 +1,7 @@ -from argon2 import PasswordHasher import re + +from argon2 import PasswordHasher + from simple_logger_handler import setup_logger logger = setup_logger(__name__)