Use ruff linter to fix issues and provide consistent formatting

This commit is contained in:
Ian Renton
2026-08-15 08:25:54 +01:00
parent 7391c28cd0
commit af3f82c14d
121 changed files with 1989 additions and 996 deletions
+131 -36
View File
@@ -5,13 +5,23 @@ import os
import tornado
from tornado.web import StaticFileHandler
from core.config import ALLOW_SPOTTING, WEB_SERVER_PORT, API_ONLY_MODE, LOG_WEB_REQUESTS, BASE_URL
from core.config import (
ALLOW_SPOTTING,
API_ONLY_MODE,
BASE_URL,
LOG_WEB_REQUESTS,
WEB_SERVER_PORT,
)
from core.data_providers import DATA_PROVIDERS
from core.data_store import DATA_STORE
from server.handlers.api.addspot import APISpotHandler
from server.handlers.api.alerts import APIAlertsHandler, APIAlertsStreamHandler
from server.handlers.api.dxstats import APIDxStatsHandler
from server.handlers.api.lookups import APILookupCallHandler, APILookupSIGRefHandler, APILookupGridHandler
from server.handlers.api.lookups import (
APILookupCallHandler,
APILookupGridHandler,
APILookupSIGRefHandler,
)
from server.handlers.api.options import APIOptionsHandler
from server.handlers.api.solar_conditions import APISolarConditionsHandler
from server.handlers.api.spots import APISpotsHandler, APISpotsStreamHandler
@@ -45,7 +55,7 @@ class WebServer:
"last_api_access_time": None,
"page_access_counter": 0,
"api_access_counter": 0,
"status": "Starting"
"status": "Starting",
}
def setup(self):
@@ -76,30 +86,73 @@ class WebServer:
# API endpoints are always enabled
api_routes = [
(r"/api/v2/spots", APISpotsHandler, {"spots": self._data_store.spots, **handler_opts}),
(r"/api/v2/alerts", APIAlertsHandler, {"alerts": self._data_store.alerts, **handler_opts}),
(r"/api/v2/spots/stream", APISpotsStreamHandler,
{"sse_spot_broadcaster": self._spot_broadcaster, **handler_opts}),
(r"/api/v2/alerts/stream", APIAlertsStreamHandler,
{"sse_alert_broadcaster": self._alert_broadcaster, **handler_opts}),
(r"/api/v2/solar", APISolarConditionsHandler, {"solar_conditions": self._data_store.solar_conditions,
**handler_opts}),
(r"/api/v2/dxstats", APIDxStatsHandler, {"spots": self._data_store.spots, **handler_opts}),
(r"/api/v2/options", APIOptionsHandler, {"status_data": self._data_store.status_data, **handler_opts}),
(r"/api/v2/status", APIStatusHandler, {"status_data": self._data_store.status_data, **handler_opts}),
(
r"/api/v2/spots",
APISpotsHandler,
{"spots": self._data_store.spots, **handler_opts},
),
(
r"/api/v2/alerts",
APIAlertsHandler,
{"alerts": self._data_store.alerts, **handler_opts},
),
(
r"/api/v2/spots/stream",
APISpotsStreamHandler,
{"sse_spot_broadcaster": self._spot_broadcaster, **handler_opts},
),
(
r"/api/v2/alerts/stream",
APIAlertsStreamHandler,
{"sse_alert_broadcaster": self._alert_broadcaster, **handler_opts},
),
(
r"/api/v2/solar",
APISolarConditionsHandler,
{"solar_conditions": self._data_store.solar_conditions, **handler_opts},
),
(
r"/api/v2/dxstats",
APIDxStatsHandler,
{"spots": self._data_store.spots, **handler_opts},
),
(
r"/api/v2/options",
APIOptionsHandler,
{"status_data": self._data_store.status_data, **handler_opts},
),
(
r"/api/v2/status",
APIStatusHandler,
{"status_data": self._data_store.status_data, **handler_opts},
),
(r"/api/v2/lookup/call", APILookupCallHandler, {**handler_opts}),
(r"/api/v2/lookup/sigref", APILookupSIGRefHandler, {**handler_opts}),
(r"/api/v2/lookup/grid", APILookupGridHandler, {**handler_opts}),
(r"/api/v2/spot", APISpotHandler,
{"spots": self._data_store.spots, "spot_providers": self._data_providers, **handler_opts}),
(
r"/api/v2/spot",
APISpotHandler,
{
"spots": self._data_store.spots,
"spot_providers": self._data_providers,
**handler_opts,
},
),
]
# v1 API redirects. Most v1 enpoints are unchanged in v2, and get an HTTP 308 redirect to the v2 API. The ones
# that have the major breaking changes get a bespoke handler.
v1_compat_routes = [
(r"/api/v1/spots", V1APISpotsHandler, {"spots": self._data_store.spots, **handler_opts}),
(r"/api/v1/spots/stream", V1APISpotsStreamHandler,
{"sse_spot_broadcaster": self._spot_broadcaster, **handler_opts}),
(
r"/api/v1/spots",
V1APISpotsHandler,
{"spots": self._data_store.spots, **handler_opts},
),
(
r"/api/v1/spots/stream",
V1APISpotsStreamHandler,
{"sse_spot_broadcaster": self._spot_broadcaster, **handler_opts},
),
(r"/api/v1/spot", V1APISpotHandler),
(r"/api/v1/(.*)", V1RedirectHandler),
]
@@ -108,38 +161,82 @@ class WebServer:
if self._api_only_mode:
logging.info("API-only mode is enabled. Web UI will not be served.")
ui_routes = [
(r"/", PageTemplateHandler, {"template_name": "api_only_home", **handler_opts})
(
r"/",
PageTemplateHandler,
{"template_name": "api_only_home", **handler_opts},
)
]
else:
ui_routes = [
(r"/", PageTemplateHandler, {"template_name": "spots", **handler_opts}),
(r"/map", PageTemplateHandler, {"template_name": "map", **handler_opts}),
(r"/bands", PageTemplateHandler, {"template_name": "bands", **handler_opts}),
(r"/alerts", PageTemplateHandler, {"template_name": "alerts", **handler_opts}),
(r"/conditions", PageTemplateHandler, {"template_name": "conditions", **handler_opts}),
(r"/status", PageTemplateHandler, {"template_name": "status", **handler_opts}),
(r"/about", PageTemplateHandler, {"template_name": "about", **handler_opts})
(
r"/map",
PageTemplateHandler,
{"template_name": "map", **handler_opts},
),
(
r"/bands",
PageTemplateHandler,
{"template_name": "bands", **handler_opts},
),
(
r"/alerts",
PageTemplateHandler,
{"template_name": "alerts", **handler_opts},
),
(
r"/conditions",
PageTemplateHandler,
{"template_name": "conditions", **handler_opts},
),
(
r"/status",
PageTemplateHandler,
{"template_name": "status", **handler_opts},
),
(
r"/about",
PageTemplateHandler,
{"template_name": "about", **handler_opts},
),
]
# Only allow the Add Spot page if spotting is allowed
if ALLOW_SPOTTING:
ui_routes += [(r"/add-spot", PageTemplateHandler, {"template_name": "add_spot", **handler_opts})]
ui_routes += [
(
r"/add-spot",
PageTemplateHandler,
{"template_name": "add_spot", **handler_opts},
)
]
# API docs, Prometheus metrics, webapp manifest and static assets are always available regardless of API-only
# mode.
misc_routes = [
(r"/apidocs", PageTemplateHandler, {"template_name": "apidocs", **handler_opts}),
(
r"/apidocs",
PageTemplateHandler,
{"template_name": "apidocs", **handler_opts},
),
(r"/metrics", PrometheusMetricsHandler),
(r"/manifest.webmanifest", ManifestHandler),
# If e.g. nginx is configured as a reverse proxy with a hard-coded path to static files, as per the README,
# this will never have to handle anything, but having it here allows Spothole to work without nginx for
# testing.
(r"/static/(.*)", StaticFileHandler, {"path": os.path.join(_HERE, "../static")})
(
r"/static/(.*)",
StaticFileHandler,
{"path": os.path.join(_HERE, "../static")},
),
]
app = tornado.web.Application(api_routes + v1_compat_routes + ui_routes + misc_routes,
template_path=os.path.join(_HERE, "../templates"),
log_function=request_log,
debug=False)
app = tornado.web.Application(
api_routes + v1_compat_routes + ui_routes + misc_routes,
template_path=os.path.join(_HERE, "../templates"),
log_function=request_log,
debug=False,
)
app.listen(self._port, xheaders=True)
logging.info(f"Web server running on port {WEB_SERVER_PORT!s}")
logging.info(f"You can access your copy of Spothole at {BASE_URL}")
@@ -162,9 +259,7 @@ def request_log(handler):
user_agent = request.headers.get("User-Agent", "-")
log_method(
f'{client_ip} - "{request.method} {request.uri}" '
f'{handler.get_status()} {request.request_time():.2f}ms | '
f'Ref: {referrer} | UA: {user_agent}'
f'{client_ip} - "{request.method} {request.uri}" {handler.get_status()} {request.request_time():.2f}ms | Ref: {referrer} | UA: {user_agent}'
)