Fix static analysis issues

This commit is contained in:
Ian Renton
2026-02-27 20:33:45 +00:00
parent 6982354364
commit 3792e9f4d9
17 changed files with 36 additions and 38 deletions

View File

@@ -10,7 +10,8 @@ if not os.path.isfile("config.yml"):
exit() exit()
# Load config # Load config
config = yaml.safe_load(open("config.yml")) with open("config.yml") as f:
config = yaml.safe_load(f)
logging.info("Loaded config.") logging.info("Loaded config.")
MAX_SPOT_AGE = config["max-spot-age-sec"] MAX_SPOT_AGE = config["max-spot-age-sec"]
@@ -23,7 +24,7 @@ WEB_UI_OPTIONS = config["web-ui-options"]
# For ease of config, each spot provider owns its own config about whether it should be enabled by default in the web UI # For ease of config, each spot provider owns its own config about whether it should be enabled by default in the web UI
# but for consistency we provide this to the front-end in web-ui-options because it has no impact outside of the web UI. # but for consistency we provide this to the front-end in web-ui-options because it has no impact outside of the web UI.
WEB_UI_OPTIONS["spot-providers-enabled-by-default"] = [p["name"] for p in config["spot-providers"] if p["enabled"] and ( WEB_UI_OPTIONS["spot-providers-enabled-by-default"] = [p["name"] for p in config["spot-providers"] if p["enabled"] and (
"enabled-by-default-in-web-ui" not in p or p["enabled-by-default-in-web-ui"] == True)] "enabled-by-default-in-web-ui" not in p or p["enabled-by-default-in-web-ui"])]
# If spotting to this server is enabled, "API" is another valid spot source even though it does not come from # If spotting to this server is enabled, "API" is another valid spot source even though it does not come from
# one of our proviers. We set that to also be enabled by default. # one of our proviers. We set that to also be enabled by default.
if ALLOW_SPOTTING: if ALLOW_SPOTTING:

View File

@@ -19,7 +19,7 @@ SIGS = [
SIG(name="WWBOTA", description="Worldwide Bunkers on the Air", ref_regex=r"B\/[A-Z0-9]{1,3}\-\d{3,4}"), SIG(name="WWBOTA", description="Worldwide Bunkers on the Air", ref_regex=r"B\/[A-Z0-9]{1,3}\-\d{3,4}"),
SIG(name="HEMA", description="HuMPs Excluding Marilyns Award", ref_regex=r"[A-Z0-9]{1,3}\/[A-Z]{3}\-\d{3}"), SIG(name="HEMA", description="HuMPs Excluding Marilyns Award", ref_regex=r"[A-Z0-9]{1,3}\/[A-Z]{3}\-\d{3}"),
SIG(name="IOTA", description="Islands on the Air", ref_regex=r"[A-Z]{2}\-\d{3}"), SIG(name="IOTA", description="Islands on the Air", ref_regex=r"[A-Z]{2}\-\d{3}"),
SIG(name="MOTA", description="Mills on the Air", ref_regex=r"X\d{4-6}"), SIG(name="MOTA", description="Mills on the Air", ref_regex=r"X\d{4,6}"),
SIG(name="ARLHS", description="Amateur Radio Lighthouse Society", ref_regex=r"[A-Z]{3}\-\d{3,4}"), SIG(name="ARLHS", description="Amateur Radio Lighthouse Society", ref_regex=r"[A-Z]{3}\-\d{3,4}"),
SIG(name="ILLW", description="International Lighthouse & Lightship Weekend", ref_regex=r"[A-Z]{2}\d{4}"), SIG(name="ILLW", description="International Lighthouse & Lightship Weekend", ref_regex=r"[A-Z]{2}\d{4}"),
SIG(name="SIOTA", description="Silos on the Air", ref_regex=r"[A-Z]{2}\-[A-Z]{3}\d"), SIG(name="SIOTA", description="Silos on the Air", ref_regex=r"[A-Z]{2}\-[A-Z]{3}\d"),

View File

@@ -103,7 +103,7 @@ class LookupHelper:
logging.error("Could not download DXCC data, flags and similar data may be missing!") logging.error("Could not download DXCC data, flags and similar data may be missing!")
# Precompile regex matches for DXCCs to improve efficiency when iterating through them # Precompile regex matches for DXCCs to improve efficiency when iterating through them
for dxcc in self._dxcc_data.values(): for dxcc in (self._dxcc_data.values() if self._dxcc_data else []):
dxcc["_prefixRegexCompiled"] = re.compile(dxcc["prefixRegex"]) dxcc["_prefixRegexCompiled"] = re.compile(dxcc["prefixRegex"])
def _download_country_files_cty_plist(self): def _download_country_files_cty_plist(self):

View File

@@ -86,6 +86,6 @@ class StatusReporter:
"page_access_count": self._web_server.web_server_metrics["page_access_counter"]} "page_access_count": self._web_server.web_server_metrics["page_access_counter"]}
# Update Prometheus metrics # Update Prometheus metrics
memory_use_gauge.set(psutil.Process(os.getpid()).memory_info().rss * 1024) memory_use_gauge.set(psutil.Process(os.getpid()).memory_info().rss)
spots_gauge.set(len(self._spots)) spots_gauge.set(len(self._spots))
alerts_gauge.set(len(self._alerts)) alerts_gauge.set(len(self._alerts))

