Use Gray instead of Black for code formatting.

The Black code formatter sucks with respect to function
declarations with a lot of params.  Completely unreadable.
This commit is contained in:
Hemna 2021-08-23 12:14:19 -04:00
parent d6643a8e96
commit e175f77347
39 changed files with 286 additions and 278 deletions

View File

@ -17,31 +17,7 @@ repos:
hooks: hooks:
- id: setup-cfg-fmt - id: setup-cfg-fmt
- repo: https://github.com/asottile/add-trailing-comma - repo: https://github.com/dizballanze/gray
rev: v2.0.2 rev: v0.10.1
hooks: hooks:
- id: add-trailing-comma - id: gray
args: [--py36-plus]
- repo: https://github.com/asottile/pyupgrade
rev: v2.7.4
hooks:
- id: pyupgrade
args:
- --py3-plus
- repo: https://github.com/pre-commit/mirrors-isort
rev: v5.7.0
hooks:
- id: isort
- repo: https://github.com/psf/black
rev: 20.8b1
hooks:
- id: black
- repo: https://gitlab.com/pycqa/flake8
rev: 3.8.4
hooks:
- id: flake8
additional_dependencies: [flake8-bugbear]

View File

@ -12,4 +12,5 @@
import pbr.version import pbr.version
__version__ = pbr.version.VersionInfo("aprsd").version_string() __version__ = pbr.version.VersionInfo("aprsd").version_string()

View File

@ -2,19 +2,17 @@ import logging
import select import select
import time import time
import aprsd
from aprsd import stats
import aprslib import aprslib
from aprslib import is_py3 from aprslib import is_py3
from aprslib.exceptions import ( from aprslib.exceptions import (
ConnectionDrop, ConnectionDrop, ConnectionError, GenericError, LoginError, ParseError,
ConnectionError,
GenericError,
LoginError,
ParseError,
UnknownFormat, UnknownFormat,
) )
import aprsd
from aprsd import stats
LOG = logging.getLogger("APRSD") LOG = logging.getLogger("APRSD")
@ -67,15 +65,15 @@ class Client:
connected = True connected = True
backoff = 1 backoff = 1
except LoginError as e: except LoginError as e:
LOG.error("Failed to login to APRS-IS Server '{}'".format(e)) LOG.error(f"Failed to login to APRS-IS Server '{e}'")
connected = False connected = False
raise e raise e
except Exception as e: except Exception as e:
LOG.error("Unable to connect to APRS-IS server. '{}' ".format(e)) LOG.error(f"Unable to connect to APRS-IS server. '{e}' ")
time.sleep(backoff) time.sleep(backoff)
backoff = backoff * 2 backoff = backoff * 2
continue continue
LOG.debug("Logging in to APRS-IS with user '%s'" % user) LOG.debug(f"Logging in to APRS-IS with user '{user}'")
return aprs_client return aprs_client
@ -99,7 +97,7 @@ class Aprsdis(aprslib.IS):
try: try:
self.sock.setblocking(0) self.sock.setblocking(0)
except OSError as e: except OSError as e:
self.logger.error("socket error when setblocking(0): %s" % str(e)) self.logger.error(f"socket error when setblocking(0): {str(e)}")
raise aprslib.ConnectionDrop("connection dropped") raise aprslib.ConnectionDrop("connection dropped")
while not self.thread_stop: while not self.thread_stop:
@ -169,14 +167,14 @@ class Aprsdis(aprslib.IS):
else: else:
server_string = e.replace("server ", "") server_string = e.replace("server ", "")
self.logger.info("Connected to {}".format(server_string)) self.logger.info(f"Connected to {server_string}")
self.server_string = server_string self.server_string = server_string
stats.APRSDStats().set_aprsis_server(server_string) stats.APRSDStats().set_aprsis_server(server_string)
if callsign == "": if callsign == "":
raise LoginError("Server responded with empty callsign???") raise LoginError("Server responded with empty callsign???")
if callsign != self.callsign: if callsign != self.callsign:
raise LoginError("Server: %s" % test) raise LoginError(f"Server: {test}")
if status != "verified," and self.passwd != "-1": if status != "verified," and self.passwd != "-1":
raise LoginError("Password is incorrect") raise LoginError("Password is incorrect")
@ -191,7 +189,7 @@ class Aprsdis(aprslib.IS):
raise raise
except Exception as e: except Exception as e:
self.close() self.close()
self.logger.error("Failed to login '{}'".format(e)) self.logger.error(f"Failed to login '{e}'")
raise LoginError("Failed to login") raise LoginError("Failed to login")
def consumer(self, callback, blocking=True, immortal=False, raw=False): def consumer(self, callback, blocking=True, immortal=False, raw=False):

View File

