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
+16 -12
View File
@@ -1,12 +1,16 @@
from __future__ import annotations
import logging
from datetime import datetime
from threading import Event, Thread
from typing import Any
import pytz
import requests
from requests.exceptions import ConnectionError, ConnectTimeout, JSONDecodeError, ReadTimeout
from core.constants import HTTP_HEADERS
from data.spot import Spot
from providers.spot.spot_provider import SpotProvider
logger = logging.getLogger(__name__)
@@ -16,22 +20,22 @@ class HTTPSpotProvider(SpotProvider):
"""Generic spot provider class for providers that request data via HTTP(S). Just for convenience to avoid code
duplication. Subclasses of this query the individual APIs for data."""
def __init__(self, name, provider_config, url, poll_interval):
def __init__(self, name: str, provider_config: dict[str, Any], url: str, poll_interval: float) -> None:
super().__init__(name, provider_config)
self._url = url
self._poll_interval = poll_interval
self._thread = None
self._stop_event = Event()
self._wakeup_event = Event()
self._url: str = url
self._poll_interval: float = poll_interval
self._thread: Thread | None = None
self._stop_event: Event = Event()
self._wakeup_event: Event = Event()
def start(self):
def start(self) -> None:
# Fire off the polling thread. It will poll immediately on startup, then sleep for poll_interval between
# subsequent polls, so start() returns immediately and the application can continue starting.
logger.info(f"Set up query of {self.name} spot API every {self._poll_interval!s} seconds.")
self._thread = Thread(target=self._run, name=f"HTTPSpotProvider-{self.name}", daemon=True)
self._thread.start()
def stop(self):
def stop(self) -> None:
self._stop_event.set()
self._wakeup_event.set()
if self._thread:
@@ -39,12 +43,12 @@ class HTTPSpotProvider(SpotProvider):
if self._thread.is_alive():
logger.warning(f"{self.name} spot worker thread did not exit on time and will be killed.")
def force_poll(self):
def force_poll(self) -> None:
"""Trigger an immediate poll without waiting for the normal interval."""
self._wakeup_event.set()
def _run(self):
def _run(self) -> None:
while True:
self._wakeup_event.clear()
self._poll()
@@ -52,7 +56,7 @@ class HTTPSpotProvider(SpotProvider):
if self._stop_event.is_set():
break
def _poll(self):
def _poll(self) -> None:
try:
# Request data from API
logger.debug(f"Polling {self.name} spot API...")
@@ -86,7 +90,7 @@ class HTTPSpotProvider(SpotProvider):
logger.exception(f"Exception in HTTP Spot Provider ({self.name})")
self._stop_event.wait(timeout=1)
def _http_response_to_spots(self, http_response):
def _http_response_to_spots(self, http_response: requests.Response) -> list[Spot] | None:
"""Convert an HTTP response returned by the API into spot data. The whole response is provided here so the subclass
implementations can check for HTTP status codes if necessary, and handle the response as JSON, XML, text, whatever
the API actually provides."""