Utilities for MyLaps Event Results API.
Project description
speedhive-tools
A Python client, SQLite persistence layer, and CLI for scraping and analyzing MyLaps Speedhive racing results.
It's the core engine behind the speedhive-tools-ui dashboard (vendored there as a git submodule), but works standalone as a library or command-line tool with no web UI required.
What it does
- Speedhive HTTP client (
speedhive.wrapper.SpeedhiveClient) — a hand-written, ergonomic wrapper around an OpenAPI-generated low-level client (speedhive/generated/) for organizations, events, sessions, results, laps, lap charts, announcements, and championships. - SQLite cache (
speedhive.storage.SpeedhiveStorage) — local persistence for everything the client fetches, with per-entity save/read methods and org-scoped pruning. - Org sync workflow (
speedhive.workflows.refresh_org_cache) — incremental or full re-sync of an organization into the cache, with configurable event caps and recent-event backfill. - Per-org settings resolution (
speedhive.settings) — a single, reusable mechanism for "does this org have its own override for X, else fall back to a global default" (Gemini keys, parsing engine, min-laps), backed by<SPEEDHIVE_DATA_DIR>/orgs/<org_id>/settings.json. Shared by the CLI and any host application; has no notion of email/notification settings, since those are policy owned entirely by a host app likespeedhive-tools-ui. - Track-record curation (
speedhive.workflows.track_records) — parses announcer text for lap-record callouts (regex by default, optional Gemini LLM extraction viaspeedhive.llm, chosen per-org throughspeedhive.settings), normalizes classification names against an alias map, and maintains candidate/curated/rejected review queues per organization. Every manual edit to a curated record appends to that record's own edit history (what changed, when) rather than overwriting it silently. - Analyzers (
speedhive.analyzers) — driver consistency rankings (mean/stdev/coefficient-of-variation, with optional IQR outlier filtering and fuzzy name clustering), per-driver lap extraction, and average-lap-by-class-and-year pace charts. - NDJSON exporters/importers (
speedhive.exporters,speedhive.workflows.import_sqlite_dump) — portable dump/restore of an org's cache, lap records, track records, and curated records as newline-delimited JSON, individually or as a full ZIP-able dump. - Unified CLI (
speedhive) — one entry point for all of the above; new exporter/workflow/analyzer modules that expose amain(argv)are auto-registered as subcommands (speedhive.cli.discovery).
Installation
pip install speedhive-tools
For development:
git clone https://github.com/ncrosty58/speedhive-tools.git
cd speedhive-tools
python -m venv .venv && source .venv/bin/activate
pip install -e ".[dev]"
Data & configuration
By default, the CLI and storage layer keep their SQLite cache and per-organization settings under a ./data directory relative to the working directory (already gitignored). For anything unattended (cron, a systemd timer, a script), set SPEEDHIVE_DATA_DIR to a fixed absolute path explicitly rather than relying on that default — a relative path resolves differently depending on where the process happens to be invoked from.
| Variable | Description | Default |
|---|---|---|
SPEEDHIVE_DATA_DIR |
Root directory for the cache and org settings. | ./data |
SPEEDHIVE_DB_PATH |
Explicit path to the SQLite cache file. | <SPEEDHIVE_DATA_DIR>/speedhive.db |
Per-organization behavior (parser engine, minimum laps for stats, Gemini key/model overrides) is configured in data/orgs/<org_id>/settings.json, read/written through speedhive.settings. Run speedhive configure --org <id> for an interactive setup wizard covering exactly those settings, or copy settings.json.example by hand. GEMINI_API_KEY/GEMINI_MODEL can be set globally (bare env var) or per-org (overrides block in settings.json, or a GEMINI_API_KEY_<org_id>-style env var), with the org-specific value taking precedence.
Notification/email settings (Resend keys, recipient addresses) are not configured here — speedhive-tools has no code that sends email. That's entirely owned by speedhive-tools-ui; the CLI's configure wizard deliberately doesn't ask about them.
CLI reference
Run speedhive <command> --help for full options on any of these:
# Sync an organization's cache (full or incremental)
speedhive sync-org --org 30476 --mode full
speedhive sync-org --org 30476 --mode incremental --recent-backfill-events 5
# Driver consistency rankings
speedhive report-consistency --org 30476 --min-laps 15 --ignore-outliers
# Fuzzy-match a driver and extract their laps
speedhive extract-driver-laps --org 30476 --driver "Jane Doe"
# Track-record curation: sync (if stale) then scan for new candidates
speedhive refresh-track-records --org 30476
# ...or scan the existing cache only, without contacting Speedhive
speedhive scan-track-records --org 30476
# Curated-record NDJSON import/export
speedhive export-curated-track-records --org 30476 --output curated.ndjson
speedhive import-curated-track-records --org 30476 --input curated.ndjson --mode merge
# Offline dumps
speedhive export-db-dump --org 30476 --output-dir ./output
speedhive import-dump --org 30476 --dump-dir ./output
speedhive export-dump --org 30476 --output ./output # scrape straight to NDJSON, no DB required
speedhive export-lap-records --org 30476 --max-events 25
# Interactive per-org settings wizard (Gemini/parsing/min-laps only)
speedhive configure --org 30476
Both scan-track-records and refresh-track-records automatically pick up the org's parsing.engine setting (regex vs. Gemini) via speedhive.settings.get_bulk_parser_for_org — no separate flag needed.
Python API
Uncached scraping
from speedhive.wrapper import SpeedhiveClient
client = SpeedhiveClient.create()
org = client.get_organization(30476)
events = client.iter_events(30476) # generator over all events
sessions = client.get_sessions(event_id=12345)
laps = client.get_laps(session_id=67890)
Cached storage + sync
from speedhive.storage import SpeedhiveStorage
from speedhive.workflows.refresh_org_cache import refresh_org_cache
storage = SpeedhiveStorage("data/speedhive.db")
refresh_org_cache(client=client, storage=storage, org_id=30476, mode="incremental")
records = storage.get_track_records(30476, classification="Karting")
Settings resolution
from speedhive.settings import get_org_env_var, set_org_env_var, get_parsing_engine
set_org_env_var("GEMINI_API_KEY", 30476, "AIza...")
get_org_env_var("GEMINI_API_KEY", 30476) # org override, else the bare GEMINI_API_KEY fallback
get_parsing_engine(30476) # "regex" or "llm"
More end-to-end scripts live in examples/ (organizations, events, sessions, lap charts, announcements, streaming laps, track records).
Development
pip install -e ".[dev]"
pytest # full test suite (tests/)
ruff check src/ # lint
speedhive/generated/ is an OpenAPI-generated low-level client and is not meant to be hand-edited.
Project details
Release history Release notifications | RSS feed
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file speedhive_tools-0.9.16.tar.gz.
File metadata
- Download URL: speedhive_tools-0.9.16.tar.gz
- Upload date:
- Size: 128.4 kB
- Tags: Source
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.2.0 CPython/3.11.15
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
0058e95746a9622950437cf862a5a7d3f3ecd5e3908dca3eb86cea0b6d0e4a97
|
|
| MD5 |
4c89a9e0376b45abc08234a23f2aca70
|
|
| BLAKE2b-256 |
9580c99fde16bf95b3f98bf4b6a3dc4cec1f52474d30025f2cadd1a0ac976225
|
File details
Details for the file speedhive_tools-0.9.16-py3-none-any.whl.
File metadata
- Download URL: speedhive_tools-0.9.16-py3-none-any.whl
- Upload date:
- Size: 228.3 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.2.0 CPython/3.11.15
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
408f87de7a646b9856b60532ad878b1528f8d4f7088e1fcdf56bfa4ce869eeef
|
|
| MD5 |
2657f23c2906dfaec7ab148f05ff5ee4
|
|
| BLAKE2b-256 |
2ce79c509ebe83ee45d06175ed4896d7b989e480d269f5a7a72e063a54e2e000
|