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
+5 -2
View File
@@ -1,5 +1,8 @@
from __future__ import annotations
import json
import logging
from typing import Any
import geopandas
from shapely import prepare
@@ -17,10 +20,10 @@ class CQZoneData(LocalFileStaticDataProvider):
PATH = "datafiles/cqzones.geojson"
def __init__(self, provider_config):
def __init__(self, provider_config: dict[str, Any]) -> None:
super().__init__("CQ Zone Data", provider_config, self.PATH)
def _load_data(self, path):
def _load_data(self, path: str) -> bool:
try:
with open(path) as f:
cq_zone_data = geopandas.GeoDataFrame.from_features(json.load(f)["features"])
@@ -1,8 +1,12 @@
from __future__ import annotations
import logging
from datetime import datetime
from threading import Event, Thread
from typing import Any
import pytz
from requests import Response
from requests.exceptions import ConnectionError, ConnectTimeout, ReadTimeout
from core.constants import HTTP_HEADERS
@@ -16,36 +20,36 @@ class FileDownloadStaticDataProvider(StaticDataProvider):
"""Generic static reference data provider class for providers that fetch their data from the web by downloading a
file."""
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:
"""Set up the provider, note poll_interval is in *days*."""
super().__init__(name, provider_config)
self._url = url
self._poll_interval = poll_interval
self._thread = None
self._thread: Thread | None = None
self._stop_event = Event()
self._url_data_cache = URLDataCache(f"staticdata_{name}")
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} static reference data every {self._poll_interval!s} days.")
self._thread = Thread(target=self._run, name=f"FileDownloadStaticDataProvider-{self.name}", daemon=True)
self._thread.start()
def stop(self):
def stop(self) -> None:
self._stop_event.set()
if self._thread:
self._thread.join(timeout=12)
if self._thread.is_alive():
logger.warning(f"{self.name} static data worker thread did not exit on time and will be killed.")
def _run(self):
def _run(self) -> None:
while True:
self._poll()
if self._stop_event.wait(timeout=self._poll_interval * 60 * 60 * 24):
break
def _poll(self):
def _poll(self) -> None:
try:
# Request data from API. Use the data cache (with a TTL of 1 day) here, not as the main mechanism for
# caching, but just so continual restarts of the software during testing don't hammer the servers.
@@ -76,7 +80,7 @@ class FileDownloadStaticDataProvider(StaticDataProvider):
logger.exception(f"Exception in HTTP static reference data provider ({self.name})")
self._stop_event.wait(timeout=1)
def _handle_http_response(self, http_response):
def _handle_http_response(self, http_response: Response) -> bool:
"""Handle an HTTP response returned by the server and load the data from it. Return true if successful,
false otherwise."""
+5 -2
View File
@@ -1,5 +1,8 @@
from __future__ import annotations
import json
import logging
from typing import Any
import geopandas
from shapely import prepare
@@ -17,10 +20,10 @@ class ITUZoneData(LocalFileStaticDataProvider):
PATH = "datafiles/ituzones.geojson"
def __init__(self, provider_config):
def __init__(self, provider_config: dict[str, Any]) -> None:
super().__init__("ITU Zone Data", provider_config, self.PATH)
def _load_data(self, path):
def _load_data(self, path: str) -> bool:
try:
with open(path) as f:
itu_zone_data = geopandas.GeoDataFrame.from_features(json.load(f)["features"])
+8 -3
View File
@@ -1,4 +1,9 @@
from __future__ import annotations
import logging
from typing import Any
from requests import Response
from core.data_store import DATA_STORE
from providers.staticdata.file_download_static_data_provider import (
@@ -15,14 +20,14 @@ class K0SWE(FileDownloadStaticDataProvider):
POLL_INTERVAL_DAYS = 7
DATA_URL = "https://raw.githubusercontent.com/k0swe/dxcc-json/refs/heads/main/dxcc.json"
def __init__(self, provider_config):
def __init__(self, provider_config: dict[str, Any]) -> None:
super().__init__("K0SWE DXCC JSON", provider_config, self.DATA_URL, self.POLL_INTERVAL_DAYS)
def _handle_http_response(self, http_response):
def _handle_http_response(self, http_response: Response) -> bool:
try:
dxcc_list = http_response.json()["dxcc"]
# Reformat as a map for to place in the data store
dxcc_map = {}
dxcc_map: dict[int, Any] = {}
for dxcc in dxcc_list:
dxcc_map[dxcc["entityCode"]] = dxcc
@@ -1,5 +1,8 @@
from __future__ import annotations
import logging
from datetime import datetime
from typing import Any
import pytz
@@ -11,12 +14,12 @@ logger = logging.getLogger(__name__)
class LocalFileStaticDataProvider(StaticDataProvider):
"""Generic static reference data provider class for providers that fetch their data from a local file on startup."""
def __init__(self, name, provider_config, path):
def __init__(self, name: str, provider_config: dict[str, Any], path: str) -> None:
super().__init__(name, provider_config)
self._path = path
self._stop = False
def start(self):
def start(self) -> None:
logger.debug(f"Loading {self.name} static reference data from file.")
try:
ok = self._load_data(self._path)
@@ -31,10 +34,10 @@ class LocalFileStaticDataProvider(StaticDataProvider):
self.status = "Error"
logger.exception(f"Exception in local file Static Data Provider ({self.name})")
def stop(self):
def stop(self) -> None:
self._stop = True
def _load_data(self, path):
def _load_data(self, path: str) -> bool:
"""Load data from the given file path. Return true if successful, false otherwise."""
raise NotImplementedError("Subclasses must implement this method")
+7 -4
View File
@@ -1,4 +1,7 @@
from __future__ import annotations
from datetime import datetime
from typing import Any
import pytz
@@ -6,21 +9,21 @@ import pytz
class StaticDataProvider:
"""Generic static reference data provider class. Subclasses of this query the individual URLs or files for data."""
def __init__(self, name, provider_config):
def __init__(self, name: str, provider_config: dict[str, Any]) -> None:
"""Constructor"""
self.name = name
self.enabled = provider_config["enabled"]
self.enabled: bool = provider_config["enabled"]
self.last_update_time = datetime.min.replace(tzinfo=pytz.UTC)
self.status = "Not Started" if self.enabled else "Disabled"
self.reference_count = 0
def start(self):
def start(self) -> None:
"""Start the provider. This should return immediately after spawning threads to access the remote resources"""
raise NotImplementedError("Subclasses must implement this method")
def stop(self):
def stop(self) -> None:
"""Stop any threads and prepare for application shutdown"""
raise NotImplementedError("Subclasses must implement this method")