From 6d16194838f0d42dbb52a44d5b37dcea0c57186c Mon Sep 17 00:00:00 2001 From: Samuel Jones Date: Sat, 6 Jun 2026 20:34:22 +0100 Subject: [PATCH] Bit of a facelift - getting to point of needing templating. --- src/fares_site/api_calling.py | 31 +------------ src/fares_site/serve.py | 87 +++++++++++++++++++++++++++++------ 2 files changed, 74 insertions(+), 44 deletions(-) diff --git a/src/fares_site/api_calling.py b/src/fares_site/api_calling.py index 90c0384..4423181 100644 --- a/src/fares_site/api_calling.py +++ b/src/fares_site/api_calling.py @@ -4,34 +4,15 @@ Standard functions to call for fares information. # Imports import requests -import pandas as pd from os import environ import json # Init. -COLUMN_RENAMES = { - "origin_code": "Origin", - "destination_code": "Destination", - "route_code": "Route", - "status_code": "Status", - "usage_code": "Usage", - "direction": "Direction", - "end_date": "Ends", - "start_date": "Starts", - "toc": "TOC", - "cross_london_flag": "Cross London", - "settlement_flag": "Settlement", - "discount_flag": "Discount", - "flow_id": "ID", - "ticket_code": "Ticket Code", - "fare": "Fare", - "restriction_code": "Restriction", -} # Functions -def fares_query(origin: str, destination: str) -> pd.DataFrame: +def fares_query(origin: str, destination: str) -> list[dict[str, dict[str, str]]]: response = requests.get( url=f"https://fares.ballast-data.co.uk/fares?origin={origin}&destination={destination}", auth=( @@ -39,12 +20,4 @@ def fares_query(origin: str, destination: str) -> pd.DataFrame: environ.get("BD_FARES_PASS", ""), ), ) - dfs, data = [], json.loads(response.content.decode()) - for flow_fares in data: - df = pd.json_normalize(flow_fares["fares"]).drop("flow_id", axis=1) - meta = pd.DataFrame.from_records( - [flow_fares["flow_id"] | {"Number": number} for number in df.index] - ).rename(COLUMN_RENAMES, axis=1) - df.index = pd.MultiIndex.from_frame(meta) - dfs.append(df) - return pd.concat(dfs).rename(COLUMN_RENAMES, axis=1) + return json.loads(response.content.decode()) # pyright: ignore[reportAny] diff --git a/src/fares_site/serve.py b/src/fares_site/serve.py index 17f8d6e..4a2253b 100644 --- a/src/fares_site/serve.py +++ b/src/fares_site/serve.py @@ -3,8 +3,11 @@ Web server core for the fares site. """ # Import -from http.server import ThreadingHTTPServer, BaseHTTPRequestHandler -from logging import Logger, INFO +from http.server import BaseHTTPRequestHandler, ThreadingHTTPServer +from logging import INFO, Logger + +import pandas as pd +from pandas.io.formats.style import Styler from requests.exceptions import ConnectionError from fares_site.api_calling import fares_query @@ -13,6 +16,25 @@ from fares_site.api_calling import fares_query DEFAULT_ADDRESS = "127.0.0.1" DEFAULT_PORT = 12_000 +COLUMN_RENAMES = { + "origin_code": "Origin", + "destination_code": "Destination", + "route_code": "Route", + "status_code": "Status", + "usage_code": "Usage", + "direction": "Direction", + "end_date": "Ends", + "start_date": "Starts", + "toc": "TOC", + "cross_london_flag": "Cross London", + "settlement_flag": "Settlement", + "discount_flag": "Discount", + "flow_id": "ID", + "ticket_code": "Ticket Code", + "fare": "Fare", + "restriction_code": "Restriction", +} + HTML_CONTENT_HEADER = """ @@ -23,13 +45,32 @@ HTML_CONTENT_HEADER = """ - + + +
+
+Ballast-Data Product
+Contact: Non-Doxxing Email Lorum Ipsum
+Some Header Content +
+
+
+ +
+
- Fares
+ RailFares
+

""" HTML_CONTENT_FOOTER = """ +
+
+
+Open Rail Data Disclaimer Etc. | No Guarantees or Whatever | We do freelance and dont want to be poor. +
+
""" @@ -51,20 +92,36 @@ class FaresHandler(BaseHTTPRequestHandler): Generates the content of a GET request. Responsible for receiving the requests' details and constructing the output. """ - table = fares_query( + data = fares_query( origin=(_d := self.parse_url_query()).get("origin", "NCL"), destination=_d.get("destination", "NCL"), - ).style - table = table.set_table_styles( - [ - {"selector": "tr", "props": [("vertical-align", "text-top")]}, - { - "selector": "tbody td", - "props": [("border-top", "1px solid var(--dark-color)")], - }, - ] ) - text = table.to_html() + text = "" + text += ( + '\n' + ) + for flow_fares in data: + flow_table = ( + pd.json_normalize(flow_fares["flow_id"]) + .rename(COLUMN_RENAMES, axis=1) + .T.style + ) + _ = flow_table.hide(axis=1) + + fares_table = ( + pd.json_normalize(flow_fares["fares"]) + .drop("flow_id", axis=1) + .rename(COLUMN_RENAMES, axis=1) + .style + ) + _ = fares_table.hide(axis=0) + + text += ' \n \n " + text += "
Flow Fares
' + text += flow_table.to_html() + text += ' ' + text += fares_table.to_html() + text += "
" return HTML_CONTENT_HEADER + text + HTML_CONTENT_FOOTER def do_GET(self) -> None: