Skip to main content

Multi-provider driving directions and real-time traffic collector with a Typer CLI and SQL persistence.

Project description

gotime

PyPI version Python versions Documentation Status License: MIT

gotime is a multi-provider driving-directions library and Typer-powered command-line tool. It gives you a single, typed API on top of the major commercial routing services — Google Maps, Bing Maps, TomTom, HERE, MapQuest, Mapbox and Azure Maps — along with a SQLAlchemy persistence layer that stores trips and raw API responses for later analysis.

Installation

pip install gotime          # library + CLI
pip install "gotime[postgres]"  # add psycopg2 for Postgres storage

You also need API keys for any provider you plan to use; see docs/pricing.md for signup links and free-tier guidance.

Quickstart

export GOOGLE_MAPS_API_KEY=your-key
gotime providers list
gotime providers verify                         # probe every configured key
gotime query \
    --origin 42.3554,-71.0654 \
    --destination 42.3467,-71.0972 \
    --provider google --provider tomtom

The coordinates above are public Boston landmarks (Boston Common and Fenway Park), included as a recognizable short commute for demo and testing purposes.

gotime providers verify (aliased as gotime verify-keys) issues a tiny directions call per provider and classifies the response as ok, missing, invalid, rate_limited, unreachable or error. Add --provider google to narrow the probe, --json for CI consumption, and --timeout 5 to shorten the per-call deadline.

Or drop a .env file next to where you invoke the CLI:

cp .env.example .env
$EDITOR .env   # fill in the keys you have
gotime query --origin 42.36,-71.07 --destination 42.35,-71.10

Library usage

from gotime import Waypoint, query_providers
from gotime.config import load_settings

settings = load_settings()
results = query_providers(
    origin=Waypoint(42.3554, -71.0654, label="home"),
    destination=Waypoint(42.3467, -71.0972, label="work"),
    providers=["google", "tomtom"],
    settings=settings,
)

for name, result in results.items():
    if hasattr(result, "duration_minutes"):
        print(name, f"{result.duration_minutes:.1f} min", f"{result.distance_miles:.1f} mi")
    else:
        print(name, "error:", result)

Features

  • Seven Tier-1 providers with a normalized TripResult contract. Providers that don't support a field (e.g. duration-in-traffic on Mapbox's base driving profile) return None so you never have to guess.
  • Typer CLI with rich table / JSON output and no hidden global state.
  • SQLAlchemy 2.x persistence (users, providers, locations, trips, trip_api_logs) plus Alembic migrations. Swap SQLite ↔ Postgres with a URL.
  • Docker-first tests with ≥ 90 % line coverage enforced in CI.
  • Typed, Black-formatted, Ruff-linted Python 3.13 code (3.14 migration tracked in docs/roadmap.md).

Repository layout

gotime/
├── src/gotime/          # library source (see docs/architecture.md)
├── tests/               # pytest-cov suite (mocks HTTP via respx)
├── docs/                # Sphinx site published to Read the Docs
├── alembic/             # DB migrations
├── Dockerfile           # slim image for CI integration tests
├── docker-compose.test.yml
├── pyproject.toml       # hatchling build, PEP 621 metadata
└── .github/workflows/   # CI, integration, publish, docs

Development

uv venv --python 3.13
source .venv/bin/activate
uv pip install --editable ".[dev]"

black --check src tests
ruff check src tests
pytest               # pytest.ini_options sets --cov-fail-under=90

Or run everything in Docker:

docker compose --file docker-compose.test.yml up --build --abort-on-container-exit

Running CI locally

Three tiers, ordered by fidelity. Pick the one that matches what you're trying to verify.

1. Fast loop — the commands above, annotated with the .github/workflows/ step they mirror:

black --check src tests                        # ci.yml -> lint
ruff check src tests                           # ci.yml -> lint
mypy                                           # ci.yml -> types (non-blocking)
sphinx-build -W -b html docs docs/_build/html  # docs.yml
pytest                                         # ci.yml -> test (sqlite leg)

