refactor: address architect review findings (6 items)

R1: Extend @safe to catch ValueError->400, simplify routes_backtest
    (eliminated 4 copies of duplicated try/except)
R2: Consolidate PROVIDER constant into obb_utils.py (single source)
R3: Add days_ago() helper to obb_utils.py, replace 8+ duplications
R4: Extract Reddit/ApeWisdom into reddit_service.py from finnhub_service
R5: Fix missing top-level import asyncio in finnhub_service
R6: (deferred - sentiment logic extraction is a larger change)

All 561 tests passing.
This commit is contained in:
Yaojia Wang
2026-03-19 23:15:00 +01:00
parent 37c46e76ae
commit 0f7341b158
12 changed files with 184 additions and 204 deletions

View File

@@ -23,13 +23,19 @@ def validate_symbol(symbol: str) -> str:
def safe(fn: Callable[P, Awaitable[R]]) -> Callable[P, Awaitable[R]]:
"""Decorator to catch upstream errors and return 502."""
"""Decorator to catch upstream errors and return 502.
ValueError is caught separately and returned as 400 (bad request).
All other non-HTTP exceptions become 502 (upstream error).
"""
@functools.wraps(fn)
async def wrapper(*args: P.args, **kwargs: P.kwargs) -> R:
try:
return await fn(*args, **kwargs)
except HTTPException:
raise
except ValueError as exc:
raise HTTPException(status_code=400, detail=str(exc))
except Exception:
logger.exception("Upstream data error")
raise HTTPException(