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.19.tar.gz (131.0 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.19-py3-none-any.whl (229.6 kB view details)

Uploaded Python 3

File details

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

File metadata

  • Download URL: speedhive_tools-0.9.19.tar.gz
  • Upload date:
  • Size: 131.0 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.19.tar.gz
Algorithm Hash digest
SHA256 437514b0961f6f9315cb3de4300f0dc0a99fe2c05cd1df5aba00374ef4158616
MD5 c3c77f869fcce5e43e91a386a531cd21
BLAKE2b-256 621d2a0d859fc5ee54abd4cf06dd4c39b5b3a73c1578916a93fec02428c4078b

See more details on using hashes here.

File details

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

File metadata

File hashes

Hashes for speedhive_tools-0.9.19-py3-none-any.whl
Algorithm Hash digest
SHA256 41c4531d2d44b619da42d86c917f04e0c78dcf822677070221dfa4a27b2ae24d
MD5 eb671812b3b659d64cb368afa51ccedc
BLAKE2b-256 128b919685310a542d0e0064210e544c4ff23523a3388f2f96e18f99f0f74b64

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