The new changelog gate in ci.yml can be previewed locally against the current PR's base branch:

# Mirrors ci.yml -> changelog
git diff --name-only origin/main... \
  | grep --extended-regexp '^(src/gotime/|alembic/|pyproject\.toml$)' \
  && git diff --name-only origin/main... | grep --fixed-strings 'CHANGELOG.md' \
  || echo "Add a CHANGELOG entry before pushing, or apply the 'skip-changelog' label."

2. Docker fast-path — covers the Postgres leg that ci.yml's matrix runs:

docker compose --file docker-compose.test.yml up --build --abort-on-container-exit

3. Full-fidelity via act — runs the raw .github/workflows/*.yml files:

curl --silent --show-error --location \
    https://raw.githubusercontent.com/nektos/act/master/install.sh | bash

./bin/act --list
./bin/act --workflows .github/workflows/ci.yml
./bin/act --workflows .github/workflows/docs.yml

Caveats:

  • act needs Docker (≈500 MB runner image).
  • services: containers usually need --container-options "--network host".
  • Integration secrets (GOOGLE_MAPS_API_KEY, …) are not auto-present — supply via --secret-file .secrets or let integration.yml skip (it already skipifs on missing keys).

Release process

gotime uses calendar-anchored semantic versioning (YYYY.MINOR.MICRO) derived automatically from git tags via hatch-vcs. Version strings are never hand-edited.

The full runbook lives in docs/release.md. In short:

  1. Run scripts/prepare-release.sh 2026.MINOR.MICRO from main. It opens a PR whose only change is moving ## [Unreleased] in CHANGELOG.md to the new release section.
  2. Merge the PR.
  3. git pull --ff-only origin main, then git tag --annotate --sign 2026.MINOR.MICRO and git push origin 2026.MINOR.MICRO.
  4. Approve the pypi GitHub Environment deployment. Everything else (build, provenance attestation, PyPI publish via OIDC, GitHub Release, install smoke-test, Read the Docs rebuild) is automated.

License

MIT — see LICENSE.

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

gotime-2026.1.0.tar.gz (40.5 kB view details)

Uploaded Source

Built Distribution

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

gotime-2026.1.0-py3-none-any.whl (30.5 kB view details)

Uploaded Python 3

File details

Details for the file gotime-2026.1.0.tar.gz.

File metadata

  • Download URL: gotime-2026.1.0.tar.gz
  • Upload date:
  • Size: 40.5 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/6.1.0 CPython/3.13.12

File hashes

Hashes for gotime-2026.1.0.tar.gz
Algorithm Hash digest
SHA256 c882241bc059a068394a8f89dd9777b9d5cd02787f6bc2ea3280e0e49618d7b7
MD5 602caafccf7ceecf89b631a23a9d71a6
BLAKE2b-256 66fbd6d67921ccaffae4dee4c9b923a5f2783594c9dd56a6c73ee54c8466a989

See more details on using hashes here.

Provenance

The following attestation bundles were made for gotime-2026.1.0.tar.gz:

Publisher: release.yml on mgeiger/gotime

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

File details

Details for the file gotime-2026.1.0-py3-none-any.whl.

File metadata

  • Download URL: gotime-2026.1.0-py3-none-any.whl
  • Upload date:
  • Size: 30.5 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/6.1.0 CPython/3.13.12

File hashes

Hashes for gotime-2026.1.0-py3-none-any.whl
Algorithm Hash digest
SHA256 d73d0202e9c43db2309c14d3656e4c4f5e68ff6c98f86ff55f38aa8ee0862160
MD5 41e59c0c78af4567e4b5413f56f996b6
BLAKE2b-256 7da93ac86f9370933765789da24f037a5e97b7fe35008d35e585587c40a86374

See more details on using hashes here.

Provenance

The following attestation bundles were made for gotime-2026.1.0-py3-none-any.whl:

Publisher: release.yml on mgeiger/gotime

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

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