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
+1 -1
View File
@@ -29,7 +29,7 @@ class AlertProvider:
# Sort the batch so that earliest ones go in first. This helps keep the ordering correct when alerts are fired
# off to SSE listeners.
alerts = sorted(alerts, key=lambda a: (a.start_time if a and a.start_time else 0))
alerts = sorted(alerts, key=lambda a: a.start_time if a and a.start_time else 0)
for alert in alerts:
# Fill in any blanks and add to the list
alert.infer_missing()
+16 -14
View File
@@ -3,9 +3,9 @@ from datetime import datetime, timedelta
import pytz
from bs4 import BeautifulSoup
from providers.alert.http_alert_provider import HTTPAlertProvider
from data.alert import Alert
from data.sig_ref import SIGRef
from providers.alert.http_alert_provider import HTTPAlertProvider
class BOTA(HTTPAlertProvider):
@@ -23,17 +23,17 @@ class BOTA(HTTPAlertProvider):
bs = BeautifulSoup(http_response.content.decode("utf-8-sig"), features="lxml")
if not bs.body:
return new_alerts
div = bs.body.find('div', attrs={'class': 'view-activations-public'})
div = bs.body.find("div", attrs={"class": "view-activations-public"})
if div:
table = div.find('table', attrs={'class': 'views-table'})
table = div.find("table", attrs={"class": "views-table"})
if table:
tbody = table.find('tbody')
tbody = table.find("tbody")
if not tbody:
return new_alerts
for row in tbody.find_all('tr'):
cells = row.find_all('td')
first_cell_anchor = cells[0].find('a') if len(cells) > 0 else None
second_cell_anchor = cells[1].find('a') if len(cells) > 1 else None
for row in tbody.find_all("tr"):
cells = row.find_all("td")
first_cell_anchor = cells[0].find("a") if len(cells) > 0 else None
second_cell_anchor = cells[1].find("a") if len(cells) > 1 else None
if not first_cell_anchor or not second_cell_anchor:
continue
first_cell_text = first_cell_anchor.get_text().strip()
@@ -41,7 +41,7 @@ class BOTA(HTTPAlertProvider):
dx_call = second_cell_anchor.get_text().strip().upper()
# Get the date, dealing with the fact we get no year so have to figure out if it's last year or next year
date_span = cells[2].find('span') if len(cells) > 2 else None
date_span = cells[2].find("span") if len(cells) > 2 else None
if not date_span:
continue
date_text = date_span.get_text().strip()
@@ -52,11 +52,13 @@ class BOTA(HTTPAlertProvider):
date_time = date_time.replace(year=datetime.now(pytz.UTC).year + 1)
# Convert to our alert format
alert = Alert(source=self.name,
dx_calls=[dx_call],
sig_refs=[SIGRef(id=ref_name, sig="BOTA")],
start_time=date_time.timestamp(),
is_dxpedition=False)
alert = Alert(
source=self.name,
dx_calls=[dx_call],
sig_refs=[SIGRef(id=ref_name, sig="BOTA")],
start_time=date_time.timestamp(),
is_dxpedition=False,
)
new_alerts.append(alert)
return new_alerts
+3 -3
View File
@@ -1,13 +1,13 @@
import logging
from datetime import datetime
from threading import Thread, Event
from threading import Event, Thread
import pytz
import requests
from requests.exceptions import ConnectionError, ReadTimeout, ConnectTimeout
from requests.exceptions import ConnectionError, ConnectTimeout, ReadTimeout
from providers.alert.alert_provider import AlertProvider
from core.constants import HTTP_HEADERS
from providers.alert.alert_provider import AlertProvider
class HTTPAlertProvider(AlertProvider):
+21 -14
View File
@@ -6,8 +6,8 @@ import pytz
from rss_parser import Parser
from rss_parser.models.rss import RSS
from providers.alert.http_alert_provider import HTTPAlertProvider
from data.alert import Alert
from providers.alert.http_alert_provider import HTTPAlertProvider
class NG3K(HTTPAlertProvider):
@@ -49,11 +49,16 @@ class NG3K(HTTPAlertProvider):
end_day = end_string.split(", ")[0].strip()
end_mon = start_mon
start_timestamp = datetime.strptime(f"{start_year} {start_mon} {start_day}", "%Y %b %d").replace(
tzinfo=pytz.UTC).timestamp()
end_timestamp = datetime.strptime(f"{end_year} {end_mon} {end_day} 23:59",
"%Y %b %d %H:%M").replace(
tzinfo=pytz.UTC).timestamp()
start_timestamp = (
datetime.strptime(f"{start_year} {start_mon} {start_day}", "%Y %b %d")
.replace(tzinfo=pytz.UTC)
.timestamp()
)
end_timestamp = (
datetime.strptime(f"{end_year} {end_mon} {end_day} 23:59", "%Y %b %d %H:%M")
.replace(tzinfo=pytz.UTC)
.timestamp()
)
# Sometimes the DX callsign is "real", sometimes you just get a prefix with the real working callsigns being
# provided in the "by" field. e.g. call="JW", by="By LA7XK as JW7XK, LA6VM as JW6VM, LA9DL as JW9DL". So
@@ -75,14 +80,16 @@ class NG3K(HTTPAlertProvider):
comment = extra_parts[3] if len(extra_parts) > 3 else ""
# Convert to our alert format
alert = Alert(source=self.name,
dx_calls=dx_calls,
dx_country=dx_country,
freqs_modes=bands + (f"; {modes}" if modes != "" else ""),
comment=f"{by}; {comment}; {qsl_info}",
start_time=start_timestamp,
end_time=end_timestamp,
is_dxpedition=True)
alert = Alert(
source=self.name,
dx_calls=dx_calls,
dx_country=dx_country,
freqs_modes=bands + (f"; {modes}" if modes != "" else ""),
comment=f"{by}; {comment}; {qsl_info}",
start_time=start_timestamp,
end_time=end_timestamp,
is_dxpedition=True,
)
# Add to our list.
new_alerts.append(alert)
+25 -12
View File
@@ -3,9 +3,9 @@ from datetime import datetime
import pytz
from providers.alert.http_alert_provider import HTTPAlertProvider
from data.alert import Alert
from data.sig_ref import SIGRef
from providers.alert.http_alert_provider import HTTPAlertProvider
class ParksNPeaks(HTTPAlertProvider):
@@ -30,8 +30,9 @@ class ParksNPeaks(HTTPAlertProvider):
else:
sig_ref = source_alert["WWFFID"]
sig_ref_name = source_alert["Location"]
start_time = datetime.strptime(source_alert["alTime"], "%Y-%m-%d %H:%M:%S").replace(
tzinfo=pytz.UTC).timestamp()
start_time = (
datetime.strptime(source_alert["alTime"], "%Y-%m-%d %H:%M:%S").replace(tzinfo=pytz.UTC).timestamp()
)
sigrefs = []
# PnP can give us an alert of class "QRP" which is the only one that's not a real SIG in Spothole's list,
@@ -40,17 +41,29 @@ class ParksNPeaks(HTTPAlertProvider):
sigrefs = [SIGRef(id=sig_ref, sig=sig, name=sig_ref_name)]
# Convert to our alert format
alert = Alert(source=self.name,
source_id=source_alert["alID"],
dx_calls=[source_alert["CallSign"].upper()],
freqs_modes=f"{source_alert['Freq']} {source_alert['MODE']}",
comment=source_alert["Comments"],
sig_refs=sigrefs,
start_time=start_time,
is_dxpedition=False)
alert = Alert(
source=self.name,
source_id=source_alert["alID"],
dx_calls=[source_alert["CallSign"].upper()],
freqs_modes=f"{source_alert['Freq']} {source_alert['MODE']}",
comment=source_alert["Comments"],
sig_refs=sigrefs,
start_time=start_time,
is_dxpedition=False,
)
# Log a warning for the developer if PnP gives us an unknown programme we've never seen before
if sig and sig not in ["POTA", "SOTA", "WWFF", "SIOTA", "ZLOTA", "KRMNPA", "SANPCPA", "LLOTA", "QRP"]:
if sig and sig not in [
"POTA",
"SOTA",
"WWFF",
"SIOTA",
"ZLOTA",
"KRMNPA",
"SANPCPA",
"LLOTA",
"QRP",
]:
logging.warning(f"PNP alert found with sig {sig}, developer needs to add support for this!")
# If this is POTA, SOTA or WWFF data we already have it through other means, so ignore. Otherwise, add to
+26 -13
View File
@@ -2,9 +2,9 @@ from datetime import datetime
import pytz
from providers.alert.http_alert_provider import HTTPAlertProvider
from data.alert import Alert
from data.sig_ref import SIGRef
from providers.alert.http_alert_provider import HTTPAlertProvider
class POTA(HTTPAlertProvider):
@@ -21,18 +21,31 @@ class POTA(HTTPAlertProvider):
# Iterate through source data
for source_alert in http_response.json():
# Convert to our alert format
alert = Alert(source=self.name,
source_id=source_alert["scheduledActivitiesId"],
dx_calls=[source_alert["activator"].upper()],
freqs_modes=source_alert["frequencies"],
comment=source_alert["comments"],
sig_refs=[SIGRef(id=source_alert["reference"], sig="POTA", name=source_alert["name"],
url=f"https://pota.app/#/park/{source_alert['reference']}")],
start_time=datetime.strptime(source_alert["startDate"] + source_alert["startTime"],
"%Y-%m-%d%H:%M").replace(tzinfo=pytz.UTC).timestamp(),
end_time=datetime.strptime(source_alert["endDate"] + source_alert["endTime"],
"%Y-%m-%d%H:%M").replace(tzinfo=pytz.UTC).timestamp(),
is_dxpedition=False)
alert = Alert(
source=self.name,
source_id=source_alert["scheduledActivitiesId"],
dx_calls=[source_alert["activator"].upper()],
freqs_modes=source_alert["frequencies"],
comment=source_alert["comments"],
sig_refs=[
SIGRef(
id=source_alert["reference"],
sig="POTA",
name=source_alert["name"],
url=f"https://pota.app/#/park/{source_alert['reference']}",
)
],
start_time=datetime.strptime(
source_alert["startDate"] + source_alert["startTime"],
"%Y-%m-%d%H:%M",
)
.replace(tzinfo=pytz.UTC)
.timestamp(),
end_time=datetime.strptime(source_alert["endDate"] + source_alert["endTime"], "%Y-%m-%d%H:%M")
.replace(tzinfo=pytz.UTC)
.timestamp(),
is_dxpedition=False,
)
# Add to our list, but exclude any old spots that POTA can sometimes give us where even the end time is
# in the past. Don't worry about de-duping, removing old alerts etc. at this point; other code will do
+21 -13
View File
@@ -2,9 +2,9 @@ from datetime import datetime
import pytz
from providers.alert.http_alert_provider import HTTPAlertProvider
from data.alert import Alert
from data.sig_ref import SIGRef
from providers.alert.http_alert_provider import HTTPAlertProvider
class SOTA(HTTPAlertProvider):
@@ -26,18 +26,26 @@ class SOTA(HTTPAlertProvider):
summit_points = None
if len(details) > 2:
summit_points = int(details[-1].split(" ")[0])
alert = Alert(source=self.name,
source_id=source_alert["id"],
dx_calls=[source_alert["activatingCallsign"].upper()],
dx_names=[source_alert["activatorName"].upper()],
freqs_modes=source_alert["frequency"],
comment=source_alert["comments"],
sig_refs=[
SIGRef(id=f"{source_alert['associationCode']}/{source_alert['summitCode']}", sig="SOTA",
name=summit_name, activation_score=summit_points)],
start_time=datetime.strptime(source_alert["dateActivated"],
"%Y-%m-%dT%H:%M:%SZ").replace(tzinfo=pytz.UTC).timestamp(),
is_dxpedition=False)
alert = Alert(
source=self.name,
source_id=source_alert["id"],
dx_calls=[source_alert["activatingCallsign"].upper()],
dx_names=[source_alert["activatorName"].upper()],
freqs_modes=source_alert["frequency"],
comment=source_alert["comments"],
sig_refs=[
SIGRef(
id=f"{source_alert['associationCode']}/{source_alert['summitCode']}",
sig="SOTA",
name=summit_name,
activation_score=summit_points,
)
],
start_time=datetime.strptime(source_alert["dateActivated"], "%Y-%m-%dT%H:%M:%SZ")
.replace(tzinfo=pytz.UTC)
.timestamp(),
is_dxpedition=False,
)
# Add to our list
new_alerts.append(alert)
+15 -10
View File
@@ -5,9 +5,9 @@ import pytz
from rss_parser import Parser as RSSParser
from rss_parser.models.rss import RSS
from providers.alert.http_alert_provider import HTTPAlertProvider
from data.alert import Alert
from data.sig_ref import SIGRef
from providers.alert.http_alert_provider import HTTPAlertProvider
class WOTA(HTTPAlertProvider):
@@ -25,9 +25,12 @@ class WOTA(HTTPAlertProvider):
rss = cast(RSS, RSSParser.parse(http_response.content.decode("utf-8-sig")))
# Iterate through source data
for source_alert in rss.channel.items:
# Reject GUID missing or zero
if not source_alert.guid or not source_alert.guid.content or source_alert.guid.content == "http://www.wota.org.uk/alerts/0":
if (
not source_alert.guid
or not source_alert.guid.content
or source_alert.guid.content == "http://www.wota.org.uk/alerts/0"
):
continue
# Pick apart the title
@@ -51,13 +54,15 @@ class WOTA(HTTPAlertProvider):
time = datetime.strptime(source_alert.pub_date.content, self.RSS_DATE_TIME_FORMAT).astimezone(pytz.UTC)
# Convert to our alert format
alert = Alert(source=self.name,
source_id=source_alert.guid.content,
dx_calls=[dx_call],
freqs_modes=freqs_modes,
comment=comment,
sig_refs=[SIGRef(id=ref, sig="WOTA", name=ref_name)] if ref else [],
start_time=time.timestamp())
alert = Alert(
source=self.name,
source_id=source_alert.guid.content,
dx_calls=[dx_call],
freqs_modes=freqs_modes,
comment=comment,
sig_refs=[SIGRef(id=ref, sig="WOTA", name=ref_name)] if ref else [],
start_time=time.timestamp(),
)
# Add to our list.
new_alerts.append(alert)
+16 -12
View File
@@ -2,9 +2,9 @@ from datetime import datetime
import pytz
from providers.alert.http_alert_provider import HTTPAlertProvider
from data.alert import Alert
from data.sig_ref import SIGRef
from providers.alert.http_alert_provider import HTTPAlertProvider
class WWFF(HTTPAlertProvider):
@@ -21,17 +21,21 @@ class WWFF(HTTPAlertProvider):
# Iterate through source data
for source_alert in http_response.json():
# Convert to our alert format
alert = Alert(source=self.name,
source_id=source_alert["id"],
dx_calls=[source_alert["activator_call"].upper()],
freqs_modes=f"{source_alert['band']} {source_alert['mode']}",
comment=source_alert["remarks"],
sig_refs=[SIGRef(id=source_alert["reference"], sig="WWFF")],
start_time=datetime.strptime(source_alert["utc_start"],
"%Y-%m-%d %H:%M:%S").replace(tzinfo=pytz.UTC).timestamp(),
end_time=datetime.strptime(source_alert["utc_end"],
"%Y-%m-%d %H:%M:%S").replace(tzinfo=pytz.UTC).timestamp(),
is_dxpedition=False)
alert = Alert(
source=self.name,
source_id=source_alert["id"],
dx_calls=[source_alert["activator_call"].upper()],
freqs_modes=f"{source_alert['band']} {source_alert['mode']}",
comment=source_alert["remarks"],
sig_refs=[SIGRef(id=source_alert["reference"], sig="WWFF")],
start_time=datetime.strptime(source_alert["utc_start"], "%Y-%m-%d %H:%M:%S")
.replace(tzinfo=pytz.UTC)
.timestamp(),
end_time=datetime.strptime(source_alert["utc_end"], "%Y-%m-%d %H:%M:%S")
.replace(tzinfo=pytz.UTC)
.timestamp(),
is_dxpedition=False,
)
# Add to our list
new_alerts.append(alert)