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.

Metadata

Release files for gotime 2026.1.0

For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.

Source distribution (sdist)

Source distribution for gotime 2026.1.0
File Size Uploaded Provenance Actions
gotime-2026.1.0.tar.gz 40.5 kB With provenance Details for gotime-2026.1.0.tar.gz

Built distribution (wheel)

Table of built distributions (wheels) for gotime 2026.1.0
File Interpreter ABI Platform Actions
gotime-2026.1.0-py3-none-any.whl Python 3 none any Details for gotime-2026.1.0-py3-none-any.whl

Total release size: 71.0 kB

Release files / gotime-2026.1.0.tar.gz

Download URL gotime-2026.1.0.tar.gz
Size 40.5 kB
Tags Source
SHA-256 checksum
How to use checksums
c882241bc059a068394a8f89dd9777b9d5cd02787f6bc2ea3280e0e49618d7b7
BLAKE2b-256 checksum
How to use checksums
66fbd6d67921ccaffae4dee4c9b923a5f2783594c9dd56a6c73ee54c8466a989
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/6.1.0 CPython/3.13.12

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Apr 22, 2026.

Transparency log

Release files / gotime-2026.1.0-py3-none-any.whl

Download URL gotime-2026.1.0-py3-none-any.whl
Size 30.5 kB
Tags Python 3
SHA-256 checksum
How to use checksums
d73d0202e9c43db2309c14d3656e4c4f5e68ff6c98f86ff55f38aa8ee0862160
BLAKE2b-256 checksum
How to use checksums
7da93ac86f9370933765789da24f037a5e97b7fe35008d35e585587c40a86374
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/6.1.0 CPython/3.13.12

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Apr 22, 2026.

Transparency log

Security for gotime 2026.1.0

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

Full provenance

Both files in this release have been uploaded with provenance metadata.

Select from 2 files

Attestation for gotime-2026.1.0.tar.gz

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Apr 22, 2026.

Transparency log

A note on package security

PyPI is a repository for distributing packages, not a service for auditing them. While third-party security researchers and our staff do their best to detect and remove malicious packages, PyPI cannot guarantee the quality, security or suitability of any given package.

To learn more about protecting yourself from malicious actors, visit our package security documentation.

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page