Initial extraction from monorepo
This commit is contained in:
commit
f7ef7ca4ab
56 changed files with 6163 additions and 0 deletions
49
fire_planner/fx.py
Normal file
49
fire_planner/fx.py
Normal file
|
|
@ -0,0 +1,49 @@
|
|||
"""Thin shim around `job_hunter.fx` (Frankfurter-backed) so callers
|
||||
inside fire-planner have a single import. Re-exports the public API.
|
||||
|
||||
The job-hunter package isn't a hard dependency — when it isn't on
|
||||
the Python path (e.g. running `fire-planner` outside the monorepo),
|
||||
fall back to a tiny inline implementation that hits Frankfurter
|
||||
directly with no DB caching.
|
||||
"""
|
||||
from __future__ import annotations
|
||||
|
||||
from datetime import date
|
||||
from decimal import Decimal
|
||||
from typing import Any
|
||||
|
||||
import httpx
|
||||
|
||||
FRANKFURTER_URL = "https://api.frankfurter.dev/v1/{date}"
|
||||
|
||||
|
||||
async def fetch_rates(as_of: date, client: httpx.AsyncClient | None = None) -> dict[str, Decimal]:
|
||||
"""Return GBP-base rates for `as_of` — `{currency: rate_to_gbp}`.
|
||||
|
||||
rate_to_gbp[X] = "how much GBP one unit of X is worth", so
|
||||
`gbp_amount = foreign_amount * rate_to_gbp[foreign]`.
|
||||
"""
|
||||
owns = client is None
|
||||
if client is None:
|
||||
client = httpx.AsyncClient(timeout=httpx.Timeout(20.0))
|
||||
try:
|
||||
resp = await client.get(
|
||||
FRANKFURTER_URL.format(date=as_of.isoformat()),
|
||||
params={"base": "GBP"},
|
||||
follow_redirects=True,
|
||||
)
|
||||
resp.raise_for_status()
|
||||
payload: dict[str, Any] = resp.json()
|
||||
finally:
|
||||
if owns:
|
||||
await client.aclose()
|
||||
rates = payload.get("rates") or {}
|
||||
out: dict[str, Decimal] = {"GBP": Decimal("1")}
|
||||
for currency, rate in rates.items():
|
||||
if not rate:
|
||||
continue
|
||||
try:
|
||||
out[currency] = Decimal("1") / Decimal(str(rate))
|
||||
except (ArithmeticError, ValueError):
|
||||
continue
|
||||
return out
|
||||
Loading…
Add table
Add a link
Reference in a new issue