View File

@@ -155,8 +155,8 @@ def alert_allowed_by_query(alert, query):
# Check the duration if end_time is provided. If end_time is not provided, assume the activation is # Check the duration if end_time is provided. If end_time is not provided, assume the activation is
# "short", i.e. it always passes this check. If dxpeditions_skip_max_duration_check is true and # "short", i.e. it always passes this check. If dxpeditions_skip_max_duration_check is true and
# the alert is a dxpedition, it also always passes the check. # the alert is a dxpedition, it also always passes the check.
if alert.is_dxpedition and (bool(query.get( if alert.is_dxpedition and (query.get(
"dxpeditions_skip_max_duration_check")) if "dxpeditions_skip_max_duration_check" in query.keys() else False): "dxpeditions_skip_max_duration_check").upper() == "TRUE" if "dxpeditions_skip_max_duration_check" in query.keys() else False):
continue continue
if alert.end_time and alert.start_time and alert.end_time - alert.start_time > max_duration: if alert.end_time and alert.start_time and alert.end_time - alert.start_time > max_duration:
return False return False

View File

@@ -241,7 +241,7 @@ def spot_allowed_by_query(spot, query):
case "allow_qrt": case "allow_qrt":
# If false, spots that are flagged as QRT are not returned. # If false, spots that are flagged as QRT are not returned.
prevent_qrt = query.get(k).upper() == "FALSE" prevent_qrt = query.get(k).upper() == "FALSE"
if prevent_qrt and spot.qrt and spot.qrt == True: if prevent_qrt and spot.qrt:
return False return False
case "needs_good_location": case "needs_good_location":
# If true, spots require a "good" location to be returned # If true, spots require a "good" location to be returned

View File

