added uvicorn web api
This commit is contained in:
@@ -0,0 +1,68 @@
|
||||
"""Loads the scraped events JSON file and keeps it in memory.
|
||||
|
||||
The file is treated as read-only. Call ``reload()`` to pick up a fresh
|
||||
scrape without restarting the server.
|
||||
"""
|
||||
|
||||
import json
|
||||
import os
|
||||
from datetime import date
|
||||
from pathlib import Path
|
||||
from threading import Lock
|
||||
from typing import List, Optional
|
||||
|
||||
from models import Event
|
||||
|
||||
# Default: the fundi-scraped-output.json sitting in the repo root, one
|
||||
# directory above this file. Override with the DATA_FILE env var.
|
||||
_DEFAULT_DATA_FILE = Path(__file__).resolve().parent.parent / "fundi-scraped-output.json"
|
||||
|
||||
|
||||
class EventStore:
|
||||
def __init__(self, path: Optional[os.PathLike] = None):
|
||||
self.path = Path(path or os.environ.get("DATA_FILE") or _DEFAULT_DATA_FILE)
|
||||
self._lock = Lock()
|
||||
self._events: List[Event] = []
|
||||
self.reload()
|
||||
|
||||
def reload(self) -> int:
|
||||
"""Re-read the JSON file from disk. Returns the number of events loaded."""
|
||||
if not self.path.exists():
|
||||
raise FileNotFoundError(f"Data file not found: {self.path}")
|
||||
with self.path.open(encoding="utf-8") as fh:
|
||||
raw = json.load(fh)
|
||||
events = [Event.model_validate(item) for item in raw]
|
||||
with self._lock:
|
||||
self._events = events
|
||||
return len(events)
|
||||
|
||||
def all(self) -> List[Event]:
|
||||
with self._lock:
|
||||
return list(self._events)
|
||||
|
||||
def get(self, index: int) -> Optional[Event]:
|
||||
with self._lock:
|
||||
if 0 <= index < len(self._events):
|
||||
return self._events[index]
|
||||
return None
|
||||
|
||||
|
||||
def parse_event_date(value: str) -> Optional[date]:
|
||||
"""Parse the scraper's ``dd.mm.yy`` date strings. Returns None if unparseable."""
|
||||
try:
|
||||
day, month, year = (int(part) for part in value.strip().split("."))
|
||||
except (ValueError, AttributeError):
|
||||
return None
|
||||
if year < 100:
|
||||
year += 2000
|
||||
try:
|
||||
return date(year, month, day)
|
||||
except ValueError:
|
||||
return None
|
||||
|
||||
|
||||
def iter_artist_names(event: Event):
|
||||
for group in event.event_artists:
|
||||
for artist in group:
|
||||
if artist.artist_name:
|
||||
yield artist.artist_name
|
||||
Reference in New Issue
Block a user