Fix NaN serialization in cache endpoints
This commit is contained in:
parent
12b731ecf9
commit
c9f53d0ece
18
api/main.py
18
api/main.py
|
|
@ -1,3 +1,4 @@
|
||||||
|
import math
|
||||||
import os
|
import os
|
||||||
import hmac
|
import hmac
|
||||||
import hashlib
|
import hashlib
|
||||||
|
|
@ -55,6 +56,14 @@ def verify_jwt(authorization: Optional[str] = Header(None)):
|
||||||
raise HTTPException(status_code=401, detail="Invalid token")
|
raise HTTPException(status_code=401, detail="Invalid token")
|
||||||
|
|
||||||
|
|
||||||
|
def _clean(row: dict) -> dict:
|
||||||
|
"""Convert NaN/Inf floats → None so FastAPI can serialize the row to JSON."""
|
||||||
|
return {
|
||||||
|
k: (None if isinstance(v, float) and not math.isfinite(v) else v)
|
||||||
|
for k, v in row.items()
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
def verify_admin(authorization: Optional[str] = Header(None)):
|
def verify_admin(authorization: Optional[str] = Header(None)):
|
||||||
if not authorization or authorization != f"Bearer {ADMIN_KEY}":
|
if not authorization or authorization != f"Bearer {ADMIN_KEY}":
|
||||||
raise HTTPException(status_code=401, detail="Unauthorized")
|
raise HTTPException(status_code=401, detail="Unauthorized")
|
||||||
|
|
@ -117,7 +126,7 @@ def get_analyst_cache(payload=Depends(verify_jwt), db=Depends(get_db)):
|
||||||
cur = db.cursor(cursor_factory=psycopg2.extras.RealDictCursor)
|
cur = db.cursor(cursor_factory=psycopg2.extras.RealDictCursor)
|
||||||
table = "beta_analyst_cache" if payload.get("channel") == "beta" else "analyst_cache"
|
table = "beta_analyst_cache" if payload.get("channel") == "beta" else "analyst_cache"
|
||||||
cur.execute(f"SELECT * FROM {table}")
|
cur.execute(f"SELECT * FROM {table}")
|
||||||
return {"data": cur.fetchall()}
|
return {"data": [_clean(dict(r)) for r in cur.fetchall()]}
|
||||||
|
|
||||||
|
|
||||||
@app.get("/cache/fundamentals")
|
@app.get("/cache/fundamentals")
|
||||||
|
|
@ -125,14 +134,15 @@ def get_fundamentals_cache(payload=Depends(verify_jwt), db=Depends(get_db)):
|
||||||
cur = db.cursor(cursor_factory=psycopg2.extras.RealDictCursor)
|
cur = db.cursor(cursor_factory=psycopg2.extras.RealDictCursor)
|
||||||
table = "beta_fundamentals_cache" if payload.get("channel") == "beta" else "fundamentals_cache"
|
table = "beta_fundamentals_cache" if payload.get("channel") == "beta" else "fundamentals_cache"
|
||||||
cur.execute(f"SELECT * FROM {table}")
|
cur.execute(f"SELECT * FROM {table}")
|
||||||
return {"data": cur.fetchall()}
|
return {"data": [_clean(dict(r)) for r in cur.fetchall()]}
|
||||||
|
|
||||||
|
|
||||||
@app.get("/cache/sector")
|
@app.get("/cache/sector")
|
||||||
def get_sector_stats(payload=Depends(verify_jwt), db=Depends(get_db)):
|
def get_sector_stats(payload=Depends(verify_jwt), db=Depends(get_db)):
|
||||||
cur = db.cursor(cursor_factory=psycopg2.extras.RealDictCursor)
|
cur = db.cursor(cursor_factory=psycopg2.extras.RealDictCursor)
|
||||||
cur.execute("SELECT * FROM sector_stats ORDER BY sector")
|
table = "beta_sector_stats" if payload.get("channel") == "beta" else "sector_stats"
|
||||||
return {"data": cur.fetchall()}
|
cur.execute(f"SELECT * FROM {table} ORDER BY sector")
|
||||||
|
return {"data": [_clean(dict(r)) for r in cur.fetchall()]}
|
||||||
|
|
||||||
|
|
||||||
@app.get("/update")
|
@app.get("/update")
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue