Logging tidy-up, IDE inspection fixes

This commit is contained in:
Ian Renton
2026-08-15 07:42:38 +01:00
parent 9cd6d9c177
commit bff5b79f8f
40 changed files with 128 additions and 125 deletions
+22
View File
@@ -3,6 +3,7 @@
<option name="myName" value="Project Default" /> <option name="myName" value="Project Default" />
<inspection_tool class="Annotator" enabled="false" level="ERROR" enabled_by_default="false" /> <inspection_tool class="Annotator" enabled="false" level="ERROR" enabled_by_default="false" />
<inspection_tool class="BadExpressionStatementJS" enabled="false" level="WEAK WARNING" enabled_by_default="false" /> <inspection_tool class="BadExpressionStatementJS" enabled="false" level="WEAK WARNING" enabled_by_default="false" />
<inspection_tool class="CheckImageSize" enabled="false" level="WARNING" enabled_by_default="false" />
<inspection_tool class="CssOverwrittenProperties" enabled="false" level="WARNING" enabled_by_default="false" /> <inspection_tool class="CssOverwrittenProperties" enabled="false" level="WARNING" enabled_by_default="false" />
<inspection_tool class="CssUnresolvedCustomProperty" enabled="false" level="ERROR" enabled_by_default="false" /> <inspection_tool class="CssUnresolvedCustomProperty" enabled="false" level="ERROR" enabled_by_default="false" />
<inspection_tool class="CssUnusedSymbol" enabled="false" level="WARNING" enabled_by_default="false" /> <inspection_tool class="CssUnusedSymbol" enabled="false" level="WARNING" enabled_by_default="false" />
@@ -43,6 +44,27 @@
<inspection_tool class="LanguageDetectionInspection" enabled="false" level="WEAK WARNING" enabled_by_default="false" /> <inspection_tool class="LanguageDetectionInspection" enabled="false" level="WEAK WARNING" enabled_by_default="false" />
<inspection_tool class="OutdatedRequirementInspection" enabled="false" level="WEAK WARNING" enabled_by_default="false" /> <inspection_tool class="OutdatedRequirementInspection" enabled="false" level="WEAK WARNING" enabled_by_default="false" />
<inspection_tool class="PyBroadExceptionInspection" enabled="false" level="WEAK WARNING" enabled_by_default="false" /> <inspection_tool class="PyBroadExceptionInspection" enabled="false" level="WEAK WARNING" enabled_by_default="false" />
<inspection_tool class="PyCompatibilityInspection" enabled="true" level="WARNING" enabled_by_default="true">
<option name="ourVersions">
<value>
<list size="6">
<item index="0" class="java.lang.String" itemvalue="3.15" />
<item index="1" class="java.lang.String" itemvalue="3.14" />
<item index="2" class="java.lang.String" itemvalue="3.13" />
<item index="3" class="java.lang.String" itemvalue="3.12" />
<item index="4" class="java.lang.String" itemvalue="3.11" />
<item index="5" class="java.lang.String" itemvalue="3.10" />
</list>
</value>
</option>
</inspection_tool>
<inspection_tool class="PyStringConversionWithoutDunderMethodInspection" enabled="true" level="WEAK WARNING" enabled_by_default="true">
<option name="ignoredTypes">
<list>
<option value="types.NoneType" />
</list>
</option>
</inspection_tool>
<inspection_tool class="SpellCheckingInspection" enabled="false" level="TYPO" enabled_by_default="false"> <inspection_tool class="SpellCheckingInspection" enabled="false" level="TYPO" enabled_by_default="false">
<option name="processCode" value="true" /> <option name="processCode" value="true" />
<option name="processLiterals" value="true" /> <option name="processLiterals" value="true" />
+1 -1
View File
@@ -12,7 +12,7 @@ def get_call_info(callsign, lookup_credentials):
if callsign: if callsign:
# Sort callsign providers by priority order, so we query the highest priority (lowest numbers) first, and only # Sort callsign providers by priority order, so we query the highest priority (lowest numbers) first, and only
# query other providers for data we are missing as we go along. # query other providers for data we are missing as we go along.
for p in sorted(DATA_PROVIDERS.callsign_data_providers, key=lambda p: p.priority): for p in sorted(DATA_PROVIDERS.callsign_data_providers, key=lambda p2: p2.priority):
if p.enabled: if p.enabled:
# Get new lookup data # Get new lookup data
data = p.lookup(callsign, lookup_credentials) data = p.lookup(callsign, lookup_credentials)
+2 -2
View File
@@ -31,10 +31,10 @@ class DataProviders:
self.callsign_data_providers.append(create_provider_from_config("providers.callsigndata", entry)) self.callsign_data_providers.append(create_provider_from_config("providers.callsigndata", entry))
@staticmethod @staticmethod
def start_providers(providers, type): def start_providers(providers, provider_type):
"""Helper method to activate enabled providers in the list.""" """Helper method to activate enabled providers in the list."""
logging.info(f"Starting %s providers...", type) logging.info(f"Starting %s providers...", provider_type)
for p in providers: for p in providers:
if p.enabled: if p.enabled:
p.start() p.start()
+2 -2
View File
@@ -34,7 +34,7 @@ class LiveDataCache:
try: try:
callback(value) callback(value)
except Exception: except Exception:
logging.error("Listener raised an exception for key %s", key, exc_info=True) logging.exception("Listener raised an exception for key %s", key)
def get(self, key, default=None): def get(self, key, default=None):
@@ -71,7 +71,7 @@ class LiveDataCache:
try: try:
self._disk_cache.set("snapshot", data) self._disk_cache.set("snapshot", data)
except Exception as e: except Exception as e:
logging.error("Failed to write snapshot to %s", self._snapshot_dir, e, exc_info=True) logging.exception("Failed to write snapshot to %s", self._snapshot_dir, e)
def _load_snapshot(self): def _load_snapshot(self):
data = self._disk_cache.get("snapshot") data = self._disk_cache.get("snapshot")
+7 -6
View File
@@ -29,7 +29,7 @@ def get_sig_ref_info(sig, ref_id):
# If the SIG is HEMA, we have no current lookup for this so just skip the lookup here. # If the SIG is HEMA, we have no current lookup for this so just skip the lookup here.
if sig.upper() == "HEMA": if sig.upper() == "HEMA":
sig_ref.type = "Summit" sig_ref.ref_type = "Summit"
return sig_ref return sig_ref
### PROGRAMMATIC DATA GENERATION INSTEAD OF LOOKUPS ### ### PROGRAMMATIC DATA GENERATION INSTEAD OF LOOKUPS ###
@@ -38,7 +38,7 @@ def get_sig_ref_info(sig, ref_id):
# calculate all the information we are going to get directly. # calculate all the information we are going to get directly.
if sig.upper() == "TILES": if sig.upper() == "TILES":
# Tiles on the Air just uses Maidenhead 6-digit squares, so ID, Name and Grid are all the same # Tiles on the Air just uses Maidenhead 6-digit squares, so ID, Name and Grid are all the same
sig_ref.type = "Grid" sig_ref.ref_type = "Grid"
if not sig_ref.name: if not sig_ref.name:
sig_ref.name = sig_ref.id sig_ref.name = sig_ref.id
if not sig_ref.grid: if not sig_ref.grid:
@@ -50,7 +50,7 @@ def get_sig_ref_info(sig, ref_id):
return sig_ref return sig_ref
elif sig.upper() == "WAB" or sig.upper() == "WAI": elif sig.upper() == "WAB" or sig.upper() == "WAI":
sig_ref.type = "Grid" sig_ref.ref_type = "Grid"
ll = wab_wai_square_to_lat_lon(ref_id) ll = wab_wai_square_to_lat_lon(ref_id)
if ll: if ll:
sig_ref.name = ref_id sig_ref.name = ref_id
@@ -64,10 +64,11 @@ def get_sig_ref_info(sig, ref_id):
elif sig.upper() == "BOTA": elif sig.upper() == "BOTA":
# For BOTA all we can ever generate is the URL, there is no data file or lookup for lat/longs # For BOTA all we can ever generate is the URL, there is no data file or lookup for lat/longs
sig_ref.type = "Beach" sig_ref.ref_type = "Beach"
if not sig_ref.name: if not sig_ref.name:
sig_ref.name = sig_ref.id sig_ref.name = sig_ref.id
sig_ref.url = "https://www.beachesontheair.com/beaches/" + sig_ref.name.lower().replace(" ", "-") if sig_ref.name:
sig_ref.url = "https://www.beachesontheair.com/beaches/" + sig_ref.name.lower().replace(" ", "-")
return sig_ref return sig_ref
### ACTUAL LOOKUP ### ### ACTUAL LOOKUP ###
@@ -85,7 +86,7 @@ def get_sig_ref_info(sig, ref_id):
logging.debug("%s database did not contain data for ref %s", sig, ref_id) logging.debug("%s database did not contain data for ref %s", sig, ref_id)
except Exception: except Exception:
logging.error("Exception when looking up sig_ref info for " + sig + " ref " + ref_id, exc_info=True) logging.exception("Exception when looking up sig_ref info for " + sig + " ref " + ref_id)
return sig_ref return sig_ref
+2 -3
View File
@@ -1,4 +1,3 @@
import copy
import hashlib import hashlib
import json import json
import logging import logging
@@ -128,8 +127,8 @@ class Alert:
self.dx_names = list( self.dx_names = list(
map(lambda c: get_call_info(c, credentials).name, self.dx_calls)) map(lambda c: get_call_info(c, credentials).name, self.dx_calls))
except Exception as e: except Exception:
logging.error("Exception while inferring missing data from spot", e, exc_info=True) logging.exception("Exception while inferring missing data from spot")
def to_json(self): def to_json(self):
"""JSON serialise""" """JSON serialise"""
+6 -6
View File
@@ -1,4 +1,4 @@
import copy import hashlib
import hashlib import hashlib
import json import json
import logging import logging
@@ -9,12 +9,12 @@ from datetime import datetime, timedelta
import pytz import pytz
from pyhamtools.locator import locator_to_latlong, latlong_to_locator from pyhamtools.locator import locator_to_latlong, latlong_to_locator
from core.call_lookup_helper import get_call_info
from core.config import MAX_SPOT_AGE from core.config import MAX_SPOT_AGE
from core.constants import MODE_ALIASES, PROPAGATION_MODES from core.constants import MODE_ALIASES, PROPAGATION_MODES
from core.geo_utils import lat_lon_to_cq_zone, lat_lon_to_itu_zone from core.geo_utils import lat_lon_to_cq_zone, lat_lon_to_itu_zone
from core.call_lookup_helper import get_call_info
from core.sig_utils import ANY_SIG_REGEX, get_ref_regex_for_sig, get_sig_name_from_comment_name
from core.sig_lookup_helper import populate_missing_sig_ref_info from core.sig_lookup_helper import populate_missing_sig_ref_info
from core.sig_utils import ANY_SIG_REGEX, get_ref_regex_for_sig, get_sig_name_from_comment_name
from core.utils import infer_band_from_freq, infer_mode_from_comment, \ from core.utils import infer_band_from_freq, infer_mode_from_comment, \
infer_mode_from_frequency, infer_mode_type_from_mode, get_flag_for_dxcc infer_mode_from_frequency, infer_mode_type_from_mode, get_flag_for_dxcc
from data.sig_ref import SIGRef from data.sig_ref import SIGRef
@@ -413,7 +413,7 @@ class Spot:
or (self.dx_location_source == "HOME QTH" and "/" not in (self.dx_call or "")))) or (self.dx_location_source == "HOME QTH" and "/" not in (self.dx_call or ""))))
# DE with no digits and APRS servers starting "T2" are not things we can look up location for # DE with no digits and APRS servers starting "T2" are not things we can look up location for
if self.de_call and any(char.isdigit() for char in self.de_call) and not ( if self.de_call and any(char.isdigit() for char in str(self.de_call)) and not (
self.de_call.startswith("T2") and self.source == "APRS-IS"): self.de_call.startswith("T2") and self.source == "APRS-IS"):
# DE operator location lookup # DE operator location lookup
if not self.de_latitude: if not self.de_latitude:
@@ -421,8 +421,8 @@ class Spot:
self.de_longitude = de_call_info.longitude self.de_longitude = de_call_info.longitude
self.de_grid = de_call_info.grid self.de_grid = de_call_info.grid
except Exception as e: except Exception:
logging.error("Exception while inferring missing data from spot", e, exc_info=True) logging.exception("Exception while inferring missing data from spot")
def to_json(self): def to_json(self):
"""JSON serialise""" """JSON serialise"""
+1 -1
View File
@@ -3,7 +3,7 @@
If you want to run a copy of Spothole with different configuration settings than the main instance, you can download it If you want to run a copy of Spothole with different configuration settings than the main instance, you can download it
and run it on your own local machine or server. and run it on your own local machine or server.
You will require Python version 3.8 or later. If you encounter an error about `gdal-config` during the following You will require Python version 3.10 or later. If you encounter an error about `gdal-config` during the following
process, you will also need `libgdal-dev` installed. process, you will also need `libgdal-dev` installed.
To download and set up Spothole on a Debian server, run the following commands. Other operating systems will likely be To download and set up Spothole on a Debian server, run the following commands. Other operating systems will likely be
@@ -1,13 +1,3 @@
import logging
from datetime import datetime
from threading import Thread, Event
import pytz
from requests import ReadTimeout
from requests.exceptions import ConnectionError, ConnectTimeout
from core.constants import HTTP_HEADERS
from core.url_data_cache import URLDataCache
from providers.callsigndata.callsign_data_provider import CallsignDataProvider from providers.callsigndata.callsign_data_provider import CallsignDataProvider
@@ -1,4 +1,3 @@
import logging
from datetime import datetime from datetime import datetime
import pytz import pytz
+2 -2
View File
@@ -41,8 +41,8 @@ class ClublogAPI(APIQueryCallsignDataProvider):
else: else:
return None return None
except Exception as e: except Exception:
self.status = "Error" self.status = "Error"
logging.error("Exception when looking up data from Clublog API", e, exc_info=True) logging.exception("Exception when looking up data from Clublog API")
return callsign_data return callsign_data
+4 -6
View File
@@ -1,8 +1,6 @@
import gzip import gzip
import logging import logging
from datetime import datetime
import pytz
from pyhamtools import LookupLib, Callinfo from pyhamtools import LookupLib, Callinfo
from core.data_store import DATA_STORE from core.data_store import DATA_STORE
@@ -47,8 +45,8 @@ class ClublogXML(FileDownloadCallsignDataProvider):
self._callinfo = Callinfo(lookuplib) self._callinfo = Callinfo(lookuplib)
return True return True
except Exception as e: except Exception:
logging.error("Exception when loading Clublog XML.", e, exc_info=True) logging.exception("Exception when loading Clublog XML.")
return False return False
def _perform_new_lookup(self, callsign, lookup_credentials): def _perform_new_lookup(self, callsign, lookup_credentials):
@@ -62,8 +60,8 @@ class ClublogXML(FileDownloadCallsignDataProvider):
else: else:
return None return None
except Exception as e: except Exception:
self.status = "Error" self.status = "Error"
logging.error("Exception when looking up data from Clublog XML data", e, exc_info=True) logging.exception("Exception when looking up data from Clublog XML data")
return callsign_data return callsign_data
+4 -4
View File
@@ -26,8 +26,8 @@ class CountryFiles(FileDownloadCallsignDataProvider):
self._callinfo = Callinfo(lookuplib) self._callinfo = Callinfo(lookuplib)
return True return True
except Exception as e: except Exception:
logging.error("Exception when loading Country Files cty.plist.", e, exc_info=True) logging.exception("Exception when loading Country Files cty.plist.")
return False return False
def _perform_new_lookup(self, callsign, lookup_credentials): def _perform_new_lookup(self, callsign, lookup_credentials):
@@ -41,8 +41,8 @@ class CountryFiles(FileDownloadCallsignDataProvider):
else: else:
return None return None
except Exception as e: except Exception:
self.status = "Error" self.status = "Error"
logging.error("Exception when looking up data from Country file", e, exc_info=True) logging.exception("Exception when looking up data from Country file")
return callsign_data return callsign_data
+3 -3
View File
@@ -97,15 +97,15 @@ class HamQTH(APIQueryCallsignDataProvider):
logging.warning(f"Timeout when looking up callsign %s using HamQTH", lookup_call) logging.warning(f"Timeout when looking up callsign %s using HamQTH", lookup_call)
continue continue
except Exception: except Exception:
logging.error("Exception when looking up callsign %s using HamQTH", lookup_call, exc_info=True) logging.exception("Exception when looking up callsign %s using HamQTH", lookup_call)
continue continue
# Not found in HamQTH; return a Callsign object with no data so we cache that and don't keep retrying # Not found in HamQTH; return a Callsign object with no data so we cache that and don't keep retrying
return Callsign(call=callsign) return Callsign(call=callsign)
except Exception as e: except Exception:
self.status = "Error" self.status = "Error"
logging.error("Exception when looking up data from HamQTH", e, exc_info=True) logging.exception("Exception when looking up data from HamQTH")
# Return None, this won't be cached so we will be asked to query data again for this call next time. # Return None, this won't be cached so we will be asked to query data again for this call next time.
return None return None
+3 -3
View File
@@ -106,15 +106,15 @@ class QRZ(APIQueryCallsignDataProvider):
logging.warning(f"Timeout when looking up callsign %s using QRZ.", lookup_call) logging.warning(f"Timeout when looking up callsign %s using QRZ.", lookup_call)
continue continue
except Exception: except Exception:
logging.error("Exception when looking up callsign %s using QRZ", lookup_call, exc_info=True) logging.exception("Exception when looking up callsign %s using QRZ", lookup_call)
continue continue
# Not found in QRZ; return a Callsign object with no data so we cache that and don't keep retrying # Not found in QRZ; return a Callsign object with no data so we cache that and don't keep retrying
return Callsign(call=callsign) return Callsign(call=callsign)
except Exception as e: except Exception:
self.status = "Error" self.status = "Error"
logging.error("Exception when looking up data from QRZ.com", e, exc_info=True) logging.exception("Exception when looking up data from QRZ.com")
# Return None, this won't be cached so we will be asked to query data again for this call next time. # Return None, this won't be cached so we will be asked to query data again for this call next time.
return None return None
@@ -24,9 +24,9 @@ class LocalFileSIGRefDataProvider(SIGRefDataProvider):
else: else:
self.status = "Error" self.status = "Error"
logging.info("Failed to load SIG ref data for " + self.sig_name) logging.info("Failed to load SIG ref data for " + self.sig_name)
except Exception as e: except Exception:
self.status = "Error" self.status = "Error"
logging.error("Exception in local file SIG Ref Data Provider (" + self.sig_name + ")", e, exc_info=True) logging.exception("Exception in local file SIG Ref Data Provider (" + self.sig_name + ")")
def _file_to_data(self, path): def _file_to_data(self, path):
"""Load a file on the given path and turn it into SIG Ref data.""" """Load a file on the given path and turn it into SIG Ref data."""
@@ -24,7 +24,9 @@ class ParksNPeaksKMLSIGRefDataProvider(FileDownloadSIGRefDataProvider):
k = kml.KML.from_string(http_response.content) k = kml.KML.from_string(http_response.content)
for document in k.features: for document in k.features:
# noinspection unresolved-references
for folder in document.features: for folder in document.features:
# noinspection unresolved-references
for placemark in folder.features: for placemark in folder.features:
description = placemark.description or "" description = placemark.description or ""
match = self.REF_PATTERN.search(description) match = self.REF_PATTERN.search(description)
+2 -2
View File
@@ -115,8 +115,8 @@ class GMA(HTTPSpotProvider):
logging.warning( logging.warning(
f"GMA API returned a malformed response when looking up ref {source_spot['REF']}") f"GMA API returned a malformed response when looking up ref {source_spot['REF']}")
except: except:
logging.warning("Exception when looking up " + self.REF_INFO_URL_ROOT + source_spot[ logging.exception("Exception when looking up " + self.REF_INFO_URL_ROOT + source_spot[
"REF"] + ", ignoring this spot for now", exc_info=True) "REF"] + ", ignoring this spot for now")
else: else:
logging.warning(f"The GMA API returned an unexpected response (HTTP {http_response.status_code}).") logging.warning(f"The GMA API returned an unexpected response (HTTP {http_response.status_code}).")
+2 -2
View File
@@ -31,6 +31,6 @@ class CQZoneData(LocalFileStaticDataProvider):
DATA_STORE.cq_zone_data = cq_zone_data DATA_STORE.cq_zone_data = cq_zone_data
return True return True
except Exception as e: except Exception:
logging.error("Exception when loading CQ zone data.", e, exc_info=True) logging.exception("Exception when loading CQ zone data.")
return False return False
+2 -2
View File
@@ -31,6 +31,6 @@ class ITUZoneData(LocalFileStaticDataProvider):
DATA_STORE.itu_zone_data = itu_zone_data DATA_STORE.itu_zone_data = itu_zone_data
return True return True
except Exception as e: except Exception:
logging.error("Exception when loading ITU zone data.", e, exc_info=True) logging.exception("Exception when loading ITU zone data.")
return False return False
+2 -2
View File
@@ -41,8 +41,8 @@ class K0SWE(FileDownloadStaticDataProvider):
return True return True
except Exception as e: except Exception:
logging.error("Exception when loading K0SWE dxcc.json.", e, exc_info=True) logging.exception("Exception when loading K0SWE dxcc.json.")
return False return False
@@ -25,9 +25,9 @@ class LocalFileStaticDataProvider(StaticDataProvider):
else: else:
self.status = "Error" self.status = "Error"
logging.error("Failed to load data for " + self.name) logging.error("Failed to load data for " + self.name)
except Exception as e: except Exception:
self.status = "Error" self.status = "Error"
logging.error("Exception in local file Static Data Provider (" + self.name + ")", e, exc_info=True) logging.exception("Exception in local file Static Data Provider (" + self.name + ")")
def stop(self): def stop(self):
self._stop = True self._stop = True
+2 -2
View File
@@ -232,8 +232,8 @@ class APISpotHandler(tornado.web.RequestHandler):
self.set_header("Cache-Control", "no-store") self.set_header("Cache-Control", "no-store")
self.set_header("Content-Type", "application/json") self.set_header("Content-Type", "application/json")
except Exception as e: except Exception:
logging.error("Exception when handling client request to add spot API: %s", e, exc_info=True) logging.exception("Exception when handling client request to add spot API")
self.write(safe_json_dumps("Error - an internal server error occurred.")) self.write(safe_json_dumps("Error - an internal server error occurred."))
self.set_status(500) self.set_status(500)
self.set_header("Cache-Control", "no-store") self.set_header("Cache-Control", "no-store")
+6 -17
View File
@@ -1,5 +1,4 @@
import copy import copy
import inspect
import logging import logging
from datetime import datetime from datetime import datetime
from typing import Any from typing import Any
@@ -53,28 +52,18 @@ class APIAlertsHandler(tornado.web.RequestHandler):
data = get_alert_list_with_filters(self._alerts, query_params) data = get_alert_list_with_filters(self._alerts, query_params)
if credentials: if credentials:
data = self._enrich(data, credentials) data = self._enrich(data, credentials)
find_bad_values(data)
self.write(safe_json_dumps(data)) self.write(safe_json_dumps(data))
self.set_status(200) self.set_status(200)
except ValueError as e: except ValueError as e:
self.write(safe_json_dumps("Bad request - " + str(e))) self.write(safe_json_dumps("Bad request - " + str(e)))
self.set_status(400) self.set_status(400)
except Exception as e: except Exception:
logging.error("Exception when handling client request to alerts API: %s", e, exc_info=True) logging.exception("Exception when handling client request to alerts API")
self.write(safe_json_dumps("Error - an internal server error occurred.")) self.write(safe_json_dumps("Error - an internal server error occurred."))
self.set_status(500) self.set_status(500)
self.set_header("Cache-Control", "no-store") self.set_header("Cache-Control", "no-store")
self.set_header("Content-Type", "application/json") self.set_header("Content-Type", "application/json")
def find_bad_values(obj, path="data"):
if isinstance(obj, dict):
for k, v in obj.items():
find_bad_values(v, f"{path}[{k!r}]")
elif isinstance(obj, (list, tuple)):
for i, v in enumerate(obj):
find_bad_values(v, f"{path}[{i}]")
elif inspect.isbuiltin(obj) or inspect.ismethod(obj) or inspect.isfunction(obj):
print(f"Found bad value at {path}: {obj!r}")
class APIAlertsStreamHandler(tornado_eventsource.handler.EventSourceHandler): class APIAlertsStreamHandler(tornado_eventsource.handler.EventSourceHandler):
"""API request handler for /api/v2/alerts/stream""" """API request handler for /api/v2/alerts/stream"""
@@ -116,8 +105,8 @@ class APIAlertsStreamHandler(tornado_eventsource.handler.EventSourceHandler):
# argument. # argument.
self._sse_alert_broadcaster.register(self) self._sse_alert_broadcaster.register(self)
except Exception as e: except Exception:
logging.warning("Exception when serving SSE socket: %s", e, exc_info=True) logging.exception("Exception when serving SSE socket")
self.close() self.close()
def close(self): def close(self):
@@ -135,8 +124,8 @@ class APIAlertsStreamHandler(tornado_eventsource.handler.EventSourceHandler):
alert = copy.deepcopy(alert) alert = copy.deepcopy(alert)
alert.infer_missing(self._credentials) alert.infer_missing(self._credentials)
self.write_message(msg=safe_json_dumps(alert)) self.write_message(msg=safe_json_dumps(alert))
except Exception as e: except Exception:
logging.warning("Exception in SSE callback, connection will be closed: %s", e, exc_info=True) logging.exception("Exception in SSE callback, connection will be closed")
self.close() self.close()
+2 -2
View File
@@ -59,7 +59,7 @@ class APIDxStatsHandler(tornado.web.RequestHandler):
self.set_header("Cache-Control", "no-store") self.set_header("Cache-Control", "no-store")
self.set_header("Content-Type", "application/json") self.set_header("Content-Type", "application/json")
except Exception as e: except Exception:
logging.error("Exception when handling client request to dx stats API: %s", e, exc_info=True) logging.exception("Exception when handling client request to dx stats API")
self.write(safe_json_dumps("Error - an internal server error occurred.")) self.write(safe_json_dumps("Error - an internal server error occurred."))
self.set_status(500) self.set_status(500)
+6 -6
View File
@@ -56,8 +56,8 @@ class APILookupCallHandler(tornado.web.RequestHandler):
self.write(safe_json_dumps("Error - call must be provided")) self.write(safe_json_dumps("Error - call must be provided"))
self.set_status(422) self.set_status(422)
except Exception as e: except Exception:
logging.error("Exception when handling client request to call lookup API: %s", e, exc_info=True) logging.exception("Exception when handling client request to call lookup API")
self.write(safe_json_dumps("Error - an internal server error occurred.")) self.write(safe_json_dumps("Error - an internal server error occurred."))
self.set_status(500) self.set_status(500)
@@ -108,8 +108,8 @@ class APILookupSIGRefHandler(tornado.web.RequestHandler):
self.write(safe_json_dumps("Error - sig and id must be provided")) self.write(safe_json_dumps("Error - sig and id must be provided"))
self.set_status(422) self.set_status(422)
except Exception as e: except Exception:
logging.error("Exception when handling client request to sig ref lookup API: %s", e, exc_info=True) logging.exception("Exception when handling client request to sig ref lookup API")
self.write(safe_json_dumps("Error - an internal server error occurred.")) self.write(safe_json_dumps("Error - an internal server error occurred."))
self.set_status(500) self.set_status(500)
@@ -170,8 +170,8 @@ class APILookupGridHandler(tornado.web.RequestHandler):
self.write(safe_json_dumps("Error - grid must be provided")) self.write(safe_json_dumps("Error - grid must be provided"))
self.set_status(422) self.set_status(422)
except Exception as e: except Exception:
logging.error("Exception when handling client request to grid ref lookup API: %s", e, exc_info=True) logging.exception("Exception when handling client request to grid ref lookup API")
self.write(safe_json_dumps("Error - an internal server error occurred.")) self.write(safe_json_dumps("Error - an internal server error occurred."))
self.set_status(500) self.set_status(500)
+2 -2
View File
@@ -82,7 +82,7 @@ class APIOptionsHandler(tornado.web.RequestHandler):
self.set_header("Cache-Control", "no-store") self.set_header("Cache-Control", "no-store")
self.set_header("Content-Type", "application/json") self.set_header("Content-Type", "application/json")
except Exception as e: except Exception:
logging.error("Exception when handling client request to options API: %s", e, exc_info=True) logging.exception("Exception when handling client request to options API")
self.write(safe_json_dumps("Error - an internal server error occurred.")) self.write(safe_json_dumps("Error - an internal server error occurred."))
self.set_status(500) self.set_status(500)
+2 -2
View File
@@ -36,7 +36,7 @@ class APISolarConditionsHandler(tornado.web.RequestHandler):
self.set_header("Cache-Control", "no-store") self.set_header("Cache-Control", "no-store")
self.set_header("Content-Type", "application/json") self.set_header("Content-Type", "application/json")
except Exception as e: except Exception:
logging.error("Exception when handling client request to solar conditions API: %s", e, exc_info=True) logging.exception("Exception when handling client request to solar conditions API")
self.write(safe_json_dumps("Error - an internal server error occurred.")) self.write(safe_json_dumps("Error - an internal server error occurred."))
self.set_status(500) self.set_status(500)
+6 -6
View File
@@ -57,8 +57,8 @@ class APISpotsHandler(tornado.web.RequestHandler):
except ValueError as e: except ValueError as e:
self.write(safe_json_dumps("Bad request - " + str(e))) self.write(safe_json_dumps("Bad request - " + str(e)))
self.set_status(400) self.set_status(400)
except Exception as e: except Exception:
logging.error("Excedption when handling client request to spots API: %s", e, exc_info=True) logging.exception("Excedption when handling client request to spots API")
self.write(safe_json_dumps("Error - an internal server error occurred.")) self.write(safe_json_dumps("Error - an internal server error occurred."))
self.set_status(500) self.set_status(500)
self.set_header("Cache-Control", "no-store") self.set_header("Cache-Control", "no-store")
@@ -107,8 +107,8 @@ class APISpotsStreamHandler(tornado_eventsource.handler.EventSourceHandler):
# argument. # argument.
self._sse_spot_broadcaster.register(self) self._sse_spot_broadcaster.register(self)
except Exception as e: except Exception:
logging.warning("Exception when serving SSE socket: %s", e, exc_info=True) logging.exception("Exception when serving SSE socket")
self.close() self.close()
def close(self): def close(self):
@@ -127,8 +127,8 @@ class APISpotsStreamHandler(tornado_eventsource.handler.EventSourceHandler):
spot = copy.deepcopy(spot) spot = copy.deepcopy(spot)
spot.infer_missing(self._credentials) spot.infer_missing(self._credentials)
self.write_message(msg=safe_json_dumps(spot)) self.write_message(msg=safe_json_dumps(spot))
except Exception as e: except Exception:
logging.warning("Exception in SSE callback, connection will be closed: %s", e, exc_info=True) logging.exception("Exception in SSE callback, connection will be closed")
self.close() self.close()
+2 -2
View File
@@ -36,7 +36,7 @@ class APIStatusHandler(tornado.web.RequestHandler):
self.set_header("Cache-Control", "no-store") self.set_header("Cache-Control", "no-store")
self.set_header("Content-Type", "application/json") self.set_header("Content-Type", "application/json")
except Exception as e: except Exception:
logging.error("Exception when handling client request to status API: %s", e, exc_info=True) logging.exception("Exception when handling client request to status API")
self.write(safe_json_dumps("Error - an internal server error occurred.")) self.write(safe_json_dumps("Error - an internal server error occurred."))
self.set_status(500) self.set_status(500)
+2 -2
View File
@@ -125,8 +125,8 @@ class V1APISpotHandler(tornado.web.RequestHandler):
self.set_header("Cache-Control", "no-store") self.set_header("Cache-Control", "no-store")
self.set_header("Content-Type", "application/json") self.set_header("Content-Type", "application/json")
except Exception as e: except Exception:
logging.error("Exception when handling client request to add spot API: %s", e, exc_info=True) logging.exception("Exception when handling client request to add spot API")
self.write(safe_json_dumps("Error - an internal server error occurred.")) self.write(safe_json_dumps("Error - an internal server error occurred."))
self.set_status(500) self.set_status(500)
self.set_header("Cache-Control", "no-store") self.set_header("Cache-Control", "no-store")
+10 -7
View File
@@ -1,5 +1,7 @@
import tornado import tornado
from tornado.httpclient import AsyncHTTPClient from tornado.httpclient import AsyncHTTPClient
from tornado.httputil import HTTPHeaders
class V1RedirectHandler(tornado.web.RequestHandler): class V1RedirectHandler(tornado.web.RequestHandler):
"""Transparently proxies requests from the old API to the new one, """Transparently proxies requests from the old API to the new one,
@@ -30,13 +32,14 @@ class V1RedirectHandler(tornado.web.RequestHandler):
raise tornado.web.HTTPError(502, reason=str(e)) raise tornado.web.HTTPError(502, reason=str(e))
self.set_status(response.code, response.reason) self.set_status(response.code, response.reason)
for name, value in response.headers.get_all(): if isinstance(response.headers, HTTPHeaders):
# Let Tornado recompute these for the outgoing response for name, value in response.headers.get_all():
if name.lower() not in ("content-length", "transfer-encoding", "connection"): # Let Tornado recompute these for the outgoing response
self.add_header(name, value) if name.lower() not in ("content-length", "transfer-encoding", "connection"):
if response.body: self.add_header(name, value)
self.write(response.body) if response.body:
self.finish() self.write(response.body)
await self.finish()
async def get(self, path): async def get(self, path):
await self._proxy(path) await self._proxy(path)
+1 -1
View File
@@ -76,7 +76,7 @@
</div> </div>
<script src="/static/js/add-spot.js?v=1786774305"></script> <script src="/static/js/add-spot.js?v=1786776159"></script>
<script>$(document).ready(function () { <script>$(document).ready(function () {
$("#nav-link-add-spot").addClass("active"); $("#nav-link-add-spot").addClass("active");
}); <!-- highlight active page in nav --></script> }); <!-- highlight active page in nav --></script>
+1 -1
View File
@@ -82,7 +82,7 @@
</div> </div>
<script src="/static/js/alerts.js?v=1786774305"></script> <script src="/static/js/alerts.js?v=1786776159"></script>
<script>$(document).ready(function () { <script>$(document).ready(function () {
$("#nav-link-alerts").addClass("active"); $("#nav-link-alerts").addClass("active");
}); <!-- highlight active page in nav --></script> }); <!-- highlight active page in nav --></script>
+2 -2
View File
@@ -79,8 +79,8 @@
</div> </div>
<script src="/static/js/spotsbandsandmap.js?v=1786774305"></script> <script src="/static/js/spotsbandsandmap.js?v=1786776159"></script>
<script src="/static/js/bands.js?v=1786774305"></script> <script src="/static/js/bands.js?v=1786776159"></script>
<script>$(document).ready(function () { <script>$(document).ready(function () {
$("#nav-link-bands").addClass("active"); $("#nav-link-bands").addClass("active");
}); <!-- highlight active page in nav --></script> }); <!-- highlight active page in nav --></script>
+5 -5
View File
@@ -1,6 +1,6 @@
{% extends "skeleton.html" %} {% extends "skeleton.html" %}
{% block head_extra %} {% block head_extra %}
<link rel="stylesheet" href="/static/css/style.css?v=1786774305" type="text/css"> <link rel="stylesheet" href="/static/css/style.css?v=1786776159" type="text/css">
<link href="/static/vendor/css/bootstrap-5.3.8.min.css" rel="stylesheet"> <link href="/static/vendor/css/bootstrap-5.3.8.min.css" rel="stylesheet">
<link href="/static/vendor/css/fontawesome-6.7.2.min.css" rel="stylesheet"> <link href="/static/vendor/css/fontawesome-6.7.2.min.css" rel="stylesheet">
<link href="/static/vendor/css/solid-6.7.2.min.css" rel="stylesheet"> <link href="/static/vendor/css/solid-6.7.2.min.css" rel="stylesheet">
@@ -15,10 +15,10 @@
window.fetchEventSource = fetchEventSource; window.fetchEventSource = fetchEventSource;
</script> </script>
<script src="/static/js/utils.js?v=1786774305"></script> <script src="/static/js/utils.js?v=1786776159"></script>
<script src="/static/js/ui-ham.js?v=1786774305"></script> <script src="/static/js/ui-ham.js?v=1786776159"></script>
<script src="/static/js/geo.js?v=1786774305"></script> <script src="/static/js/geo.js?v=1786776159"></script>
<script src="/static/js/common.js?v=1786774305"></script> <script src="/static/js/common.js?v=1786776159"></script>
{% end %} {% end %}
{% block body %} {% block body %}
<div class="container"> <div class="container">
+1 -1
View File
@@ -284,7 +284,7 @@
</div> </div>
<script src="/static/vendor/js/chart-4.4.9.umd.min.js"></script> <script src="/static/vendor/js/chart-4.4.9.umd.min.js"></script>
<script src="/static/js/conditions.js?v=1786774305"></script> <script src="/static/js/conditions.js?v=1786776159"></script>
<script>$(document).ready(function () { <script>$(document).ready(function () {
$("#nav-link-conditions").addClass("active"); $("#nav-link-conditions").addClass("active");
}); <!-- highlight active page in nav --></script> }); <!-- highlight active page in nav --></script>
+2 -2
View File
@@ -112,8 +112,8 @@
<script src="/static/vendor/js/leaflet-cqzones.js"></script> <script src="/static/vendor/js/leaflet-cqzones.js"></script>
<script src="/static/vendor/js/leaflet-workedallbritainireland.js" type="module"></script> <script src="/static/vendor/js/leaflet-workedallbritainireland.js" type="module"></script>
<script src="/static/js/spotsbandsandmap.js?v=1786774305"></script> <script src="/static/js/spotsbandsandmap.js?v=1786776159"></script>
<script src="/static/js/map.js?v=1786774305"></script> <script src="/static/js/map.js?v=1786776159"></script>
<script>$(document).ready(function () { <script>$(document).ready(function () {
$("#nav-link-map").addClass("active"); $("#nav-link-map").addClass("active");
}); <!-- highlight active page in nav --></script> }); <!-- highlight active page in nav --></script>
+2 -2
View File
@@ -118,8 +118,8 @@
</div> </div>
<script src="/static/js/spotsbandsandmap.js?v=1786774305"></script> <script src="/static/js/spotsbandsandmap.js?v=1786776159"></script>
<script src="/static/js/spots.js?v=1786774305"></script> <script src="/static/js/spots.js?v=1786776159"></script>
<script>$(document).ready(function () { <script>$(document).ready(function () {
$("#nav-link-spots").addClass("active"); $("#nav-link-spots").addClass("active");
}); <!-- highlight active page in nav --></script> }); <!-- highlight active page in nav --></script>
+1 -1
View File
@@ -86,7 +86,7 @@
</div> </div>
</div> </div>
<script src="/static/js/status.js?v=1786774305"></script> <script src="/static/js/status.js?v=1786776159"></script>
<script> <script>
$(document).ready(function () { $(document).ready(function () {
$("#nav-link-status").addClass("active"); $("#nav-link-status").addClass("active");