Releases: NerdySoftPaw/python-openpublictransport
Release list
v0.2.0 — typed exceptions on API failures
Breaking change
search_stops() returning [] and fetch_departures() returning None now mean "no data" and nothing else. Every failure raises.
Previously each provider logged a non-200 response and handed back an empty result, so a caller could not tell "the search found nothing" apart from "the provider is down" — see NerdySoftPaw/openpublictransport#88.
Migrating
from openpublictransport import ApiError, AuthenticationError, OpenPublicTransportError
try:
stops = await provider.search_stops(term)
except AuthenticationError:
... # the key was rejected — prompt for credentials
except ApiError as err:
... # err.status holds the HTTP status
except OpenPublicTransportError:
... # timeout, unreachable host, or an unusable payload
if not stops:
... # genuinely no matchesException hierarchy
All under OpenPublicTransportError:
| Class | Raised for |
|---|---|
ApiError |
any non-2xx; carries .status and a truncated .body |
AuthenticationError |
HTTP 401/403 — now a subclass of ApiError |
ApiConnectionError |
host unreachable |
ApiTimeoutError |
request timed out |
ApiResponseError |
a 2xx whose payload cannot be used |
AuthenticationError deriving from ApiError means a caller that only cares about "the API failed" catches it too, while one that wants a credential prompt can still single it out.
One HTTP path
BaseProvider._request() replaces all 16 hand-rolled call sites — the seven protocol bases (EFA, FPTF, HAFAS, HAFAS mgate, OTP REST, OTP GraphQL, TRIAS) and the nine standalone providers.
Retry policy: 4xx raises immediately — retrying a rejected key or a dead endpoint only delays the error the user needs to see — while 5xx, timeouts and connection errors keep the existing retry and backoff before raising. The error body travels on the exception, because a provider often explains a rejection only there.
Eight dead raise sites fixed
In otp_base, trias_base, rmv, trafiklab (×2), nta, national_rail and rejseplanen a broad except Exception in the same method swallowed the provider's own AuthenticationError, so HTTP 401 and 403 never reached a caller.
Kept on purpose
- National Rail still falls back to its bundled station snapshot when Overpass is unreachable.
- HVV GTI still treats
ERROR_TEXTas an unmatched search term rather than a failure.
Tests
83 → 101, including a new suite pinning the retry policy and the empty-versus-failed distinction across every protocol family.
Full changelog: v0.1.16...v0.2.0
v0.1.17 — EFA: accept RapidJSON sent with an XML content type
Fixed
-
EFA: accept RapidJSON payloads sent with an XML content type. VGN (Nuremberg) answers
outputFormat=RapidJSONrequests withContent-Type: text/xml;;charset=utf-8. aiohttp's strict content-type check rejected those bodies, so station search failed with "no results found" and departures never loaded. Both EFA request paths (fetch_departures,search_stops) now decode withcontent_type=None; malformed bodies still fall through to the existing error handling. Applies to all 16 EFA providers.Fixes openpublictransport#79
Tests
New tests/test_efa_mimetype.py — the fake response mimics aiohttp and raises unless the strict check is disabled, so it fails without the fix.
v0.1.16
What's Changed
- feat(hvv): add the official Geofox GTI provider (0.1.16) by @NerdySoftPaw in #16
Full Changelog: v0.1.15...v0.1.16
v0.1.15
What's Changed
- fix(efa): map location.properties.platform to the platform attribute (0.1.15) by @NerdySoftPaw in #15
Full Changelog: v0.1.14...v0.1.15
v0.1.14 — ÖBB fix + 6 new providers (NL, LU, NO, US×2, IE, CH)
Fixes
- ÖBB (Austria): migrate off the permanently-suspended
oebb.macistry.comREST backend to ÖBB's own Scotty HAFAS endpoints (fahrplan.oebb.at). Fixes NerdySoftPaw/openpublictransport#50.
New providers
- NS (Netherlands) — HAFAS Scotty
- mobilitéit.lu (Luxembourg) — HAFAS Scotty
- Entur (Norway) — OTP transmodel GraphQL (keyless)
- BART (San Francisco, USA) — HAFAS mgate
- DART (Des Moines, USA) — HAFAS mgate
- Iarnród Éireann / Irish Rail (Ireland) — HAFAS mgate
- TPG (Geneva, Switzerland) — HAFAS mgate
Internals
- New
HafasBaseProvider(legacy HAFAS "Scotty":ajax-getstop.exe+stboard.exe), tolerant of malformed board XML and 2-/4-digit years. - New
HafasMgateBaseProvider(modernmgate.exeJSON gateway; unsigned, with an optional checksum/mic-mac signing hook). Transport type derived fromprodCtx.catOut. - Endpoints/config sourced from public-transport/transport-apis and validated live.
v0.1.12 — National Rail: fix HTTP 500 (SOAPAction/version) + non-blocking snapshot
Fixes
- National Rail (UK): departures returned HTTP 500 for every station. The SOAPAction was pinned to the request-body ldb version instead of the fixed operation version. Aligned the LDBWS version triple with reference clients: endpoint
ldb12.asmx, body namespace2021-11-01, SOAPAction.../2012-01-13/ldb/GetDepartureBoard. Refs NerdySoftPaw/openpublictransport#39. - Station snapshot is now loaded off the event loop (Home Assistant flagged a blocking file read).
- Non-200 SOAP responses now log the fault reason instead of discarding it.
v0.1.11 — National Rail: snapshot fallback only on Overpass failure
Fixes
- National Rail (UK): the offline station snapshot is now used only when the live Overpass (OSM) query actually fails (unreachable / rate-limited), not when Overpass succeeds and legitimately returns no matches — avoiding potentially out-of-date fallback results. Addresses Copilot review feedback on #8.
v0.1.10 — National Rail: offline station snapshot fallback
Adds
- National Rail (UK): a bundled offline station snapshot (CRS + name, ~2,855 UK stations) used as a fallback for station search when the live Overpass (OSM) API is unreachable, rate-limited, or returns nothing. Overpass remains the source of truth. The snapshot is a point-in-time extract and is not continuously updated.
v0.1.9 — National Rail: fix empty departure board (OpenLDBWS parsing)
Fixes
- National Rail (UK): departures never parsed — every station returned an empty board ("Invalid or empty API response" in Home Assistant) regardless of the API key. Real OpenLDBWS responses use namespace prefixes containing digits (
lt4:,lt5:,lt7:…), which the namespace-stripping step didn't handle, causing anunbound prefixparse error. Refs NerdySoftPaw/openpublictransport#39.
Includes a regression test parsing a realistic multi-namespace response.
v0.1.8 — National Rail: direct CRS code stop search (#39)
Fixes
- National Rail (UK):
search_stops()now accepts a 3-letter CRS code (e.g.WIN,RDG) and looks it up directly against the OSMref:crstag. Previously only station names matched, so searching by code returned nothing. Fixes NerdySoftPaw/openpublictransport#39.
Includes a regression test for the CRS-code path.