Client API¶
PyroxClient¶
Create a client:
from pyrox import PyroxClient
client = PyroxClient()
list_races(season: int | None = None, force_refresh: bool = False)¶
Return a DataFrame of available races. Filter by season when provided.
list_seasons(force_refresh: bool = False)¶
Return sorted season values available in the manifest.
list_locations(season: int | None = None, force_refresh: bool = False)¶
Return sorted location values available in the manifest. When season is
provided, results are limited to that season. Returns an empty list if no
locations match.
list_years(...)¶
list_years(
season: int | None = None,
location: str | None = None,
force_refresh: bool = False,
) -> list[int]
Return sorted calendar years available in the manifest. Location matching is case-insensitive. Returns an empty list if no years match.
get_race(...)¶
get_race(
season: int,
location: str,
year: int | None = None,
gender: str | None = None,
division: str | None = None,
total_time: float | tuple[float | None, float | None] | None = None,
use_cache: bool = True,
) -> pd.DataFrame
Key behaviors:
- Applies server-side gender and division filters when available.
- Converts time columns into minutes.
- Supports strict time windows using total_time.
Division values seen in the dataset include open, pro, and pro_doubles.
If the manifest lookup fails, RaceNotFound includes discovery context such as
available seasons, available years, and close location suggestions:
from pyrox.errors import RaceNotFound
try:
client.get_race(season=8, location="londn")
except RaceNotFound as exc:
print(exc.suggestions)
get_athlete_in_race(...)¶
get_athlete_in_race(
season: int,
location: str,
athlete_name: str,
year: int | None = None,
gender: str | None = None,
division: str | None = None,
use_cache: bool = True,
) -> pd.DataFrame
Case-insensitive search on the name column. Raises AthleteNotFound if no match.
get_season(...)¶
get_season(
season: int,
locations: Iterable[str] | None = None,
gender: str | None = None,
division: str | None = None,
max_workers: int = 8,
use_cache: bool = True,
) -> pd.DataFrame
Parallelized race fetching with a configurable worker pool.
clear_cache(pattern: str = "*")¶
Clear cached items matching a glob pattern.
cache_info() -> dict¶
Return cache statistics and keys.
Reporting Service Note (Repository-Only)¶
This repository also ships a FastAPI reporting service (pyrox_api_service/) that
is separate from the published pyrox-client wheel.
The optional pyrox-client[reporting] extra installs the DuckDB Python library
needed by ReportingClient, but it does not bundle a DuckDB database file. Use
ReportingClient(database="/path/to/pyrox_duckdb") when you have a local
generated database artifact.
For athlete profile endpoints:
GET /api/athletes/profile?name=<name>GET /api/athletes/{athlete_id}/profile
personal_bests entries may include an optional percentile field (float in
[0, 1]) per segment key (overall, runplusroxzone, skierg, sledpush,
sledpull, burpeebroadjump, rowerg, farmerscarry, sandbaglunges,
wallballs).
average_times entries may also include optional percentile with the same
range and segment keys.
Percentile direction matches report split percentiles:
- 1.0 means faster than 100% of the cohort.
- 0.0 means slower than everyone in the cohort.
- If percentile cannot be computed for a segment, the key is omitted for that
segment without failing the endpoint.
Profile percentiles are computed against historical results in the same division and gender.