Skip to main content

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 like speedhive-tools-ui.
  • Track-record curation (speedhive.workflows.track_records) — parses announcer text for lap-record callouts (regex by default, optional Gemini LLM extraction via speedhive.llm, chosen per-org through speedhive.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 a main(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


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

speedhive_tools-0.9.17.tar.gz (129.4 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

speedhive_tools-0.9.17-py3-none-any.whl (228.8 kB view details)

Uploaded Python 3

File details

Details for the file speedhive_tools-0.9.17.tar.gz.

File metadata

  • Download URL: speedhive_tools-0.9.17.tar.gz
  • Upload date:
  • Size: 129.4 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.2.0 CPython/3.11.15

File hashes

Hashes for speedhive_tools-0.9.17.tar.gz
Algorithm Hash digest
SHA256 1318927ecfca8fc57469afe2311a89c1e205e271f0502733c2ef302200d86432
MD5 4e0dfc327dfdc11778e8d49177b77e03
BLAKE2b-256 ca701cee2c05ab1560f31e40dfbb1b2e0f5a8dbe4871e8e8a7f5ef6364e9ebdb

See more details on using hashes here.

File details

Details for the file speedhive_tools-0.9.17-py3-none-any.whl.

File metadata

File hashes

Hashes for speedhive_tools-0.9.17-py3-none-any.whl
Algorithm Hash digest
SHA256 e28a3a366fb07c1f180f670cb63a9e5bc7818c0b246d2a270b8a17a4afed0930
MD5 64505679d977f69f5ee1177297629b22
BLAKE2b-256 53e1b905adc80e863ce791f7838391db7c0fbbb548af2408ef944ec526a0f978

See more details on using hashes here.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page