@ -9,11 +9,13 @@ from logging.handlers import RotatingFileHandler
import os import os
import sys import sys
import click
import click_completion
# local imports here # local imports here
import aprsd import aprsd
from aprsd import client, email, plugin, utils from aprsd import client, email, plugin, utils
import click
import click_completion
# setup the global logger # setup the global logger
# logging.basicConfig(level=logging.DEBUG) # level=10 # logging.basicConfig(level=logging.DEBUG) # level=10
@ -48,7 +50,7 @@ Available shell types:
%s %s
Default type: auto Default type: auto
""" % "\n ".join( """ % "\n ".join(
"{:<12} {}".format(k, click_completion.core.shells[k]) f"{k:<12} {click_completion.core.shells[k]}"
for k in sorted(click_completion.core.shells.keys()) for k in sorted(click_completion.core.shells.keys())
) )
@ -110,7 +112,7 @@ def install(append, case_insensitive, shell, path):
append=append, append=append,
extra_env=extra_env, extra_env=extra_env,
) )
click.echo("{} completion installed in {}".format(shell, path)) click.echo(f"{shell} completion installed in {path}")
# Setup the logging faciility # Setup the logging faciility
@ -180,10 +182,10 @@ def test_plugin(
email.CONFIG = config email.CONFIG = config
setup_logging(config, loglevel, False) setup_logging(config, loglevel, False)
LOG.info("Test APRSD PLugin version: {}".format(aprsd.__version__)) LOG.info(f"Test APRSD PLugin version: {aprsd.__version__}")
if type(message) is tuple: if type(message) is tuple:
message = " ".join(message) message = " ".join(message)
LOG.info("P'{}' F'{}' C'{}'".format(plugin_path, fromcall, message)) LOG.info(f"P'{plugin_path}' F'{fromcall}' C'{message}'")
client.Client(config) client.Client(config)
pm = plugin.PluginManager(config) pm = plugin.PluginManager(config)
@ -192,7 +194,7 @@ def test_plugin(
packet = {"from": fromcall, "message_text": message, "msgNo": 1} packet = {"from": fromcall, "message_text": message, "msgNo": 1}
reply = obj.run(packet) reply = obj.run(packet)
LOG.info("Result = '{}'".format(reply)) LOG.info(f"Result = '{reply}'")
if __name__ == "__main__": if __name__ == "__main__":

View File

@ -7,10 +7,12 @@ import re
import smtplib import smtplib
import time import time
from aprsd import messaging, stats, threads, trace
import imapclient import imapclient
from validate_email import validate_email from validate_email import validate_email
from aprsd import messaging, stats, threads, trace
LOG = logging.getLogger("APRSD") LOG = logging.getLogger("APRSD")
# This gets forced set from main.py prior to being used internally # This gets forced set from main.py prior to being used internally
@ -45,7 +47,7 @@ def _imap_connect():
) )
except (imaplib.IMAP4.error, Exception) as e: except (imaplib.IMAP4.error, Exception) as e:
msg = getattr(e, "message", repr(e)) msg = getattr(e, "message", repr(e))
LOG.error("Failed to login {}".format(msg)) LOG.error(f"Failed to login {msg}")
return return
server.select_folder("INBOX") server.select_folder("INBOX")
@ -87,7 +89,7 @@ def _smtp_connect():
LOG.error("Couldn't connect to SMTP Server") LOG.error("Couldn't connect to SMTP Server")
return return
LOG.debug("Connected to smtp host {}".format(msg)) LOG.debug(f"Connected to smtp host {msg}")
debug = CONFIG["aprsd"]["email"]["smtp"].get("debug", False) debug = CONFIG["aprsd"]["email"]["smtp"].get("debug", False)
if debug: if debug:
@ -103,7 +105,7 @@ def _smtp_connect():
LOG.error("Couldn't connect to SMTP Server") LOG.error("Couldn't connect to SMTP Server")
return return
LOG.debug("Logged into SMTP server {}".format(msg)) LOG.debug(f"Logged into SMTP server {msg}")
return server return server
@ -118,7 +120,7 @@ def validate_shortcuts(config):
) )
delete_keys = [] delete_keys = []
for key in shortcuts: for key in shortcuts:
LOG.info("Validating {}:{}".format(key, shortcuts[key])) LOG.info(f"Validating {key}:{shortcuts[key]}")
is_valid = validate_email( is_valid = validate_email(
email_address=shortcuts[key], email_address=shortcuts[key],
check_regex=True, check_regex=True,
@ -183,7 +185,7 @@ def parse_email(msgid, data, server):
from_addr = f.group(1) from_addr = f.group(1)
else: else:
from_addr = "noaddr" from_addr = "noaddr"
LOG.debug("Got a message from '{}'".format(from_addr)) LOG.debug(f"Got a message from '{from_addr}'")
try: try:
m = server.fetch([msgid], ["RFC822"]) m = server.fetch([msgid], ["RFC822"])
except Exception as e: except Exception as e:
@ -317,7 +319,7 @@ def resend_email(count, fromcall):
month = date.strftime("%B")[:3] # Nov, Mar, Apr month = date.strftime("%B")[:3] # Nov, Mar, Apr
day = date.day day = date.day
year = date.year year = date.year
today = "{}-{}-{}".format(day, month, year) today = f"{day}-{month}-{year}"
shortcuts = CONFIG["aprsd"]["email"]["shortcuts"] shortcuts = CONFIG["aprsd"]["email"]["shortcuts"]
# swap key/value # swap key/value
@ -434,7 +436,7 @@ class APRSDEmailThread(threads.APRSDThread):
month = date.strftime("%B")[:3] # Nov, Mar, Apr month = date.strftime("%B")[:3] # Nov, Mar, Apr
day = date.day day = date.day
year = date.year year = date.year
today = "{}-{}-{}".format(day, month, year) today = f"{day}-{month}-{year}"
server = None server = None
try: try:
@ -450,7 +452,7 @@ class APRSDEmailThread(threads.APRSDThread):
except Exception as e: except Exception as e:
LOG.exception("IMAP failed to search for messages since today.", e) LOG.exception("IMAP failed to search for messages since today.", e)
continue continue
LOG.debug("{} messages received today".format(len(messages))) LOG.debug(f"{len(messages)} messages received today")
try: try:
_msgs = server.fetch(messages, ["ENVELOPE"]) _msgs = server.fetch(messages, ["ENVELOPE"])

View File

@ -7,6 +7,7 @@ import time
from aprsd import utils from aprsd import utils
# command line args # command line args
parser = argparse.ArgumentParser() parser = argparse.ArgumentParser()
parser.add_argument( parser.add_argument(
@ -56,7 +57,7 @@ class MyAPRSTCPHandler(socketserver.BaseRequestHandler):
def handle(self): def handle(self):
# self.request is the TCP socket connected to the client # self.request is the TCP socket connected to the client
self.data = self.request.recv(1024).strip() self.data = self.request.recv(1024).strip()
LOG.debug("{} wrote:".format(self.client_address[0])) LOG.debug(f"{self.client_address[0]} wrote:")
LOG.debug(self.data) LOG.debug(self.data)
# just send back the same data, but upper-cased # just send back the same data, but upper-cased
self.request.sendall(self.data.upper()) self.request.sendall(self.data.upper())
@ -73,7 +74,7 @@ def main():
ip = CONFIG["aprs"]["host"] ip = CONFIG["aprs"]["host"]
port = CONFIG["aprs"]["port"] port = CONFIG["aprs"]["port"]
LOG.info("Start server listening on {}:{}".format(args.ip, args.port)) LOG.info(f"Start server listening on {args.ip}:{args.port}")
with socketserver.TCPServer((ip, port), MyAPRSTCPHandler) as server: with socketserver.TCPServer((ip, port), MyAPRSTCPHandler) as server:
server.serve_forever() server.serve_forever()

View File

@ -5,13 +5,15 @@ from logging import NullHandler
from logging.handlers import RotatingFileHandler from logging.handlers import RotatingFileHandler
import sys import sys
import aprsd
from aprsd import messaging, packets, plugin, stats, utils
import flask import flask
import flask_classful import flask_classful
from flask_httpauth import HTTPBasicAuth from flask_httpauth import HTTPBasicAuth
from werkzeug.security import check_password_hash, generate_password_hash from werkzeug.security import check_password_hash, generate_password_hash
import aprsd
from aprsd import messaging, packets, plugin, stats, utils
LOG = logging.getLogger("APRSD") LOG = logging.getLogger("APRSD")
auth = HTTPBasicAuth() auth = HTTPBasicAuth()

View File

@ -13,13 +13,15 @@ import os
import re import re
import sys import sys
# local imports here
import aprsd
from aprsd import utils
import click import click
import click_completion import click_completion
import requests import requests
# local imports here
import aprsd
from aprsd import utils
# setup the global logger # setup the global logger
# logging.basicConfig(level=logging.DEBUG) # level=10 # logging.basicConfig(level=logging.DEBUG) # level=10
LOG = logging.getLogger("APRSD") LOG = logging.getLogger("APRSD")
@ -53,7 +55,7 @@ Available shell types:
%s %s
Default type: auto Default type: auto
""" % "\n ".join( """ % "\n ".join(
"{:<12} {}".format(k, click_completion.core.shells[k]) f"{k:<12} {click_completion.core.shells[k]}"
for k in sorted(click_completion.core.shells.keys()) for k in sorted(click_completion.core.shells.keys())
) )
@ -115,7 +117,7 @@ def install(append, case_insensitive, shell, path):
append=append, append=append,
extra_env=extra_env, extra_env=extra_env,
) )
click.echo("{} completion installed in {}".format(shell, path)) click.echo(f"{shell} completion installed in {path}")
# Setup the logging faciility # Setup the logging faciility
@ -192,14 +194,14 @@ def check(loglevel, config_file, health_url, timeout):
config = utils.parse_config(config_file) config = utils.parse_config(config_file)
setup_logging(config, loglevel, False) setup_logging(config, loglevel, False)
LOG.debug("APRSD HealthCheck version: {}".format(aprsd.__version__)) LOG.debug(f"APRSD HealthCheck version: {aprsd.__version__}")
try: try:
url = health_url url = health_url
response = requests.get(url, timeout=timeout) response = requests.get(url, timeout=timeout)
response.raise_for_status() response.raise_for_status()
except Exception as ex: except Exception as ex:
LOG.error("Failed to fetch healthcheck url '{}' : '{}'".format(url, ex)) LOG.error(f"Failed to fetch healthcheck url '{url}' : '{ex}'")
sys.exit(-1) sys.exit(-1)
else: else:
stats = json.loads(response.text) stats = json.loads(response.text)
@ -212,7 +214,7 @@ def check(loglevel, config_file, health_url, timeout):
max_timeout = {"hours": 0.0, "minutes": 5, "seconds": 0} max_timeout = {"hours": 0.0, "minutes": 5, "seconds": 0}
max_delta = datetime.timedelta(**max_timeout) max_delta = datetime.timedelta(**max_timeout)
if d > max_delta: if d > max_delta:
LOG.error("Email thread is very old! {}".format(d)) LOG.error(f"Email thread is very old! {d}")
sys.exit(-1) sys.exit(-1)
aprsis_last_update = stats["stats"]["aprs-is"]["last_update"] aprsis_last_update = stats["stats"]["aprs-is"]["last_update"]
@ -221,7 +223,7 @@ def check(loglevel, config_file, health_url, timeout):
max_timeout = {"hours": 0.0, "minutes": 5, "seconds": 0} max_timeout = {"hours": 0.0, "minutes": 5, "seconds": 0}
max_delta = datetime.timedelta(**max_timeout) max_delta = datetime.timedelta(**max_timeout)
if d > max_delta: if d > max_delta:
LOG.error("APRS-IS last update is very old! {}".format(d)) LOG.error(f"APRS-IS last update is very old! {d}")
sys.exit(-1) sys.exit(-1)
sys.exit(0) sys.exit(0)

View File

@ -29,14 +29,16 @@ import signal
import sys import sys
import time import time
# local imports here
import aprsd
from aprsd import client, messaging, stats, threads, trace, utils
import aprslib import aprslib
from aprslib.exceptions import LoginError from aprslib.exceptions import LoginError
import click import click
import click_completion import click_completion
# local imports here
import aprsd
from aprsd import client, messaging, stats, threads, trace, utils
# setup the global logger # setup the global logger
# logging.basicConfig(level=logging.DEBUG) # level=10 # logging.basicConfig(level=logging.DEBUG) # level=10
LOG = logging.getLogger("APRSD") LOG = logging.getLogger("APRSD")
@ -78,7 +80,7 @@ Available shell types:
%s %s
Default type: auto Default type: auto
""" % "\n ".join( """ % "\n ".join(
"{:<12} {}".format(k, click_completion.core.shells[k]) f"{k:<12} {click_completion.core.shells[k]}"
for k in sorted(click_completion.core.shells.keys()) for k in sorted(click_completion.core.shells.keys())
) )
@ -140,7 +142,7 @@ def install(append, case_insensitive, shell, path):
append=append, append=append,
extra_env=extra_env, extra_env=extra_env,
) )
click.echo("{} completion installed in {}".format(shell, path)) click.echo(f"{shell} completion installed in {path}")
def signal_handler(sig, frame): def signal_handler(sig, frame):
@ -270,22 +272,22 @@ def listen(
messaging.CONFIG = config messaging.CONFIG = config
setup_logging(config, loglevel, quiet) setup_logging(config, loglevel, quiet)
LOG.info("APRSD TEST Started version: {}".format(aprsd.__version__)) LOG.info(f"APRSD TEST Started version: {aprsd.__version__}")
if type(command) is tuple: if type(command) is tuple:
command = " ".join(command) command = " ".join(command)
if not quiet: if not quiet:
if raw: if raw:
LOG.info("L'{}' R'{}'".format(aprs_login, raw)) LOG.info(f"L'{aprs_login}' R'{raw}'")
else: else:
LOG.info("L'{}' To'{}' C'{}'".format(aprs_login, tocallsign, command)) LOG.info(f"L'{aprs_login}' To'{tocallsign}' C'{command}'")
flat_config = utils.flatten_dict(config) flat_config = utils.flatten_dict(config)
LOG.info("Using CONFIG values:") LOG.info("Using CONFIG values:")
for x in flat_config: for x in flat_config:
if "password" in x or "aprsd.web.users.admin" in x: if "password" in x or "aprsd.web.users.admin" in x:
LOG.info("{} = XXXXXXXXXXXXXXXXXXX".format(x)) LOG.info(f"{x} = XXXXXXXXXXXXXXXXXXX")
else: else:
LOG.info("{} = {}".format(x, flat_config[x])) LOG.info(f"{x} = {flat_config[x]}")
got_ack = False got_ack = False
got_response = False got_response = False
@ -328,7 +330,7 @@ def listen(
), ),
) )
else: else:
LOG.debug("Not old enough to notify {} < {}".format(d, max_delta)) LOG.debug(f"Not old enough to notify {d} < {max_delta}")
LOG.debug("Update last seen from {}".format(packet["from"])) LOG.debug("Update last seen from {}".format(packet["from"]))
last_seen[packet["from"]] = now last_seen[packet["from"]] = now
else: else:
@ -339,7 +341,7 @@ def listen(
resp = packet.get("response", None) resp = packet.get("response", None)
if resp == "ack": if resp == "ack":
ack_num = packet.get("msgNo") ack_num = packet.get("msgNo")
LOG.info("We saw an ACK {} Ignoring".format(ack_num)) LOG.info(f"We saw an ACK {ack_num} Ignoring")
# messaging.log_packet(packet) # messaging.log_packet(packet)
got_ack = True got_ack = True
else: else:
@ -366,7 +368,7 @@ def listen(
# LOG.debug("Filter by '{}'".format(filter_str)) # LOG.debug("Filter by '{}'".format(filter_str))
# aprs_client.set_filter(filter_str) # aprs_client.set_filter(filter_str)
filter_str = "p/{}".format("/".join(watch_list)) filter_str = "p/{}".format("/".join(watch_list))
LOG.debug("Filter by '{}'".format(filter_str)) LOG.debug(f"Filter by '{filter_str}'")
aprs_client.set_filter(filter_str) aprs_client.set_filter(filter_str)
while True: while True:

View File

@ -30,25 +30,19 @@ import signal
import sys import sys
import time import time
# local imports here
import aprsd
from aprsd import (
client,
email,
flask,
messaging,
packets,
plugin,
stats,
threads,
trace,
utils,
)
import aprslib import aprslib
from aprslib.exceptions import LoginError from aprslib.exceptions import LoginError
import click import click
import click_completion import click_completion
# local imports here
import aprsd
from aprsd import (
client, email, flask, messaging, packets, plugin, stats, threads, trace,
utils,
)
# setup the global logger # setup the global logger
# logging.basicConfig(level=logging.DEBUG) # level=10 # logging.basicConfig(level=logging.DEBUG) # level=10
LOG = logging.getLogger("APRSD") LOG = logging.getLogger("APRSD")
@ -90,7 +84,7 @@ Available shell types:
%s %s
Default type: auto Default type: auto
""" % "\n ".join( """ % "\n ".join(
"{:<12} {}".format(k, click_completion.core.shells[k]) f"{k:<12} {click_completion.core.shells[k]}"
for k in sorted(click_completion.core.shells.keys()) for k in sorted(click_completion.core.shells.keys())
) )
@ -152,7 +146,7 @@ def install(append, case_insensitive, shell, path):
append=append, append=append,
extra_env=extra_env, extra_env=extra_env,
) )
click.echo("{} completion installed in {}".format(shell, path)) click.echo(f"{shell} completion installed in {path}")
def signal_handler(sig, frame): def signal_handler(sig, frame):
@ -325,14 +319,14 @@ def send_message(
messaging.CONFIG = config messaging.CONFIG = config
setup_logging(config, loglevel, quiet) setup_logging(config, loglevel, quiet)
LOG.info("APRSD Started version: {}".format(aprsd.__version__)) LOG.info(f"APRSD Started version: {aprsd.__version__}")
if type(command) is tuple: if type(command) is tuple:
command = " ".join(command) command = " ".join(command)
if not quiet: if not quiet:
if raw: if raw:
LOG.info("L'{}' R'{}'".format(aprs_login, raw)) LOG.info(f"L'{aprs_login}' R'{raw}'")
else: else:
LOG.info("L'{}' To'{}' C'{}'".format(aprs_login, tocallsign, command)) LOG.info(f"L'{aprs_login}' To'{tocallsign}' C'{command}'")
got_ack = False got_ack = False
got_response = False got_response = False
@ -343,7 +337,7 @@ def send_message(
resp = packet.get("response", None) resp = packet.get("response", None)
if resp == "ack": if resp == "ack":
ack_num = packet.get("msgNo") ack_num = packet.get("msgNo")
LOG.info("We got ack for our sent message {}".format(ack_num)) LOG.info(f"We got ack for our sent message {ack_num}")
messaging.log_packet(packet) messaging.log_packet(packet)
got_ack = True got_ack = True
else: else:
@ -471,15 +465,15 @@ def server(
LOG.warning(msg) LOG.warning(msg)
else: else:
LOG.info(msg) LOG.info(msg)
LOG.info("APRSD Started version: {}".format(aprsd.__version__)) LOG.info(f"APRSD Started version: {aprsd.__version__}")
flat_config = utils.flatten_dict(config) flat_config = utils.flatten_dict(config)
LOG.info("Using CONFIG values:") LOG.info("Using CONFIG values:")
for x in flat_config: for x in flat_config:
if "password" in x or "aprsd.web.users.admin" in x: if "password" in x or "aprsd.web.users.admin" in x:
LOG.info("{} = XXXXXXXXXXXXXXXXXXX".format(x)) LOG.info(f"{x} = XXXXXXXXXXXXXXXXXXX")
else: else:
LOG.info("{} = {}".format(x, flat_config[x])) LOG.info(f"{x} = {flat_config[x]}")
if config["aprsd"].get("trace", False): if config["aprsd"].get("trace", False):
trace.setup_tracing(["method", "api"]) trace.setup_tracing(["method", "api"])

View File

@ -11,6 +11,7 @@ import time
from aprsd import client, stats, threads, trace, utils from aprsd import client, stats, threads, trace, utils
LOG = logging.getLogger("APRSD") LOG = logging.getLogger("APRSD")
# What to return from a plugin if we have processed the message # What to return from a plugin if we have processed the message
@ -81,7 +82,7 @@ class MsgTrack:
with self.lock: with self.lock:
result = "{" result = "{"
for key in self.track.keys(): for key in self.track.keys():
result += "{}: {}, ".format(key, str(self.track[key])) result += f"{key}: {str(self.track[key])}, "
result += "}" result += "}"
return result return result
@ -105,9 +106,9 @@ class MsgTrack:
def save(self): def save(self):
"""Save any queued to disk?""" """Save any queued to disk?"""
LOG.debug("Save tracker to disk? {}".format(len(self))) LOG.debug(f"Save tracker to disk? {len(self)}")
if len(self) > 0: if len(self) > 0:
LOG.info("Saving {} tracking messages to disk".format(len(self))) LOG.info(f"Saving {len(self)} tracking messages to disk")
pickle.dump(self.dump(), open(utils.DEFAULT_SAVE_FILE, "wb+")) pickle.dump(self.dump(), open(utils.DEFAULT_SAVE_FILE, "wb+"))
else: else:
LOG.debug( LOG.debug(
@ -239,7 +240,6 @@ class Message(metaclass=abc.ABCMeta):
@abc.abstractmethod @abc.abstractmethod
def send(self): def send(self):
"""Child class must declare.""" """Child class must declare."""
pass
class RawMessage(Message): class RawMessage(Message):
@ -348,7 +348,7 @@ class TextMessage(Message):
def send(self): def send(self):
tracker = MsgTrack() tracker = MsgTrack()
tracker.add(self) tracker.add(self)
LOG.debug("Length of MsgTrack is {}".format(len(tracker))) LOG.debug(f"Length of MsgTrack is {len(tracker)}")
thread = SendMessageThread(message=self) thread = SendMessageThread(message=self)
thread.start() thread.start()
@ -370,7 +370,7 @@ class SendMessageThread(threads.APRSDThread):
def __init__(self, message): def __init__(self, message):
self.msg = message self.msg = message
name = self.msg.message[:5] name = self.msg.message[:5]
super().__init__("SendMessage-{}-{}".format(self.msg.id, name)) super().__init__(f"SendMessage-{self.msg.id}-{name}")
def loop(self): def loop(self):
"""Loop until a message is acked or it gets delayed. """Loop until a message is acked or it gets delayed.
@ -463,7 +463,7 @@ class AckMessage(Message):
) )
def send(self): def send(self):
LOG.debug("Send ACK({}:{}) to radio.".format(self.tocall, self.id)) LOG.debug(f"Send ACK({self.tocall}:{self.id}) to radio.")
thread = SendAckThread(self) thread = SendAckThread(self)
thread.start() thread.start()
@ -486,7 +486,7 @@ class AckMessage(Message):
class SendAckThread(threads.APRSDThread): class SendAckThread(threads.APRSDThread):
def __init__(self, ack): def __init__(self, ack):
self.ack = ack self.ack = ack
super().__init__("SendAck-{}".format(self.ack.id)) super().__init__(f"SendAck-{self.ack.id}")
@trace.trace @trace.trace
def loop(self): def loop(self):
@ -511,7 +511,7 @@ class SendAckThread(threads.APRSDThread):
# It's time to try to send it again # It's time to try to send it again
send_now = True send_now = True
else: else:
LOG.debug("Still wating. {}".format(delta)) LOG.debug(f"Still wating. {delta}")
else: else:
send_now = True send_now = True
@ -555,16 +555,8 @@ def log_packet(packet):
def log_message( def log_message(
header, header, raw, message, tocall=None, fromcall=None, msg_num=None,
raw, retry_number=None, ack=None, packet_type=None, uuid=None,
message,
tocall=None,
fromcall=None,
msg_num=None,
retry_number=None,
ack=None,
packet_type=None,
uuid=None,
): ):
""" """
@ -581,36 +573,36 @@ def log_message(
log_list = [""] log_list = [""]
if retry_number: if retry_number:
# LOG.info(" {} _______________(TX:{})".format(header, retry_number)) # LOG.info(" {} _______________(TX:{})".format(header, retry_number))
log_list.append(" {} _______________(TX:{})".format(header, retry_number)) log_list.append(f" {header} _______________(TX:{retry_number})")
else: else:
# LOG.info(" {} _______________".format(header)) # LOG.info(" {} _______________".format(header))
log_list.append(" {} _______________".format(header)) log_list.append(f" {header} _______________")
# LOG.info(" Raw : {}".format(raw)) # LOG.info(" Raw : {}".format(raw))
log_list.append(" Raw : {}".format(raw)) log_list.append(f" Raw : {raw}")
if packet_type: if packet_type:
# LOG.info(" Packet : {}".format(packet_type)) # LOG.info(" Packet : {}".format(packet_type))
log_list.append(" Packet : {}".format(packet_type)) log_list.append(f" Packet : {packet_type}")
if tocall: if tocall:
# LOG.info(" To : {}".format(tocall)) # LOG.info(" To : {}".format(tocall))
log_list.append(" To : {}".format(tocall)) log_list.append(f" To : {tocall}")
if fromcall: if fromcall:
# LOG.info(" From : {}".format(fromcall)) # LOG.info(" From : {}".format(fromcall))
log_list.append(" From : {}".format(fromcall)) log_list.append(f" From : {fromcall}")
if ack: if ack:
# LOG.info(" Ack : {}".format(ack)) # LOG.info(" Ack : {}".format(ack))
log_list.append(" Ack : {}".format(ack)) log_list.append(f" Ack : {ack}")
else: else:
# LOG.info(" Message : {}".format(message)) # LOG.info(" Message : {}".format(message))
log_list.append(" Message : {}".format(message)) log_list.append(f" Message : {message}")
if msg_num: if msg_num:
# LOG.info(" Msg number : {}".format(msg_num)) # LOG.info(" Msg number : {}".format(msg_num))
log_list.append(" Msg number : {}".format(msg_num)) log_list.append(f" Msg number : {msg_num}")
if uuid: if uuid:
log_list.append(" UUID : {}".format(uuid)) log_list.append(f" UUID : {uuid}")
# LOG.info(" {} _______________ Complete".format(header)) # LOG.info(" {} _______________ Complete".format(header))
log_list.append(" {} _______________ Complete".format(header)) log_list.append(f" {header} _______________ Complete")
LOG.info("\n".join(log_list)) LOG.info("\n".join(log_list))

View File

@ -5,6 +5,7 @@ import time
from aprsd import utils from aprsd import utils
LOG = logging.getLogger("APRSD") LOG = logging.getLogger("APRSD")
PACKET_TYPE_MESSAGE = "message" PACKET_TYPE_MESSAGE = "message"

View File

@ -11,6 +11,7 @@ import threading
import pluggy import pluggy
from thesmuggler import smuggle from thesmuggler import smuggle
# setup the global logger # setup the global logger
LOG = logging.getLogger("APRSD") LOG = logging.getLogger("APRSD")
@ -40,7 +41,6 @@ class APRSDCommandSpec:
@hookspec @hookspec
def run(self, packet): def run(self, packet):
"""My special little hook that you can customize.""" """My special little hook that you can customize."""
pass
class APRSDNotificationPluginBase(metaclass=abc.ABCMeta): class APRSDNotificationPluginBase(metaclass=abc.ABCMeta):
@ -70,7 +70,6 @@ class APRSDNotificationPluginBase(metaclass=abc.ABCMeta):
This will get called when a packet is seen by a callsign This will get called when a packet is seen by a callsign
registered in the watch list in the config file.""" registered in the watch list in the config file."""
pass
class APRSDMessagePluginBase(metaclass=abc.ABCMeta): class APRSDMessagePluginBase(metaclass=abc.ABCMeta):
@ -119,7 +118,6 @@ class APRSDMessagePluginBase(metaclass=abc.ABCMeta):
To reply with a message over the air, return a string To reply with a message over the air, return a string
to send. to send.
""" """
pass
class PluginManager: class PluginManager:
@ -152,7 +150,7 @@ class PluginManager:
def load_plugins_from_path(self, module_path): def load_plugins_from_path(self, module_path):
if not os.path.exists(module_path): if not os.path.exists(module_path):
LOG.error("plugin path '{}' doesn't exist.".format(module_path)) LOG.error(f"plugin path '{module_path}' doesn't exist.")
return None return None
dir_path = os.path.realpath(module_path) dir_path = os.path.realpath(module_path)
@ -163,8 +161,8 @@ class PluginManager:
for path, _subdirs, files in os.walk(dir_path): for path, _subdirs, files in os.walk(dir_path):
for name in files: for name in files:
if fnmatch.fnmatch(name, pattern): if fnmatch.fnmatch(name, pattern):
LOG.debug("MODULE? '{}' '{}'".format(name, path)) LOG.debug(f"MODULE? '{name}' '{path}'")
module = smuggle("{}/{}".format(path, name)) module = smuggle(f"{path}/{name}")
for mem_name, obj in inspect.getmembers(module): for mem_name, obj in inspect.getmembers(module):
if inspect.isclass(obj) and self.is_plugin(obj): if inspect.isclass(obj) and self.is_plugin(obj):
self.obj_list.append( self.obj_list.append(
@ -196,7 +194,7 @@ class PluginManager:
module = importlib.import_module(module_name) module = importlib.import_module(module_name)
module = importlib.reload(module) module = importlib.reload(module)
except Exception as ex: except Exception as ex:
LOG.error("Failed to load Plugin '{}' : '{}'".format(module_name, ex)) LOG.error(f"Failed to load Plugin '{module_name}' : '{ex}'")
return return
assert hasattr(module, class_name), "class {} is not in {}".format( assert hasattr(module, class_name), "class {} is not in {}".format(
@ -238,7 +236,7 @@ class PluginManager:
) )
self._pluggy_msg_pm.register(plugin_obj) self._pluggy_msg_pm.register(plugin_obj)
except Exception as ex: except Exception as ex:
LOG.exception("Couldn't load plugin '{}'".format(plugin_name), ex) LOG.exception(f"Couldn't load plugin '{plugin_name}'", ex)
def _load_notify_plugin(self, plugin_name): def _load_notify_plugin(self, plugin_name):
""" """
@ -262,7 +260,7 @@ class PluginManager:
) )
self._pluggy_notify_pm.register(plugin_obj) self._pluggy_notify_pm.register(plugin_obj)
except Exception as ex: except Exception as ex:
LOG.exception("Couldn't load plugin '{}'".format(plugin_name), ex) LOG.exception(f"Couldn't load plugin '{plugin_name}'", ex)
def reload_plugins(self): def reload_plugins(self):
with self.lock: with self.lock:

View File

@ -4,11 +4,12 @@ import logging
import requests import requests
LOG = logging.getLogger("APRSD") LOG = logging.getLogger("APRSD")
def get_aprs_fi(api_key, callsign): def get_aprs_fi(api_key, callsign):
LOG.debug("Fetch aprs.fi location for '{}'".format(callsign)) LOG.debug(f"Fetch aprs.fi location for '{callsign}'")
try: try:
url = ( url = (
"http://api.aprs.fi/api/get?" "http://api.aprs.fi/api/get?"
@ -24,13 +25,13 @@ def get_aprs_fi(api_key, callsign):
def get_weather_gov_for_gps(lat, lon): def get_weather_gov_for_gps(lat, lon):
LOG.debug("Fetch station at {}, {}".format(lat, lon)) LOG.debug(f"Fetch station at {lat}, {lon}")
try: try:
url2 = ( url2 = (
"https://forecast.weather.gov/MapClick.php?lat=%s" "https://forecast.weather.gov/MapClick.php?lat=%s"
"&lon=%s&FcstType=json" % (lat, lon) "&lon=%s&FcstType=json" % (lat, lon)
) )
LOG.debug("Fetching weather '{}'".format(url2)) LOG.debug(f"Fetching weather '{url2}'")
response = requests.get(url2) response = requests.get(url2)
except Exception as e: except Exception as e:
LOG.error(e) LOG.error(e)
@ -41,7 +42,7 @@ def get_weather_gov_for_gps(lat, lon):
def get_weather_gov_metar(station): def get_weather_gov_metar(station):
LOG.debug("Fetch metar for station '{}'".format(station)) LOG.debug(f"Fetch metar for station '{station}'")
try: try:
url = "https://api.weather.gov/stations/{}/observations/latest".format( url = "https://api.weather.gov/stations/{}/observations/latest".format(
station, station,
@ -55,7 +56,7 @@ def get_weather_gov_metar(station):
def fetch_openweathermap(api_key, lat, lon, units="metric", exclude=None): def fetch_openweathermap(api_key, lat, lon, units="metric", exclude=None):
LOG.debug("Fetch openweathermap for {}, {}".format(lat, lon)) LOG.debug(f"Fetch openweathermap for {lat}, {lon}")
if not exclude: if not exclude:
exclude = "minutely,hourly,daily,alerts" exclude = "minutely,hourly,daily,alerts"
try: try:

View File

@ -4,6 +4,7 @@ import time
from aprsd import email, messaging, plugin, trace from aprsd import email, messaging, plugin, trace
LOG = logging.getLogger("APRSD") LOG = logging.getLogger("APRSD")
@ -68,11 +69,11 @@ class EmailPlugin(plugin.APRSDMessagePluginBase):
if timedelta < 300: # five minutes if timedelta < 300: # five minutes
too_soon = 1 too_soon = 1
if not too_soon or ack == 0: if not too_soon or ack == 0:
LOG.info("Send email '{}'".format(content)) LOG.info(f"Send email '{content}'")
send_result = email.send_email(to_addr, content) send_result = email.send_email(to_addr, content)
reply = messaging.NULL_MESSAGE reply = messaging.NULL_MESSAGE
if send_result != 0: if send_result != 0:
reply = "-{} failed".format(to_addr) reply = f"-{to_addr} failed"
# messaging.send_message(fromcall, "-" + to_addr + " failed") # messaging.send_message(fromcall, "-" + to_addr + " failed")
else: else:
# clear email sent dictionary if somehow goes over 100 # clear email sent dictionary if somehow goes over 100

View File

@ -4,6 +4,7 @@ import subprocess
from aprsd import plugin, trace from aprsd import plugin, trace
LOG = logging.getLogger("APRSD") LOG = logging.getLogger("APRSD")
@ -45,7 +46,7 @@ class FortunePlugin(plugin.APRSDMessagePluginBase):
.replace("\t", " ") .replace("\t", " ")
) )
except subprocess.CalledProcessError as ex: except subprocess.CalledProcessError as ex:
reply = "Fortune command failed '{}'".format(ex.output) reply = f"Fortune command failed '{ex.output}'"
else: else:
reply = output reply = output

View File

@ -4,6 +4,7 @@ import time
from aprsd import plugin, plugin_utils, trace, utils from aprsd import plugin, plugin_utils, trace, utils
LOG = logging.getLogger("APRSD") LOG = logging.getLogger("APRSD")
@ -25,7 +26,7 @@ class LocationPlugin(plugin.APRSDMessagePluginBase):
try: try:
utils.check_config_option(self.config, ["services", "aprs.fi", "apiKey"]) utils.check_config_option(self.config, ["services", "aprs.fi", "apiKey"])
except Exception as ex: except Exception as ex:
LOG.error("Failed to find config aprs.fi:apikey {}".format(ex)) LOG.error(f"Failed to find config aprs.fi:apikey {ex}")
return "No aprs.fi apikey found" return "No aprs.fi apikey found"
api_key = self.config["services"]["aprs.fi"]["apiKey"] api_key = self.config["services"]["aprs.fi"]["apiKey"]
@ -42,10 +43,10 @@ class LocationPlugin(plugin.APRSDMessagePluginBase):
try: try:
aprs_data = plugin_utils.get_aprs_fi(api_key, searchcall) aprs_data = plugin_utils.get_aprs_fi(api_key, searchcall)
except Exception as ex: except Exception as ex:
LOG.error("Failed to fetch aprs.fi '{}'".format(ex)) LOG.error(f"Failed to fetch aprs.fi '{ex}'")
return "Failed to fetch aprs.fi location" return "Failed to fetch aprs.fi location"
LOG.debug("LocationPlugin: aprs_data = {}".format(aprs_data)) LOG.debug(f"LocationPlugin: aprs_data = {aprs_data}")
if not len(aprs_data["entries"]): if not len(aprs_data["entries"]):
LOG.error("Didn't get any entries from aprs.fi") LOG.error("Didn't get any entries from aprs.fi")
return "Failed to fetch aprs.fi location" return "Failed to fetch aprs.fi location"
@ -67,11 +68,11 @@ class LocationPlugin(plugin.APRSDMessagePluginBase):
try: try:
wx_data = plugin_utils.get_weather_gov_for_gps(lat, lon) wx_data = plugin_utils.get_weather_gov_for_gps(lat, lon)
except Exception as ex: except Exception as ex:
LOG.error("Couldn't fetch forecast.weather.gov '{}'".format(ex)) LOG.error(f"Couldn't fetch forecast.weather.gov '{ex}'")
wx_data = {"location": {"areaDescription": "Unknown Location"}} wx_data = {"location": {"areaDescription": "Unknown Location"}}
if "location" not in wx_data: if "location" not in wx_data:
LOG.error("Couldn't fetch forecast.weather.gov '{}'".format(wx_data)) LOG.error(f"Couldn't fetch forecast.weather.gov '{wx_data}'")
wx_data = {"location": {"areaDescription": "Unknown Location"}} wx_data = {"location": {"areaDescription": "Unknown Location"}}
reply = "{}: {} {}' {},{} {}h ago".format( reply = "{}: {} {}' {},{} {}h ago".format(

View File

@ -2,6 +2,7 @@ import logging
from aprsd import messaging, packets, plugin from aprsd import messaging, packets, plugin
LOG = logging.getLogger("APRSD") LOG = logging.getLogger("APRSD")
@ -40,7 +41,7 @@ class NotifySeenPlugin(plugin.APRSDNotificationPluginBase):
packet_type = packets.get_packet_type(packet) packet_type = packets.get_packet_type(packet)
# we shouldn't notify the alert user that they are online. # we shouldn't notify the alert user that they are online.
if fromcall != notify_callsign: if fromcall != notify_callsign:
return "{} was just seen by type:'{}'".format(fromcall, packet_type) return f"{fromcall} was just seen by type:'{packet_type}'"
else: else:
LOG.debug( LOG.debug(
"Not old enough to notify callsign '{}' : {} < {}".format( "Not old enough to notify callsign '{}' : {} < {}".format(

View File

@ -3,6 +3,7 @@ import time
from aprsd import plugin, trace from aprsd import plugin, trace
LOG = logging.getLogger("APRSD") LOG = logging.getLogger("APRSD")

View File

@ -4,6 +4,7 @@ import re
from aprsd import messaging, plugin, trace from aprsd import messaging, plugin, trace
LOG = logging.getLogger("APRSD") LOG = logging.getLogger("APRSD")

View File

@ -1,9 +1,11 @@
import logging import logging
import re import re
from aprsd import plugin, trace
import yfinance as yf import yfinance as yf
from aprsd import plugin, trace
LOG = logging.getLogger("APRSD") LOG = logging.getLogger("APRSD")
@ -30,7 +32,7 @@ class StockPlugin(plugin.APRSDMessagePluginBase):
reply = "No stock symbol" reply = "No stock symbol"
return reply return reply
LOG.info("Fetch stock quote for '{}'".format(stock_symbol)) LOG.info(f"Fetch stock quote for '{stock_symbol}'")
try: try:
stock = yf.Ticker(stock_symbol) stock = yf.Ticker(stock_symbol)
@ -42,8 +44,8 @@ class StockPlugin(plugin.APRSDMessagePluginBase):
) )
except Exception as e: except Exception as e:
LOG.error( LOG.error(
"Failed to fetch stock '{}' from yahoo '{}'".format(stock_symbol, e), f"Failed to fetch stock '{stock_symbol}' from yahoo '{e}'",
) )
reply = "Failed to fetch stock '{}'".format(stock_symbol) reply = f"Failed to fetch stock '{stock_symbol}'"
return reply.rstrip() return reply.rstrip()

View File

@ -2,10 +2,12 @@ import logging
import re import re
import time import time
from aprsd import fuzzyclock, plugin, plugin_utils, trace, utils
from opencage.geocoder import OpenCageGeocode from opencage.geocoder import OpenCageGeocode
import pytz import pytz
from aprsd import fuzzyclock, plugin, plugin_utils, trace, utils
LOG = logging.getLogger("APRSD") LOG = logging.getLogger("APRSD")
@ -64,7 +66,7 @@ class TimeOpenCageDataPlugin(TimePlugin):
try: try:
utils.check_config_option(self.config, ["services", "aprs.fi", "apiKey"]) utils.check_config_option(self.config, ["services", "aprs.fi", "apiKey"])
except Exception as ex: except Exception as ex:
LOG.error("Failed to find config aprs.fi:apikey {}".format(ex)) LOG.error(f"Failed to find config aprs.fi:apikey {ex}")
return "No aprs.fi apikey found" return "No aprs.fi apikey found"
api_key = self.config["services"]["aprs.fi"]["apiKey"] api_key = self.config["services"]["aprs.fi"]["apiKey"]
@ -81,7 +83,7 @@ class TimeOpenCageDataPlugin(TimePlugin):
try: try:
aprs_data = plugin_utils.get_aprs_fi(api_key, searchcall) aprs_data = plugin_utils.get_aprs_fi(api_key, searchcall)
except Exception as ex: except Exception as ex:
LOG.error("Failed to fetch aprs.fi data {}".format(ex)) LOG.error(f"Failed to fetch aprs.fi data {ex}")
return "Failed to fetch location" return "Failed to fetch location"
# LOG.debug("LocationPlugin: aprs_data = {}".format(aprs_data)) # LOG.debug("LocationPlugin: aprs_data = {}".format(aprs_data))
@ -95,7 +97,7 @@ class TimeOpenCageDataPlugin(TimePlugin):
try: try:
utils.check_config_option(self.config, "opencagedata", "apiKey") utils.check_config_option(self.config, "opencagedata", "apiKey")
except Exception as ex: except Exception as ex:
LOG.error("Failed to find config opencage:apiKey {}".format(ex)) LOG.error(f"Failed to find config opencage:apiKey {ex}")
return "No opencage apiKey found" return "No opencage apiKey found"
try: try:
@ -103,7 +105,7 @@ class TimeOpenCageDataPlugin(TimePlugin):
geocoder = OpenCageGeocode(opencage_key) geocoder = OpenCageGeocode(opencage_key)
results = geocoder.reverse_geocode(lat, lon) results = geocoder.reverse_geocode(lat, lon)
except Exception as ex: except Exception as ex:
LOG.error("Couldn't fetch opencagedata api '{}'".format(ex)) LOG.error(f"Couldn't fetch opencagedata api '{ex}'")
# Default to UTC instead # Default to UTC instead
localzone = pytz.timezone("UTC") localzone = pytz.timezone("UTC")
else: else:
@ -130,7 +132,7 @@ class TimeOWMPlugin(TimePlugin):
try: try:
utils.check_config_option(self.config, ["services", "aprs.fi", "apiKey"]) utils.check_config_option(self.config, ["services", "aprs.fi", "apiKey"])
except Exception as ex: except Exception as ex:
LOG.error("Failed to find config aprs.fi:apikey {}".format(ex)) LOG.error(f"Failed to find config aprs.fi:apikey {ex}")
return "No aprs.fi apikey found" return "No aprs.fi apikey found"
# optional second argument is a callsign to search # optional second argument is a callsign to search
@ -146,10 +148,10 @@ class TimeOWMPlugin(TimePlugin):
try: try:
aprs_data = plugin_utils.get_aprs_fi(api_key, searchcall) aprs_data = plugin_utils.get_aprs_fi(api_key, searchcall)
except Exception as ex: except Exception as ex:
LOG.error("Failed to fetch aprs.fi data {}".format(ex)) LOG.error(f"Failed to fetch aprs.fi data {ex}")
return "Failed to fetch location" return "Failed to fetch location"
LOG.debug("LocationPlugin: aprs_data = {}".format(aprs_data)) LOG.debug(f"LocationPlugin: aprs_data = {aprs_data}")
if not len(aprs_data["entries"]): if not len(aprs_data["entries"]):
LOG.error("Didn't get any entries from aprs.fi") LOG.error("Didn't get any entries from aprs.fi")
return "Failed to fetch aprs.fi location" return "Failed to fetch aprs.fi location"
@ -163,14 +165,14 @@ class TimeOWMPlugin(TimePlugin):
["services", "openweathermap", "apiKey"], ["services", "openweathermap", "apiKey"],
) )
except Exception as ex: except Exception as ex:
LOG.error("Failed to find config openweathermap:apiKey {}".format(ex)) LOG.error(f"Failed to find config openweathermap:apiKey {ex}")
return "No openweathermap apiKey found" return "No openweathermap apiKey found"
api_key = self.config["services"]["openweathermap"]["apiKey"] api_key = self.config["services"]["openweathermap"]["apiKey"]
try: try:
results = plugin_utils.fetch_openweathermap(api_key, lat, lon) results = plugin_utils.fetch_openweathermap(api_key, lat, lon)
except Exception as ex: except Exception as ex:
LOG.error("Couldn't fetch openweathermap api '{}'".format(ex)) LOG.error(f"Couldn't fetch openweathermap api '{ex}'")
# default to UTC # default to UTC
localzone = pytz.timezone("UTC") localzone = pytz.timezone("UTC")
else: else:

View File

@ -3,6 +3,7 @@ import logging
import aprsd import aprsd
from aprsd import plugin, stats, trace from aprsd import plugin, stats, trace
LOG = logging.getLogger("APRSD") LOG = logging.getLogger("APRSD")

View File

@ -2,9 +2,11 @@ import json
import logging import logging
import re import re
from aprsd import plugin, plugin_utils, trace, utils
import requests import requests
from aprsd import plugin, plugin_utils, trace, utils
LOG = logging.getLogger("APRSD") LOG = logging.getLogger("APRSD")
@ -34,14 +36,14 @@ class USWeatherPlugin(plugin.APRSDMessagePluginBase):
try: try:
utils.check_config_option(self.config, ["services", "aprs.fi", "apiKey"]) utils.check_config_option(self.config, ["services", "aprs.fi", "apiKey"])
except Exception as ex: except Exception as ex:
LOG.error("Failed to find config aprs.fi:apikey {}".format(ex)) LOG.error(f"Failed to find config aprs.fi:apikey {ex}")
return "No aprs.fi apikey found" return "No aprs.fi apikey found"
api_key = self.config["services"]["aprs.fi"]["apiKey"] api_key = self.config["services"]["aprs.fi"]["apiKey"]
try: try:
aprs_data = plugin_utils.get_aprs_fi(api_key, fromcall) aprs_data = plugin_utils.get_aprs_fi(api_key, fromcall)
except Exception as ex: except Exception as ex:
LOG.error("Failed to fetch aprs.fi data {}".format(ex)) LOG.error(f"Failed to fetch aprs.fi data {ex}")
return "Failed to fetch location" return "Failed to fetch location"
# LOG.debug("LocationPlugin: aprs_data = {}".format(aprs_data)) # LOG.debug("LocationPlugin: aprs_data = {}".format(aprs_data))
@ -51,7 +53,7 @@ class USWeatherPlugin(plugin.APRSDMessagePluginBase):
try: try:
wx_data = plugin_utils.get_weather_gov_for_gps(lat, lon) wx_data = plugin_utils.get_weather_gov_for_gps(lat, lon)
except Exception as ex: except Exception as ex:
LOG.error("Couldn't fetch forecast.weather.gov '{}'".format(ex)) LOG.error(f"Couldn't fetch forecast.weather.gov '{ex}'")
return "Unable to get weather" return "Unable to get weather"
reply = ( reply = (
@ -65,7 +67,7 @@ class USWeatherPlugin(plugin.APRSDMessagePluginBase):
wx_data["data"]["weather"][1], wx_data["data"]["weather"][1],
) )
).rstrip() ).rstrip()
LOG.debug("reply: '{}' ".format(reply)) LOG.debug(f"reply: '{reply}' ")
return reply return reply
@ -93,7 +95,7 @@ class USMetarPlugin(plugin.APRSDMessagePluginBase):
fromcall = packet.get("from") fromcall = packet.get("from")
message = packet.get("message_text", None) message = packet.get("message_text", None)
# ack = packet.get("msgNo", "0") # ack = packet.get("msgNo", "0")
LOG.info("WX Plugin '{}'".format(message)) LOG.info(f"WX Plugin '{message}'")
a = re.search(r"^.*\s+(.*)", message) a = re.search(r"^.*\s+(.*)", message)
if a is not None: if a is not None:
searchcall = a.group(1) searchcall = a.group(1)
@ -101,7 +103,7 @@ class USMetarPlugin(plugin.APRSDMessagePluginBase):
try: try:
resp = plugin_utils.get_weather_gov_metar(station) resp = plugin_utils.get_weather_gov_metar(station)
except Exception as e: except Exception as e:
LOG.debug("Weather failed with: {}".format(str(e))) LOG.debug(f"Weather failed with: {str(e)}")
reply = "Unable to find station METAR" reply = "Unable to find station METAR"
else: else:
station_data = json.loads(resp.text) station_data = json.loads(resp.text)
@ -118,7 +120,7 @@ class USMetarPlugin(plugin.APRSDMessagePluginBase):
["services", "aprs.fi", "apiKey"], ["services", "aprs.fi", "apiKey"],
) )
except Exception as ex: except Exception as ex:
LOG.error("Failed to find config aprs.fi:apikey {}".format(ex)) LOG.error(f"Failed to find config aprs.fi:apikey {ex}")
return "No aprs.fi apikey found" return "No aprs.fi apikey found"
api_key = self.config["services"]["aprs.fi"]["apiKey"] api_key = self.config["services"]["aprs.fi"]["apiKey"]
@ -126,7 +128,7 @@ class USMetarPlugin(plugin.APRSDMessagePluginBase):
try: try:
aprs_data = plugin_utils.get_aprs_fi(api_key, fromcall) aprs_data = plugin_utils.get_aprs_fi(api_key, fromcall)
except Exception as ex: except Exception as ex:
LOG.error("Failed to fetch aprs.fi data {}".format(ex)) LOG.error(f"Failed to fetch aprs.fi data {ex}")
return "Failed to fetch location" return "Failed to fetch location"
# LOG.debug("LocationPlugin: aprs_data = {}".format(aprs_data)) # LOG.debug("LocationPlugin: aprs_data = {}".format(aprs_data))
@ -140,7 +142,7 @@ class USMetarPlugin(plugin.APRSDMessagePluginBase):
try: try:
wx_data = plugin_utils.get_weather_gov_for_gps(lat, lon) wx_data = plugin_utils.get_weather_gov_for_gps(lat, lon)
except Exception as ex: except Exception as ex:
LOG.error("Couldn't fetch forecast.weather.gov '{}'".format(ex)) LOG.error(f"Couldn't fetch forecast.weather.gov '{ex}'")
return "Unable to metar find station." return "Unable to metar find station."
if wx_data["location"]["metar"]: if wx_data["location"]["metar"]:
@ -148,7 +150,7 @@ class USMetarPlugin(plugin.APRSDMessagePluginBase):
try: try:
resp = plugin_utils.get_weather_gov_metar(station) resp = plugin_utils.get_weather_gov_metar(station)
except Exception as e: except Exception as e:
LOG.debug("Weather failed with: {}".format(str(e))) LOG.debug(f"Weather failed with: {str(e)}")
reply = "Failed to get Metar" reply = "Failed to get Metar"
else: else:
station_data = json.loads(resp.text) station_data = json.loads(resp.text)
@ -188,7 +190,7 @@ class OWMWeatherPlugin(plugin.APRSDMessagePluginBase):
fromcall = packet.get("from") fromcall = packet.get("from")
message = packet.get("message_text", None) message = packet.get("message_text", None)
# ack = packet.get("msgNo", "0") # ack = packet.get("msgNo", "0")
LOG.info("OWMWeather Plugin '{}'".format(message)) LOG.info(f"OWMWeather Plugin '{message}'")
a = re.search(r"^.*\s+(.*)", message) a = re.search(r"^.*\s+(.*)", message)
if a is not None: if a is not None:
searchcall = a.group(1) searchcall = a.group(1)
@ -199,14 +201,14 @@ class OWMWeatherPlugin(plugin.APRSDMessagePluginBase):
try: try:
utils.check_config_option(self.config, ["services", "aprs.fi", "apiKey"]) utils.check_config_option(self.config, ["services", "aprs.fi", "apiKey"])
except Exception as ex: except Exception as ex:
LOG.error("Failed to find config aprs.fi:apikey {}".format(ex)) LOG.error(f"Failed to find config aprs.fi:apikey {ex}")
return "No aprs.fi apikey found" return "No aprs.fi apikey found"
api_key = self.config["services"]["aprs.fi"]["apiKey"] api_key = self.config["services"]["aprs.fi"]["apiKey"]
try: try:
aprs_data = plugin_utils.get_aprs_fi(api_key, searchcall) aprs_data = plugin_utils.get_aprs_fi(api_key, searchcall)
except Exception as ex: except Exception as ex:
LOG.error("Failed to fetch aprs.fi data {}".format(ex)) LOG.error(f"Failed to fetch aprs.fi data {ex}")
return "Failed to fetch location" return "Failed to fetch location"
# LOG.debug("LocationPlugin: aprs_data = {}".format(aprs_data)) # LOG.debug("LocationPlugin: aprs_data = {}".format(aprs_data))
@ -223,7 +225,7 @@ class OWMWeatherPlugin(plugin.APRSDMessagePluginBase):
["services", "openweathermap", "apiKey"], ["services", "openweathermap", "apiKey"],
) )
except Exception as ex: except Exception as ex:
LOG.error("Failed to find config openweathermap:apiKey {}".format(ex)) LOG.error(f"Failed to find config openweathermap:apiKey {ex}")
return "No openweathermap apiKey found" return "No openweathermap apiKey found"
try: try:
@ -244,7 +246,7 @@ class OWMWeatherPlugin(plugin.APRSDMessagePluginBase):
exclude="minutely,hourly", exclude="minutely,hourly",
) )
except Exception as ex: except Exception as ex:
LOG.error("Couldn't fetch openweathermap api '{}'".format(ex)) LOG.error(f"Couldn't fetch openweathermap api '{ex}'")
# default to UTC # default to UTC
return "Unable to get weather" return "Unable to get weather"
@ -312,7 +314,7 @@ class AVWXWeatherPlugin(plugin.APRSDMessagePluginBase):
fromcall = packet.get("from") fromcall = packet.get("from")
message = packet.get("message_text", None) message = packet.get("message_text", None)
# ack = packet.get("msgNo", "0") # ack = packet.get("msgNo", "0")
LOG.info("OWMWeather Plugin '{}'".format(message)) LOG.info(f"OWMWeather Plugin '{message}'")
a = re.search(r"^.*\s+(.*)", message) a = re.search(r"^.*\s+(.*)", message)
if a is not None: if a is not None:
searchcall = a.group(1) searchcall = a.group(1)
@ -323,14 +325,14 @@ class AVWXWeatherPlugin(plugin.APRSDMessagePluginBase):
try: try:
utils.check_config_option(self.config, ["services", "aprs.fi", "apiKey"]) utils.check_config_option(self.config, ["services", "aprs.fi", "apiKey"])
except Exception as ex: except Exception as ex:
LOG.error("Failed to find config aprs.fi:apikey {}".format(ex)) LOG.error(f"Failed to find config aprs.fi:apikey {ex}")
return "No aprs.fi apikey found" return "No aprs.fi apikey found"
api_key = self.config["services"]["aprs.fi"]["apiKey"] api_key = self.config["services"]["aprs.fi"]["apiKey"]
try: try:
aprs_data = plugin_utils.get_aprs_fi(api_key, searchcall) aprs_data = plugin_utils.get_aprs_fi(api_key, searchcall)
except Exception as ex: except Exception as ex:
LOG.error("Failed to fetch aprs.fi data {}".format(ex)) LOG.error(f"Failed to fetch aprs.fi data {ex}")
return "Failed to fetch location" return "Failed to fetch location"
# LOG.debug("LocationPlugin: aprs_data = {}".format(aprs_data)) # LOG.debug("LocationPlugin: aprs_data = {}".format(aprs_data))
@ -344,32 +346,32 @@ class AVWXWeatherPlugin(plugin.APRSDMessagePluginBase):
try: try:
utils.check_config_option(self.config, ["services", "avwx", "apiKey"]) utils.check_config_option(self.config, ["services", "avwx", "apiKey"])
except Exception as ex: except Exception as ex:
LOG.error("Failed to find config avwx:apiKey {}".format(ex)) LOG.error(f"Failed to find config avwx:apiKey {ex}")
return "No avwx apiKey found" return "No avwx apiKey found"
try: try:
utils.check_config_option(self.config, ["services", "avwx", "base_url"]) utils.check_config_option(self.config, ["services", "avwx", "base_url"])
except Exception as ex: except Exception as ex:
LOG.debug("Didn't find avwx:base_url {}".format(ex)) LOG.debug(f"Didn't find avwx:base_url {ex}")
base_url = "https://avwx.rest" base_url = "https://avwx.rest"
else: else:
base_url = self.config["services"]["avwx"]["base_url"] base_url = self.config["services"]["avwx"]["base_url"]
api_key = self.config["services"]["avwx"]["apiKey"] api_key = self.config["services"]["avwx"]["apiKey"]
token = "TOKEN {}".format(api_key) token = f"TOKEN {api_key}"
headers = {"Authorization": token} headers = {"Authorization": token}
try: try:
coord = "{},{}".format(lat, lon) coord = f"{lat},{lon}"
url = ( url = (
"{}/api/station/near/{}?" "{}/api/station/near/{}?"
"n=1&airport=false&reporting=true&format=json".format(base_url, coord) "n=1&airport=false&reporting=true&format=json".format(base_url, coord)
) )
LOG.debug("Get stations near me '{}'".format(url)) LOG.debug(f"Get stations near me '{url}'")
response = requests.get(url, headers=headers) response = requests.get(url, headers=headers)
except Exception as ex: except Exception as ex:
LOG.error(ex) LOG.error(ex)
raise Exception("Failed to get the weather '{}'".format(ex)) raise Exception(f"Failed to get the weather '{ex}'")
else: else:
wx_data = json.loads(response.text) wx_data = json.loads(response.text)
@ -385,11 +387,11 @@ class AVWXWeatherPlugin(plugin.APRSDMessagePluginBase):
) )
) )
LOG.debug("Get METAR '{}'".format(url)) LOG.debug(f"Get METAR '{url}'")
response = requests.get(url, headers=headers) response = requests.get(url, headers=headers)
except Exception as ex: except Exception as ex:
LOG.error(ex) LOG.error(ex)
raise Exception("Failed to get metar {}".format(ex)) raise Exception(f"Failed to get metar {ex}")
else: else:
metar_data = json.loads(response.text) metar_data = json.loads(response.text)

