Remove journey-client

This commit is contained in:
Andras Schmelczer 2026-01-27 22:38:51 +00:00
parent bd0dd34b6e
commit 6b1539a3e7
5 changed files with 63 additions and 1278 deletions

File diff suppressed because it is too large Load diff

View file

@ -4,7 +4,6 @@ tasks:
install:
desc: Install dependencies, generate client, and download data
cmds:
- uv run generate_tfl_client.py
- uv sync
- cd frontend && npm install

View file

@ -1,49 +0,0 @@
#!/usr/bin/env python3
# /// script
# requires-python = ">=3.12"
# dependencies = ["openapi-python-client"]
# ///
"""Regenerate the TfL Journey API client from the OpenAPI specification."""
# Run it with:
# uv run generate_tfl_client.py
import subprocess
from pathlib import Path
OPENAPI_SPEC = Path("Journey.yaml")
OUTPUT_PATH = Path("tfl_journey_client")
def main() -> None:
if not OPENAPI_SPEC.exists():
raise FileNotFoundError(f"OpenAPI spec not found: {OPENAPI_SPEC}")
# Skip if client already exists
if OUTPUT_PATH.exists():
print(f"TfL client already exists at {OUTPUT_PATH}, skipping")
return
# Generate the client
print(f"Generating client from {OPENAPI_SPEC}")
result = subprocess.run(
[
"openapi-python-client",
"generate",
"--path",
str(OPENAPI_SPEC),
"--output-path",
str(OUTPUT_PATH),
],
check=True,
)
if result.returncode == 0:
print(f"Client generated successfully at {OUTPUT_PATH}")
else:
print("Client generation failed")
raise SystemExit(1)
if __name__ == "__main__":
main()

View file

@ -1,35 +1,22 @@
import asyncio
import os
from typing import Literal
import warnings
from collections.abc import Callable
from http import HTTPStatus
from httpx import Timeout
from journey_client import Client
from journey_client.api.journey import (
journey_journey_results_by_path_from_path_to_query_via_query_national_search_query_date_qu as journey_api,
)
from journey_client.models import (
JourneyJourneyResultsByPathFromPathToQueryViaQueryNationalSearchQueryDateQuTimeIs as TimeIs,
)
from journey_client.models import (
JourneyJourneyResultsByPathFromPathToQueryViaQueryNationalSearchQueryDateQuJourneyPreference as JourneyPreference,
)
from journey_client.models import (
JourneyJourneyResultsByPathFromPathToQueryViaQueryNationalSearchQueryDateQuCyclePreference as CyclePreference,
)
from journey_client.models import (
JourneyJourneyResultsByPathFromPathToQueryViaQueryNationalSearchQueryDateQuBikeProficiency as BikeProficiency,
)
from journey_client.types import Unset
import httpx
from .config import MAX_DELAY
from .models import Destination, JourneyResult
from .rate_limiter import RateLimiter
BASE_URL = "https://api.tfl.gov.uk"
async def fetch_journey_for_mode(
client: Client,
client: httpx.AsyncClient,
rate_limiter: RateLimiter,
from_location: str,
to_location: str,
@ -44,65 +31,77 @@ async def fetch_journey_for_mode(
try:
await rate_limiter.acquire()
cycle_preference = {
"quick": CyclePreference.TAKEONTRANSPORT,
"easy": CyclePreference.NONE,
"cycle": CyclePreference.ALLTHEWAY,
journey_preference = {
"quick": "LeastTime",
"easy": "LeastInterchange",
"cycle": None,
}[journey_type]
# options: public-bus,overground,train,tube,coach,dlr,cablecar,tram,river,walking,cycle
cycle_preference = {
"quick": None,
"easy": None,
"cycle": "AllTheWay",
}[journey_type]
# curl -s "https://api.tfl.gov.uk/Journey/Meta/Modes" | jq '.[].modeName'
mode = {
"quick": [
"public-bus",
"bus",
"overground",
"train",
"national-rail",
"international-rail",
"elizabeth-line",
"tube",
"coach",
"dlr",
"cablecar",
"cable-car",
"replacement-bus",
"tram",
"river",
"river-bus",
"walking",
"cycle",
],
"easy": [
"public-bus",
"bus",
"overground",
"train",
"national-rail",
"international-rail",
"elizabeth-line",
"replacement-bus",
"tube",
"coach",
"dlr",
"cablecar",
"cable-car",
"tram",
"river",
"river-bus",
],
"cycle": ["cycle"],
}[journey_type]
response = await journey_api.asyncio_detailed(
from_=from_location,
to=to_location,
client=client,
date=journey_date,
time=journey_time,
national_search=True,
time_is=TimeIs.ARRIVING,
journey_preference=JourneyPreference.LEASTINTERCHANGE
if journey_type == "easy"
else JourneyPreference.LEASTINTERCHANGE,
cycle_preference=cycle_preference,
bike_proficiency=BikeProficiency.FAST,
walking_optimization=journey_type == "quick",
mode=mode,
)
params: dict = {
"date": journey_date,
"time": journey_time,
"nationalSearch": "true",
"timeIs": "Arriving",
"cyclePreference": cycle_preference,
"bikeProficiency": "Fast",
"walkingOptimization": str(journey_type == "quick").lower(),
"mode": ",".join(mode),
}
if journey_preference:
params["journeyPreference"] = journey_preference
if response.status_code == HTTPStatus.OK and response.parsed:
journeys = response.parsed.journeys
if not isinstance(journeys, Unset) and journeys:
url = f"/Journey/JourneyResults/{from_location}/to/{to_location}"
response = await client.get(url, params=params)
if response.status_code == HTTPStatus.OK:
data = response.json()
journeys = data.get("journeys", [])
if journeys:
durations = [
j.duration
j["duration"]
for j in journeys
if not isinstance(j.duration, Unset)
if j.get("duration") is not None
]
if durations:
return min(durations)
@ -115,7 +114,7 @@ async def fetch_journey_for_mode(
HTTPStatus.GATEWAY_TIMEOUT,
):
warnings.warn(
f"HTTP {response.status_code.value} for {journey_type} from {from_location}, "
f"HTTP {response.status_code} for {journey_type} from {from_location}, "
f"retrying in {backoff:.1f}s (attempt {attempt + 1}/{retry_count})",
stacklevel=2,
)
@ -141,7 +140,7 @@ async def fetch_journey_for_mode(
async def fetch_all_modes(
client: Client,
client: httpx.AsyncClient,
rate_limiter: RateLimiter,
postcode: str,
lat: float,
@ -220,8 +219,15 @@ async def fetch_journey_times(
to_location = dest.to_tfl_location()
rate_limiter = RateLimiter()
client = Client(base_url="https://api.tfl.gov.uk").with_timeout(Timeout(30))
async with client as client:
# TFL API authentication via app_key query parameter
tfl_token = os.environ.get("TFL_TOKEN")
params = {"app_key": tfl_token} if tfl_token else {}
async with httpx.AsyncClient(
base_url=BASE_URL,
params=params,
timeout=httpx.Timeout(30),
) as client:
tasks = [
fetch_all_modes(
client,

View file

@ -8,7 +8,6 @@ dependencies = [
"attrs>=22.2.0",
"httpx>=0.28.1",
"ipywidgets>=8.0.0",
"journey-client",
"jupyter>=1.0.0",
"nest-asyncio>=1.6.0",
"numpy>=1.26.0",