@@ -16,13 +16,11 @@ class DXCluster(SpotProvider):
"""Spot provider for a DX Cluster. Hostname, port, login_prompt, login_callsign and allow_rbn_spots are provided in config. """Spot provider for a DX Cluster. Hostname, port, login_prompt, login_callsign and allow_rbn_spots are provided in config.
See config-example.yml for examples.""" See config-example.yml for examples."""
_CALLSIGN_PATTERN = "([a-z|0-9|/]+)"
_FREQUENCY_PATTERN = "([0-9|.]+)"
_LINE_PATTERN_EXCLUDE_RBN = re.compile( _LINE_PATTERN_EXCLUDE_RBN = re.compile(
"^DX de " + _CALLSIGN_PATTERN + ":\\s+" + _FREQUENCY_PATTERN + "\\s+" + _CALLSIGN_PATTERN + "\\s+(.*)\\s+(\\d{4}Z)", r"^DX de ([a-z0-9/]+):\s+([0-9.]+)\s+([a-z0-9/]+)\s+(.*)\s+(\d{4}Z)",
re.IGNORECASE) re.IGNORECASE)
_LINE_PATTERN_ALLOW_RBN = re.compile( _LINE_PATTERN_ALLOW_RBN = re.compile(
"^DX de " + _CALLSIGN_PATTERN + "-?#?:\\s+" + _FREQUENCY_PATTERN + "\\s+" + _CALLSIGN_PATTERN + "\\s+(.*)\\s+(\\d{4}Z)", r"^DX de ([a-z0-9/]+)-?#?:\s+([0-9.]+)\s+([a-z0-9/]+)\s+(.*)\s+(\d{4}Z)",
re.IGNORECASE) re.IGNORECASE)
def __init__(self, provider_config): def __init__(self, provider_config):
@@ -74,7 +72,7 @@ class DXCluster(SpotProvider):
match = self._spot_line_pattern.match(telnet_output.decode("latin-1")) match = self._spot_line_pattern.match(telnet_output.decode("latin-1"))
if match: if match:
spot_time = datetime.strptime(match.group(5), "%H%MZ") spot_time = datetime.strptime(match.group(5), "%H%MZ")
spot_datetime = datetime.combine(datetime.today(), spot_time.time()).replace(tzinfo=pytz.UTC) spot_datetime = datetime.combine(datetime.now(pytz.UTC).date(), spot_time.time(), tzinfo=pytz.UTC)
spot = Spot(source=self.name, spot = Spot(source=self.name,
dx_call=match.group(3), dx_call=match.group(3),
de_call=match.group(1), de_call=match.group(1),

View File

@@ -16,10 +16,8 @@ class RBN(SpotProvider):
"""Spot provider for the Reverse Beacon Network. Connects to a single port, if you want both CW/RTTY (port 7000) and FT8 """Spot provider for the Reverse Beacon Network. Connects to a single port, if you want both CW/RTTY (port 7000) and FT8
(port 7001) you need to instantiate two copies of this. The port is provided as an argument to the constructor.""" (port 7001) you need to instantiate two copies of this. The port is provided as an argument to the constructor."""
_CALLSIGN_PATTERN = "([a-z|0-9|/]+)"
_FREQUENCY_PATTERM = "([0-9|.]+)"
_LINE_PATTERN = re.compile( _LINE_PATTERN = re.compile(
"^DX de " + _CALLSIGN_PATTERN + "-.*:\\s+" + _FREQUENCY_PATTERM + "\\s+" + _CALLSIGN_PATTERN + "\\s+(.*)\\s+(\\d{4}Z)", r"^DX de ([a-z0-9/]+)-.*:\s+([0-9.]+)\s+([a-z0-9/]+)\s+(.*)\s+(\d{4}Z)",
re.IGNORECASE) re.IGNORECASE)
def __init__(self, provider_config): def __init__(self, provider_config):
@@ -65,7 +63,7 @@ class RBN(SpotProvider):
match = self._LINE_PATTERN.match(telnet_output.decode("latin-1")) match = self._LINE_PATTERN.match(telnet_output.decode("latin-1"))
if match: if match:
spot_time = datetime.strptime(match.group(5), "%H%MZ") spot_time = datetime.strptime(match.group(5), "%H%MZ")
spot_datetime = datetime.combine(datetime.today(), spot_time.time()).replace(tzinfo=pytz.UTC) spot_datetime = datetime.combine(datetime.now(pytz.UTC).date(), spot_time.time(), tzinfo=pytz.UTC)
spot = Spot(source=self.name, spot = Spot(source=self.name,
dx_call=match.group(3), dx_call=match.group(3),
de_call=match.group(1), de_call=match.group(1),

View File

@@ -44,6 +44,7 @@ class SpotProvider:
# Fill in any blanks and add to the list # Fill in any blanks and add to the list
spot.infer_missing() spot.infer_missing()
self._add_spot(spot) self._add_spot(spot)
if spots:
self.last_spot_time = datetime.fromtimestamp(max(map(lambda s: s.time, spots)), pytz.UTC) self.last_spot_time = datetime.fromtimestamp(max(map(lambda s: s.time, spots)), pytz.UTC)
def _submit(self, spot): def _submit(self, spot):

View File

@@ -66,7 +66,7 @@
<p>This software is dedicated to the memory of Tom G1PJB, SK, a friend and colleague who sadly passed away around the time I started writing it in Autumn 2025. I was looking forward to showing it to you when it was done.</p> <p>This software is dedicated to the memory of Tom G1PJB, SK, a friend and colleague who sadly passed away around the time I started writing it in Autumn 2025. I was looking forward to showing it to you when it was done.</p>
</div> </div>
<script src="/js/common.js?v=1772219824"></script> <script src="/js/common.js?v=1772224426"></script>
<script>$(document).ready(function() { $("#nav-link-about").addClass("active"); }); <!-- highlight active page in nav --></script> <script>$(document).ready(function() { $("#nav-link-about").addClass("active"); }); <!-- highlight active page in nav --></script>
{% end %} {% end %}

View File

@@ -69,8 +69,8 @@
</div> </div>
<script src="/js/common.js?v=1772219824"></script> <script src="/js/common.js?v=1772224426"></script>
<script src="/js/add-spot.js?v=1772219824"></script> <script src="/js/add-spot.js?v=1772224426"></script>
<script>$(document).ready(function() { $("#nav-link-add-spot").addClass("active"); }); <!-- highlight active page in nav --></script> <script>$(document).ready(function() { $("#nav-link-add-spot").addClass("active"); }); <!-- highlight active page in nav --></script>
{% end %} {% end %}

View File

@@ -56,8 +56,8 @@
</div> </div>
<script src="/js/common.js?v=1772219824"></script> <script src="/js/common.js?v=1772224426"></script>
<script src="/js/alerts.js?v=1772219824"></script> <script src="/js/alerts.js?v=1772224426"></script>
<script>$(document).ready(function() { $("#nav-link-alerts").addClass("active"); }); <!-- highlight active page in nav --></script> <script>$(document).ready(function() { $("#nav-link-alerts").addClass("active"); }); <!-- highlight active page in nav --></script>
{% end %} {% end %}

View File

@@ -62,9 +62,9 @@
<script> <script>
let spotProvidersEnabledByDefault = {% raw json_encode(web_ui_options["spot-providers-enabled-by-default"]) %}; let spotProvidersEnabledByDefault = {% raw json_encode(web_ui_options["spot-providers-enabled-by-default"]) %};
</script> </script>
<script src="/js/common.js?v=1772219824"></script> <script src="/js/common.js?v=1772224426"></script>
<script src="/js/spotsbandsandmap.js?v=1772219824"></script> <script src="/js/spotsbandsandmap.js?v=1772224426"></script>
<script src="/js/bands.js?v=1772219824"></script> <script src="/js/bands.js?v=1772224426"></script>
<script>$(document).ready(function() { $("#nav-link-bands").addClass("active"); }); <!-- highlight active page in nav --></script> <script>$(document).ready(function() { $("#nav-link-bands").addClass("active"); }); <!-- highlight active page in nav --></script>
{% end %} {% end %}

View File

@@ -46,10 +46,10 @@
crossorigin="anonymous"></script> crossorigin="anonymous"></script>
<script src="https://cdn.jsdelivr.net/npm/tinycolor2@1.6.0/cjs/tinycolor.min.js"></script> <script src="https://cdn.jsdelivr.net/npm/tinycolor2@1.6.0/cjs/tinycolor.min.js"></script>
<script src="https://misc.ianrenton.com/jsutils/utils.js?v=1772219824"></script> <script src="https://misc.ianrenton.com/jsutils/utils.js?v=1772224426"></script>
<script src="https://misc.ianrenton.com/jsutils/storage.js?v=1772219824"></script> <script src="https://misc.ianrenton.com/jsutils/storage.js?v=1772224426"></script>
<script src="https://misc.ianrenton.com/jsutils/ui-ham.js?v=1772219824"></script> <script src="https://misc.ianrenton.com/jsutils/ui-ham.js?v=1772224426"></script>
<script src="https://misc.ianrenton.com/jsutils/geo.js?v=1772219824"></script> <script src="https://misc.ianrenton.com/jsutils/geo.js?v=1772224426"></script>
</head> </head>
<body> <body>

View File

@@ -70,9 +70,9 @@
<script> <script>
let spotProvidersEnabledByDefault = {% raw json_encode(web_ui_options["spot-providers-enabled-by-default"]) %}; let spotProvidersEnabledByDefault = {% raw json_encode(web_ui_options["spot-providers-enabled-by-default"]) %};
</script> </script>
<script src="/js/common.js?v=1772219824"></script> <script src="/js/common.js?v=1772224426"></script>
<script src="/js/spotsbandsandmap.js?v=1772219824"></script> <script src="/js/spotsbandsandmap.js?v=1772224426"></script>
<script src="/js/map.js?v=1772219824"></script> <script src="/js/map.js?v=1772224426"></script>
<script>$(document).ready(function() { $("#nav-link-map").addClass("active"); }); <!-- highlight active page in nav --></script> <script>$(document).ready(function() { $("#nav-link-map").addClass("active"); }); <!-- highlight active page in nav --></script>
{% end %} {% end %}

View File

@@ -87,9 +87,9 @@
<script> <script>
let spotProvidersEnabledByDefault = {% raw json_encode(web_ui_options["spot-providers-enabled-by-default"]) %}; let spotProvidersEnabledByDefault = {% raw json_encode(web_ui_options["spot-providers-enabled-by-default"]) %};
</script> </script>
<script src="/js/common.js?v=1772219824"></script> <script src="/js/common.js?v=1772224426"></script>
<script src="/js/spotsbandsandmap.js?v=1772219824"></script> <script src="/js/spotsbandsandmap.js?v=1772224426"></script>
<script src="/js/spots.js?v=1772219824"></script> <script src="/js/spots.js?v=1772224426"></script>
<script>$(document).ready(function() { $("#nav-link-spots").addClass("active"); }); <!-- highlight active page in nav --></script> <script>$(document).ready(function() { $("#nav-link-spots").addClass("active"); }); <!-- highlight active page in nav --></script>
{% end %} {% end %}

View File

@@ -3,8 +3,8 @@
<div id="status-container" class="row row-cols-1 row-cols-md-4 g-4 mt-4"></div> <div id="status-container" class="row row-cols-1 row-cols-md-4 g-4 mt-4"></div>
<script src="/js/common.js?v=1772219824"></script> <script src="/js/common.js?v=1772224426"></script>
<script src="/js/status.js?v=1772219824"></script> <script src="/js/status.js?v=1772224426"></script>
<script>$(document).ready(function() { $("#nav-link-status").addClass("active"); }); <!-- highlight active page in nav --></script> <script>$(document).ready(function() { $("#nav-link-status").addClass("active"); }); <!-- highlight active page in nav --></script>
{% end %} {% end %}