Skip to content

Contributing

bikescore-bna is a database-free library that computes stress and access scores for one city. It stays a pure (inputs, config) → files function; anything stateful built on top of it — multi-city stores, run caching, a web UI — lives outside the library and is not part of this repo.

Dev setup

$ uv sync              # create the venv and install core + dev extras
$ uv run pytest        # fast suite (slow + integration deselected by default)

osmium (the CLI binary) is recommended for fast PBF clipping; a pure-Python pyosmium fallback works but is ~8× slower. See Installation.

Tooling

Tool Command Notes
Tests uv run pytest markers slow, integration, unit; the default addopts deselects slow + integration
Lint uv run ruff check line length 100; ruff is the gate — CI fails on findings
Format uv run ruff format not a gate, but keep the diff clean
Types uv run pyright advisory, not a merge gate

Run the heavier checks explicitly when touching the pipeline:

$ uv run pytest -m slow            # per-stage + end-to-end parity on Aspen
$ uv run pytest -m integration     # needs local cached input data

The one load-bearing rule: import direction

bikescore-bna must never depend on anything built on top of it. The dependency direction is one-way, into the library — any caching layer, run store, or web UI is a consumer of bikescore-bna, never the reverse. tests/test_import_guard.py scans every source and test file statically and fails on any import of such an orchestration layer, so the rule holds even when that layer isn't installed. A violation is an architecture regression, not a style nit.

Corollaries bikescore-bna keeps to:

  • No database, workspace, or web dependencies. Stages take file paths in and write files out; there is no run store to reach for.
  • Rules are data, not code. Stress, attribute, and destination logic lives in decision tables carried by scenarios (see Extensibility), not in Python branches.
  • The stage metadata stays co-located. version and the config-slice look unused here but are the cache-buster and invalidation key a caching layer relies on — leave them with the stage that owns them (an access-audit test keeps this honest).

Correctness bar

Ground truth is the SQL reference (brokenspoke-analyzer). Any behavioural change must be validated — see Validation & parity. When the spec and the SQL reference disagree, the SQL reference wins.