View File

@ -5,6 +5,7 @@ import threading
import aprsd import aprsd
from aprsd import packets, plugin, utils from aprsd import packets, plugin, utils
LOG = logging.getLogger("APRSD") LOG = logging.getLogger("APRSD")

View File

@ -6,9 +6,11 @@ import threading
import time import time
import tracemalloc import tracemalloc
from aprsd import client, messaging, packets, plugin, stats, utils
import aprslib import aprslib
from aprsd import client, messaging, packets, plugin, stats, utils
LOG = logging.getLogger("APRSD") LOG = logging.getLogger("APRSD")
RX_THREAD = "RX" RX_THREAD = "RX"
@ -214,7 +216,7 @@ class APRSDRXThread(APRSDThread):
def process_ack_packet(self, packet): def process_ack_packet(self, packet):
ack_num = packet.get("msgNo") ack_num = packet.get("msgNo")
LOG.info("Got ack for message {}".format(ack_num)) LOG.info(f"Got ack for message {ack_num}")
messaging.log_message( messaging.log_message(
"ACK", "ACK",
packet["raw"], packet["raw"],
@ -257,7 +259,7 @@ class APRSDRXThread(APRSDThread):
# one of the plugins wants to send multiple messages # one of the plugins wants to send multiple messages
found_command = True found_command = True
for subreply in reply: for subreply in reply:
LOG.debug("Sending '{}'".format(subreply)) LOG.debug(f"Sending '{subreply}'")
msg = messaging.TextMessage( msg = messaging.TextMessage(
self.config["aprs"]["login"], self.config["aprs"]["login"],
@ -272,7 +274,7 @@ class APRSDRXThread(APRSDThread):
# us that they processed the message correctly, but have # us that they processed the message correctly, but have
# nothing to reply with, so we avoid replying with a usage string # nothing to reply with, so we avoid replying with a usage string
if reply is not messaging.NULL_MESSAGE: if reply is not messaging.NULL_MESSAGE:
LOG.debug("Sending '{}'".format(reply)) LOG.debug(f"Sending '{reply}'")
msg = messaging.TextMessage( msg = messaging.TextMessage(
self.config["aprs"]["login"], self.config["aprs"]["login"],

View File

@ -5,6 +5,7 @@ import logging
import time import time
import types import types
VALID_TRACE_FLAGS = {"method", "api"} VALID_TRACE_FLAGS = {"method", "api"}
TRACE_API = False TRACE_API = False
TRACE_METHOD = False TRACE_METHOD = False
@ -155,8 +156,6 @@ class TraceWrapperMetaclass(type):
class TraceWrapperWithABCMetaclass(abc.ABCMeta, TraceWrapperMetaclass): class TraceWrapperWithABCMetaclass(abc.ABCMeta, TraceWrapperMetaclass):
"""Metaclass that wraps all methods of a class with trace.""" """Metaclass that wraps all methods of a class with trace."""
pass
def setup_tracing(trace_flags): def setup_tracing(trace_flags):
"""Set global variables for each trace flag. """Set global variables for each trace flag.

View File

@ -10,12 +10,14 @@ import re
import sys import sys
import threading import threading
import aprsd
from aprsd import plugin
import click import click
import update_checker import update_checker
import yaml import yaml
import aprsd
from aprsd import plugin
LOG_LEVELS = { LOG_LEVELS = {
"CRITICAL": logging.CRITICAL, "CRITICAL": logging.CRITICAL,
"ERROR": logging.ERROR, "ERROR": logging.ERROR,
@ -102,9 +104,9 @@ DEFAULT_CONFIG_DICT = {
} }
home = str(Path.home()) home = str(Path.home())
DEFAULT_CONFIG_DIR = "{}/.config/aprsd/".format(home) DEFAULT_CONFIG_DIR = f"{home}/.config/aprsd/"
DEFAULT_SAVE_FILE = "{}/.config/aprsd/aprsd.p".format(home) DEFAULT_SAVE_FILE = f"{home}/.config/aprsd/aprsd.p"
DEFAULT_CONFIG_FILE = "{}/.config/aprsd/aprsd.yml".format(home) DEFAULT_CONFIG_FILE = f"{home}/.config/aprsd/aprsd.yml"
def synchronized(wrapped): def synchronized(wrapped):
@ -229,7 +231,7 @@ def create_default_config():
config_file_expanded = os.path.expanduser(DEFAULT_CONFIG_FILE) config_file_expanded = os.path.expanduser(DEFAULT_CONFIG_FILE)
config_dir = os.path.dirname(config_file_expanded) config_dir = os.path.dirname(config_file_expanded)
if not os.path.exists(config_dir): if not os.path.exists(config_dir):
click.echo("Config dir '{}' doesn't exist, creating.".format(config_dir)) click.echo(f"Config dir '{config_dir}' doesn't exist, creating.")
mkdir_p(config_dir) mkdir_p(config_dir)
with open(config_file_expanded, "w+") as cf: with open(config_file_expanded, "w+") as cf:
cf.write(dump_default_cfg()) cf.write(dump_default_cfg())
@ -245,7 +247,7 @@ def get_config(config_file):
else: else:
if config_file == DEFAULT_CONFIG_FILE: if config_file == DEFAULT_CONFIG_FILE:
click.echo( click.echo(
"{} is missing, creating config file".format(config_file_expanded), f"{config_file_expanded} is missing, creating config file",
) )
create_default_config() create_default_config()
msg = ( msg = (
@ -256,7 +258,7 @@ def get_config(config_file):
else: else:
# The user provided a config file path different from the # The user provided a config file path different from the
# Default, so we won't try and create it, just bitch and bail. # Default, so we won't try and create it, just bitch and bail.
msg = "Custom config file '{}' is missing.".format(config_file) msg = f"Custom config file '{config_file}' is missing."
click.echo(msg) click.echo(msg)
sys.exit(-1) sys.exit(-1)

View File

@ -1,4 +1,3 @@
black
flake8 flake8
isort isort
mypy mypy
@ -10,3 +9,4 @@ tox
twine twine
pre-commit pre-commit
pip-tools pip-tools
gray

View File

@ -4,6 +4,8 @@
# #
# pip-compile dev-requirements.in # pip-compile dev-requirements.in
# #
add-trailing-comma==2.1.0
# via gray
alabaster==0.7.12 alabaster==0.7.12
# via sphinx # via sphinx
appdirs==1.4.4 appdirs==1.4.4
@ -11,17 +13,19 @@ appdirs==1.4.4
# black # black
# virtualenv # virtualenv
attrs==20.3.0 attrs==20.3.0
# via pytest # via
# jsonschema
# pytest
autoflake==1.4
# via gray
babel==2.9.1 babel==2.9.1
# via sphinx # via sphinx
black==21.4b2 black==21.7b0
# via -r dev-requirements.in # via gray
bleach==3.3.0 bleach==3.3.0
# via readme-renderer # via readme-renderer
certifi==2020.12.5 certifi==2020.12.5
# via requests # via requests
cffi==1.14.5
# via cryptography
cfgv==3.2.0 cfgv==3.2.0
# via pre-commit # via pre-commit
chardet==4.0.0 chardet==4.0.0
@ -32,26 +36,35 @@ click==7.1.2
# pip-tools # pip-tools
colorama==0.4.4 colorama==0.4.4
# via twine # via twine
colorlog==6.4.1
# via prettylog
configargparse==1.5.2
# via gray
coverage==5.5 coverage==5.5
# via pytest-cov # via pytest-cov
cryptography==3.4.7
# via secretstorage
distlib==0.3.1 distlib==0.3.1
# via virtualenv # via virtualenv
docutils==0.16 docutils==0.16
# via # via
# readme-renderer # readme-renderer
# sphinx # sphinx
fast-json==0.3.2
# via prettylog
filelock==3.0.12 filelock==3.0.12
# via # via
# tox # tox
# virtualenv # virtualenv
fixit==0.1.4
# via gray
flake8-polyfill==1.0.2 flake8-polyfill==1.0.2
# via pep8-naming # via pep8-naming
flake8==3.9.1 flake8==3.9.1
# via # via
# -r dev-requirements.in # -r dev-requirements.in
# fixit
# flake8-polyfill # flake8-polyfill
gray==0.10.1
# via -r dev-requirements.in
identify==2.2.4 identify==2.2.4
# via pre-commit # via pre-commit
idna==2.10 idna==2.10
@ -62,18 +75,22 @@ importlib-metadata==4.0.1
# via # via
# keyring # keyring
# twine # twine
importlib-resources==5.2.2
# via fixit
iniconfig==1.1.1 iniconfig==1.1.1
# via pytest # via pytest
isort==5.8.0 isort==5.8.0
# via -r dev-requirements.in
jeepney==0.6.0
# via # via
# keyring # -r dev-requirements.in
# secretstorage # gray
jinja2==2.11.3 jinja2==2.11.3
# via sphinx # via sphinx
jsonschema==3.2.0
# via fixit
keyring==23.0.1 keyring==23.0.1
# via twine # via twine
libcst==0.3.20
# via fixit
markupsafe==1.1.1 markupsafe==1.1.1
# via jinja2 # via jinja2
mccabe==0.6.1 mccabe==0.6.1
@ -82,6 +99,7 @@ mypy-extensions==0.4.3
# via # via
# black # black
# mypy # mypy
# typing-inspect
mypy==0.812 mypy==0.812
# via -r dev-requirements.in # via -r dev-requirements.in
nodeenv==1.6.0 nodeenv==1.6.0
@ -108,22 +126,26 @@ pluggy==0.13.1
# tox # tox
pre-commit==2.12.1 pre-commit==2.12.1
# via -r dev-requirements.in # via -r dev-requirements.in
prettylog==0.3.0
# via gray
py==1.10.0 py==1.10.0
# via # via
# pytest # pytest
# tox # tox
pycodestyle==2.7.0 pycodestyle==2.7.0
# via flake8 # via flake8
pycparser==2.20
# via cffi
pyflakes==2.3.1 pyflakes==2.3.1
# via flake8 # via
# autoflake
# flake8
pygments==2.9.0 pygments==2.9.0
# via # via
# readme-renderer # readme-renderer
# sphinx # sphinx
pyparsing==2.4.7 pyparsing==2.4.7
# via packaging # via packaging
pyrsistent==0.18.0
# via jsonschema
pytest-cov==2.11.1 pytest-cov==2.11.1
# via -r dev-requirements.in # via -r dev-requirements.in
pytest==6.2.3 pytest==6.2.3
@ -132,8 +154,13 @@ pytest==6.2.3
# pytest-cov # pytest-cov
pytz==2021.1 pytz==2021.1
# via babel # via babel
pyupgrade==2.24.0
# via gray
pyyaml==5.4.1 pyyaml==5.4.1
# via pre-commit # via
# fixit
# libcst
# pre-commit
readme-renderer==29.0 readme-renderer==29.0
# via twine # via twine
regex==2021.4.4 regex==2021.4.4
@ -147,11 +174,10 @@ requests==2.25.1
# twine # twine
rfc3986==1.4.0 rfc3986==1.4.0
# via twine # via twine
secretstorage==3.3.1
# via keyring
six==1.15.0 six==1.15.0
# via # via
# bleach # bleach
# jsonschema
# readme-renderer # readme-renderer
# tox # tox
# virtualenv # virtualenv
@ -171,13 +197,18 @@ sphinxcontrib-qthelp==1.0.3
# via sphinx # via sphinx
sphinxcontrib-serializinghtml==1.1.4 sphinxcontrib-serializinghtml==1.1.4
# via sphinx # via sphinx
tokenize-rt==4.1.0
# via
# add-trailing-comma
# pyupgrade
toml==0.10.2 toml==0.10.2
# via # via
# black
# pep517 # pep517
# pre-commit # pre-commit
# pytest # pytest
# tox # tox
tomli==1.2.1
# via black
tox==3.23.0 tox==3.23.0
# via -r dev-requirements.in # via -r dev-requirements.in
tqdm==4.60.0 tqdm==4.60.0
@ -187,7 +218,18 @@ twine==3.4.1
typed-ast==1.4.3 typed-ast==1.4.3
# via mypy # via mypy
typing-extensions==3.10.0.0 typing-extensions==3.10.0.0
# via mypy # via
# libcst
# mypy
# typing-inspect
typing-inspect==0.7.1
# via libcst
ujson==4.1.0
# via fast-json
unify==0.5
# via gray
untokenize==0.1.1
# via unify
urllib3==1.26.5 urllib3==1.26.5
# via requests # via requests
virtualenv==20.4.4 virtualenv==20.4.4
@ -197,7 +239,9 @@ virtualenv==20.4.4
webencodings==0.5.1 webencodings==0.5.1
# via bleach # via bleach
zipp==3.4.1 zipp==3.4.1
# via importlib-metadata # via
# importlib-metadata
# importlib-resources
# The following packages are considered to be unsafe in a requirements file: # The following packages are considered to be unsafe in a requirements file:
# pip # pip

View File

@ -14,6 +14,7 @@
import os import os
import sys import sys
sys.path.insert(0, os.path.abspath("../src")) sys.path.insert(0, os.path.abspath("../src"))

View File

@ -2,6 +2,7 @@ import logging
from aprsd import plugin from aprsd import plugin
LOG = logging.getLogger("APRSD") LOG = logging.getLogger("APRSD")
@ -15,5 +16,5 @@ class HelloPlugin(plugin.APRSDPluginBase):
def command(self, fromcall, message, ack): def command(self, fromcall, message, ack):
LOG.info("HelloPlugin") LOG.info("HelloPlugin")
reply = "Hello '{}'".format(fromcall) reply = f"Hello '{fromcall}'"
return reply return reply

2
gray.conf Normal file
View File

@ -0,0 +1,2 @@
formatters = add-trailing-comma,autoflake,fixit,isort,pyupgrade,unify
min-python-version = 3.8

View File

@ -2,32 +2,12 @@
requires = ["setuptools>=46.0", "wheel"] requires = ["setuptools>=46.0", "wheel"]
build-backend = "setuptools.build_meta" build-backend = "setuptools.build_meta"
[tool.black]
# Use the more relaxed max line length permitted in PEP8.
line-length = 88
target-version = ["py36", "py37", "py38"]
# black will automatically exclude all files listed in .gitignore
include = '\.pyi?$'
exclude = '''
/(
\.git
| \.hg
| \.mypy_cache
| \.tox
| \.venv
| _build
| buck-out
| build
| dist
)/
'''
[tool.isort] [tool.isort]
profile = "black"
line_length = 88
force_sort_within_sections = true force_sort_within_sections = true
multi_line_output = 4
line_length = 88
# Inform isort of paths to import names that should be considered part of the "First Party" group. # Inform isort of paths to import names that should be considered part of the "First Party" group.
src_paths = ["src/openstack_loadtest"] #src_paths = ["src/openstack_loadtest"]
skip_gitignore = true skip_gitignore = true
# If you need to skip/exclude folders, consider using skip_glob as that will allow the # If you need to skip/exclude folders, consider using skip_glob as that will allow the
# isort defaults for skip to remain without the need to duplicate them. # isort defaults for skip to remain without the need to duplicate them.

View File

@ -16,6 +16,7 @@
# THIS FILE IS MANAGED BY THE GLOBAL REQUIREMENTS REPO - DO NOT EDIT # THIS FILE IS MANAGED BY THE GLOBAL REQUIREMENTS REPO - DO NOT EDIT
import setuptools import setuptools
# In python < 2.7.4, a lazy loading of package `pbr` will break # In python < 2.7.4, a lazy loading of package `pbr` will break
# setuptools if some other modules registered functions in `atexit`. # setuptools if some other modules registered functions in `atexit`.
# solution from: http://bugs.python.org/issue15881#msg170215 # solution from: http://bugs.python.org/issue15881#msg170215

View File

@ -7,7 +7,7 @@ class TestEmail(unittest.TestCase):
def test_get_email_from_shortcut(self): def test_get_email_from_shortcut(self):
email.CONFIG = {"aprsd": {"email": {"shortcuts": {}}}} email.CONFIG = {"aprsd": {"email": {"shortcuts": {}}}}
email_address = "something@something.com" email_address = "something@something.com"
addr = "-{}".format(email_address) addr = f"-{email_address}"
actual = email.get_email_from_shortcut(addr) actual = email.get_email_from_shortcut(addr)
self.assertEqual(addr, actual) self.assertEqual(addr, actual)

View File

@ -3,6 +3,7 @@ import unittest
from aprsd import email from aprsd import email
if sys.version_info >= (3, 2): if sys.version_info >= (3, 2):
from unittest import mock from unittest import mock
else: else:

View File

@ -1,6 +1,8 @@
import unittest import unittest
from unittest import mock from unittest import mock
import pytz
import aprsd import aprsd
from aprsd import messaging, stats, utils from aprsd import messaging, stats, utils
from aprsd.fuzzyclock import fuzzy from aprsd.fuzzyclock import fuzzy
@ -9,7 +11,6 @@ from aprsd.plugins import ping as ping_plugin
from aprsd.plugins import query as query_plugin from aprsd.plugins import query as query_plugin
from aprsd.plugins import time as time_plugin from aprsd.plugins import time as time_plugin
from aprsd.plugins import version as version_plugin from aprsd.plugins import version as version_plugin
import pytz
class TestPlugin(unittest.TestCase): class TestPlugin(unittest.TestCase):
@ -171,7 +172,7 @@ class TestPlugin(unittest.TestCase):
@mock.patch("aprsd.plugin.PluginManager.get_msg_plugins") @mock.patch("aprsd.plugin.PluginManager.get_msg_plugins")
def test_version(self, mock_get_plugins): def test_version(self, mock_get_plugins):
expected = "APRSD ver:{} uptime:0:0:0".format(aprsd.__version__) expected = f"APRSD ver:{aprsd.__version__} uptime:0:0:0"
version = version_plugin.VersionPlugin(self.config) version = version_plugin.VersionPlugin(self.config)
packet = self.fake_packet( packet = self.fake_packet(

20
tox.ini
View File

@ -76,9 +76,9 @@ exclude = .venv,.git,.tox,dist,doc,.ropeproject
# This section is not needed if not using GitHub Actions for CI. # This section is not needed if not using GitHub Actions for CI.
[gh-actions] [gh-actions]
python = python =
3.6: py36, pep8, fmt-check 3.6: py36, pep8
3.7: py38, pep8, fmt-check 3.7: py38, pep8
3.8: py38, pep8, fmt-check, type-check, docs 3.8: py38, pep8, type-check, docs
3.9: py39 3.9: py39
[testenv:fmt] [testenv:fmt]
@ -88,19 +88,7 @@ skip_install = true
deps = deps =
-r{toxinidir}/dev-requirements.txt -r{toxinidir}/dev-requirements.txt
commands = commands =
isort . gray aprsd tests
black .
[testenv:fmt-check]
# Runs a check only on code formatting.
# you can fix imports by running isort standalone
# you can fix code formatting by running black standalone
skip_install = true
deps =
-r{toxinidir}/dev-requirements.txt
commands =
isort --check-only .
black --check .
[testenv:type-check] [testenv:type-check]
skip_install = true skip_install = true