Skip to main content

pygtfsie

A GTFS static and GTFS-Realtime engine: ingest a feed archive into SQLite, resolve every stop event to an absolute instant, and answer departure queries.

This is the engine half of a pair. The Home Assistant integration built on it lives in ha-gtfsie. Nothing here imports Home Assistant, and a CI job fails the build if anything ever does.

Why it is a separate package

The great majority of the logic in a transit-departure integration is not integration logic. It is date arithmetic, CSV tolerance, protobuf decoding and SQL -- none of which needs an event loop, a config entry or a pinned Home Assistant version to be exercised.

Splitting the engine out means its tests run on bare pytest across every supported Python in well under a second, so the parts most likely to be wrong are also the cheapest to check. The integration keeps the parts that genuinely need Home Assistant: config entries, coordinators, entities and services.

Design rules

Three rules account for most of what this library does differently, and each exists because the alternative has a known, reported failure mode.

Time is resolved at ingest, never at query time. Every (trip, stop time, service date) becomes an absolute UTC epoch integer when the feed is loaded. No SQL statement contains date(), datetime(), strftime() or 'now'. SQLite evaluates those in C against the process timezone in UTC, which no Python-level clock control can reach -- so a suite that fakes the clock still gets real dates from the database, and the disagreement surfaces as departures on the wrong day.

The service day is anchored at local noon minus twelve hours. Not midnight. Local midnight does not exist on spring-forward days in Cairo, Havana, Asunción and around 70 other zone-dates in the current decade, and it happens twice on the corresponding fall-back days. Anchoring there yields a silently shifted instant rather than an error. Noon has never been moved by any jurisdiction.

Nothing reads the current time except the caller. Every query takes a now_utc argument. scripts/time-sweep.sh runs the whole suite at six instants in six timezones and fails if the results differ, which is what keeps the rule from decaying.

Layout

pygtfsie/
  const.py          GTFS enumerations, route type names and icons
  exceptions.py     one hierarchy, so a consumer can catch the library
  helpers/
    tz.py           the only place timezone reasoning exists
    text.py         the only place str() is called on a raw feed value
    geo.py          bounding boxes and great-circle distance
    logthrottle.py  rate limiting for repeated messages

Later phases add store/ (schema, connections, queries), ingest/ (download, CSV, calendar expansion, materialisation) and realtime/ (protobuf and SIRI decoding, trip matching).

Install

pip install pygtfsie              # engine only
pip install pygtfsie[realtime]    # adds gtfs-realtime-bindings and protobuf

Realtime support is an extra because a consumer that only needs the static timetable should not pull in protobuf.

Development

python3 -m venv .venv
./.venv/bin/pip install -e ".[dev]"
./.venv/bin/python -m pytest -q

Before pushing anything that touches date handling:

./.venv/bin/python -m ruff check pygtfsie tests
./.venv/bin/python -m ruff format --check pygtfsie tests
scripts/time-sweep.sh              # needs libfaketime

Branching

master is the release branch and is what tags are cut from. Work happens on topic branches merged back into master.

Pipeline

The GitLab pipeline has three stages:

  • lint -- ruff check and ruff format --check, plus a grep gate that fails if any module under pygtfsie/ imports Home Assistant.
  • test -- pytest on Python 3.11, 3.12, 3.13 and 3.14.
  • publish -- builds and uploads to PyPI on a vMAJOR.MINOR.PATCH tag using PyPI Trusted Publishing (OIDC), so no API token is stored anywhere. The job is when: manual: tagging never publishes on its own.

Licence

Mozilla Public License 2.0. See LICENSE.

Metadata

Release files for pygtfsie 0.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 pygtfsie 0.1.0
File Size Uploaded Provenance Actions
pygtfsie-0.1.0.tar.gz 106.8 kB Without provenance Details for pygtfsie-0.1.0.tar.gz

Built distribution (wheel)

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

Total release size: 177.7 kB

Release files / pygtfsie-0.1.0.tar.gz

Download URL pygtfsie-0.1.0.tar.gz
Size 106.8 kB
Tags Source
SHA-256 checksum
How to use checksums
9dcb7a2747892b2e09d98a9097a461f808edb2b78359822f7c00896fce3abc1b
BLAKE2b-256 checksum
How to use checksums
bb04ac40e82f3e6624b805a343b1da717799f4399743fb00a541bc0c40584e53
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/7.0.0 CPython/3.13.15

Release files / pygtfsie-0.1.0-py3-none-any.whl

Download URL pygtfsie-0.1.0-py3-none-any.whl
Size 70.9 kB
Tags Python 3
SHA-256 checksum
How to use checksums
ca0f9c59b593bb90463f473f1928a56daf82829872139e92ba5a009f5e2f9bc9
BLAKE2b-256 checksum
How to use checksums
5b507907110de7c3a22748ad901f3c0d9d9ed4e9e8ab8ce888001a9375e7f25b
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/7.0.0 CPython/3.13.15

Security for pygtfsie 0.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.

No provenance found

None of the files in this release were uploaded with provenance metadata.

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.

Release history Release notifications | RSS feed

This release

0.1.0 This release

2 release files No provenance

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