Skip to main content

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.

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.

Release history Release notifications | RSS feed

This release

2026.1.0 This release

2 files

0.1.4

2 files

0.1.3

2 files

0.1.2

2 files

0.0.8

2 files

0.0.2

2 files

Supported by

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