Autogenerated type safety parameterisation of all methods

This commit is contained in:
Ian Renton
2026-09-20 20:02:19 +01:00
parent 6037e742cc
commit 324dd1414b
132 changed files with 1228 additions and 706 deletions
+25 -20
View File
@@ -1,3 +1,5 @@
from __future__ import annotations
import copy
import logging
from datetime import datetime, timedelta
@@ -9,8 +11,11 @@ import tornado_eventsource.handler
from tornado import httputil
from tornado.web import Application
from core.live_data_cache import LiveDataCache
from core.utils import safe_json_dumps
from data.lookup_credentials import extract_credentials
from data.lookup_credentials import LookupCredentials, extract_credentials
from data.spot import Spot
from webserver.sse_broadcaster import SSEBroadcaster
logger = logging.getLogger(__name__)
@@ -20,18 +25,18 @@ class APISpotsHandler(tornado.web.RequestHandler):
def __init__(
self,
application: "Application",
application: Application,
request: httputil.HTTPServerRequest,
**kwargs: Any,
):
self._spots = None
) -> None:
self._spots: LiveDataCache | None = None
super().__init__(application, request, **kwargs)
def initialize(self, spots):
def initialize(self, spots: LiveDataCache) -> None:
self._spots = spots
@staticmethod
def _enrich(spots, credentials):
def _enrich(spots: list[Spot], credentials: LookupCredentials) -> list[Spot]:
enriched = []
for spot in spots:
spot_copy = copy.deepcopy(spot)
@@ -39,7 +44,7 @@ class APISpotsHandler(tornado.web.RequestHandler):
enriched.append(spot_copy)
return enriched
def get(self):
def get(self) -> None:
try:
# request.arguments contains lists for each param key because technically the client can supply multiple,
# reduce that to just the first entry, and convert bytes to string
@@ -70,22 +75,22 @@ class APISpotsHandler(tornado.web.RequestHandler):
class APISpotsStreamHandler(tornado_eventsource.handler.EventSourceHandler):
"""API request handler for /api/v2/spots/stream"""
def __init__(self, application, request, **kwargs: Any):
self._sse_spot_broadcaster = None
self._query_params = None
self._credentials = None
self._fields = None
def __init__(self, application: Application, request: httputil.HTTPServerRequest, **kwargs: Any) -> None:
self._sse_spot_broadcaster: SSEBroadcaster | None = None
self._query_params: dict[str, str] | None = None
self._credentials: LookupCredentials | None = None
self._fields: list[str] | None = None
super().__init__(application, request, **kwargs)
def initialize(self, sse_spot_broadcaster):
def initialize(self, sse_spot_broadcaster: SSEBroadcaster) -> None:
self._sse_spot_broadcaster = sse_spot_broadcaster
def custom_headers(self):
def custom_headers(self) -> dict[str, str]:
"""Custom headers to avoid e.g. nginx reverse proxy from buffering SSE data"""
return {"Cache-Control": "no-store", "X-Accel-Buffering": "no"}
def open(self):
def open(self) -> None:
"""Called once on the client opening a connection, set things up"""
try:
@@ -108,13 +113,13 @@ class APISpotsStreamHandler(tornado_eventsource.handler.EventSourceHandler):
logger.exception("Exception when serving SSE socket")
self.close()
def close(self):
def close(self) -> None:
"""When the user closes the socket, deregister ourselves from the spot broadcaster"""
self._sse_spot_broadcaster.unregister(self)
super().close()
def callback(self, spot):
def callback(self, spot: Spot) -> None:
"""Callback when a new spot arrives"""
try:
@@ -133,7 +138,7 @@ class APISpotsStreamHandler(tornado_eventsource.handler.EventSourceHandler):
self.close()
def get_spot_list_with_filters(all_spots, query):
def get_spot_list_with_filters(all_spots: LiveDataCache, query: dict[str, str]) -> list[Spot]:
"""Utility method to apply filters to the overall spot list and return only a subset. Enables query parameters in
the main "spots" GET call."""
@@ -173,7 +178,7 @@ def get_spot_list_with_filters(all_spots, query):
return spots
def spot_allowed_by_query(spot, query):
def spot_allowed_by_query(spot: Spot, query: dict[str, str]) -> bool:
"""Given URL query params and a spot, figure out if the spot "passes" the requested filters or is rejected. The list
of query parameters and their function is defined in the API docs."""
@@ -263,7 +268,7 @@ def spot_allowed_by_query(spot, query):
return True
def filter_fields(spots, fields):
def filter_fields(spots: list[Spot], fields: list[str]) -> list[dict[str, Any]]:
"""Given a list of spot objects, return copies containing only the named fields."""
return [{k: v for k, v in spot.__dict__.items() if k in fields} for spot in spots]