Bit of a facelift - getting to point of needing templating.
This commit is contained in:
@@ -4,34 +4,15 @@ Standard functions to call for fares information.
|
|||||||
|
|
||||||
# Imports
|
# Imports
|
||||||
import requests
|
import requests
|
||||||
import pandas as pd
|
|
||||||
from os import environ
|
from os import environ
|
||||||
import json
|
import json
|
||||||
|
|
||||||
|
|
||||||
# Init.
|
# 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
|
# 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(
|
response = requests.get(
|
||||||
url=f"https://fares.ballast-data.co.uk/fares?origin={origin}&destination={destination}",
|
url=f"https://fares.ballast-data.co.uk/fares?origin={origin}&destination={destination}",
|
||||||
auth=(
|
auth=(
|
||||||
@@ -39,12 +20,4 @@ def fares_query(origin: str, destination: str) -> pd.DataFrame:
|
|||||||
environ.get("BD_FARES_PASS", ""),
|
environ.get("BD_FARES_PASS", ""),
|
||||||
),
|
),
|
||||||
)
|
)
|
||||||
dfs, data = [], json.loads(response.content.decode())
|
return json.loads(response.content.decode()) # pyright: ignore[reportAny]
|
||||||
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)
|
|
||||||
|
|||||||
+72
-15
@@ -3,8 +3,11 @@ Web server core for the fares site.
|
|||||||
"""
|
"""
|
||||||
|
|
||||||
# Import
|
# Import
|
||||||
from http.server import ThreadingHTTPServer, BaseHTTPRequestHandler
|
from http.server import BaseHTTPRequestHandler, ThreadingHTTPServer
|
||||||
from logging import Logger, INFO
|
from logging import INFO, Logger
|
||||||
|
|
||||||
|
import pandas as pd
|
||||||
|
from pandas.io.formats.style import Styler
|
||||||
from requests.exceptions import ConnectionError
|
from requests.exceptions import ConnectionError
|
||||||
|
|
||||||
from fares_site.api_calling import fares_query
|
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_ADDRESS = "127.0.0.1"
|
||||||
DEFAULT_PORT = 12_000
|
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 = """
|
HTML_CONTENT_HEADER = """
|
||||||
<!DOCTYPE HTML>
|
<!DOCTYPE HTML>
|
||||||
<html>
|
<html>
|
||||||
@@ -23,13 +45,32 @@ HTML_CONTENT_HEADER = """
|
|||||||
<link rel="stylesheet" href="https://cdn.ballast-data.co.uk/theme.css">
|
<link rel="stylesheet" href="https://cdn.ballast-data.co.uk/theme.css">
|
||||||
<link rel="icon" type="image/x-icon" href="https://cdn.ballast-data.co.uk/Icon.svg">
|
<link rel="icon" type="image/x-icon" href="https://cdn.ballast-data.co.uk/Icon.svg">
|
||||||
</head>
|
</head>
|
||||||
<body>
|
<body style="padding: 0px; margin: 0px;">
|
||||||
|
|
||||||
|
<div style="width: 100%; padding: 0px; margin: 0px; background-color: var(--dark-color);">
|
||||||
|
<div style="margin-left: auto; margin-right: auto; width: fit-content; background-color: var(--secondary-accent); margin-top: 0px; padding: 12px; border-radius: 0 0 9px 9px;">
|
||||||
|
Ballast-Data Product <br>
|
||||||
|
Contact: Non-Doxxing Email Lorum Ipsum <br>
|
||||||
|
Some Header Content
|
||||||
|
</div>
|
||||||
|
<br>
|
||||||
|
<div style="width: fit-content; margin-left: auto; margin-right: auto; border: 9px solid var(--light-color); border-radius: 3px; padding: 12px; background-color: white; border-radius: 9px;">
|
||||||
|
|
||||||
|
<div style="width: fit-content; margin-left: auto; margin-right: auto; border-bottom: 9px solid var(--secondary-accent);">
|
||||||
|
<br>
|
||||||
<img height=80px src="https://cdn.ballast-data.co.uk/Logo.svg">
|
<img height=80px src="https://cdn.ballast-data.co.uk/Logo.svg">
|
||||||
<b style="font-size: 100px; line-height: 1; font-weight: 400;"> Fares </b> <br>
|
<b style="font-size: 60px; line-height: 1; font-weight: 400;"> RailFares </b> <br>
|
||||||
|
</div>
|
||||||
<br>
|
<br>
|
||||||
"""
|
"""
|
||||||
|
|
||||||
HTML_CONTENT_FOOTER = """
|
HTML_CONTENT_FOOTER = """
|
||||||
|
</div>
|
||||||
|
<br>
|
||||||
|
<div style="margin-left: auto; margin-right: auto; width: fit-content; background-color: var(--primary-accent); margin-top: 0px; padding: 12px; border-radius: 9px 9px 0 0;">
|
||||||
|
Open Rail Data Disclaimer Etc. | No Guarantees or Whatever | We do freelance and dont want to be poor.
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
</body>
|
</body>
|
||||||
</html>
|
</html>
|
||||||
"""
|
"""
|
||||||
@@ -51,20 +92,36 @@ class FaresHandler(BaseHTTPRequestHandler):
|
|||||||
Generates the content of a GET request.
|
Generates the content of a GET request.
|
||||||
Responsible for receiving the requests' details and constructing the output.
|
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"),
|
origin=(_d := self.parse_url_query()).get("origin", "NCL"),
|
||||||
destination=_d.get("destination", "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 = "<table>"
|
||||||
|
text += (
|
||||||
|
'<tr style="font-size: 1.6em;"> <th> Flow </th> <th> Fares </th> </tr>\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 += '<tr> \n <td style="border-top: 6px solid var(--primary-accent); vertical-align: top;">'
|
||||||
|
text += flow_table.to_html()
|
||||||
|
text += '</td> <td style="border-top: 6px solid var(--primary-accent); vertical-align: top;">'
|
||||||
|
text += fares_table.to_html()
|
||||||
|
text += "</td> \n </tr>"
|
||||||
|
text += "</table>"
|
||||||
return HTML_CONTENT_HEADER + text + HTML_CONTENT_FOOTER
|
return HTML_CONTENT_HEADER + text + HTML_CONTENT_FOOTER
|
||||||
|
|
||||||
def do_GET(self) -> None:
|
def do_GET(self) -> None:
|
||||||
|
|||||||
Reference in New Issue
Block a user