mirror of
https://github.com/craigerl/aprsd.git
synced 2024-10-31 15:07:13 -04:00
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:
parent
d6643a8e96
commit
e175f77347
@ -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]
|
|
||||||
|
@ -12,4 +12,5 @@
|
|||||||
|
|
||||||
import pbr.version
|
import pbr.version
|
||||||
|
|
||||||
|
|
||||||
__version__ = pbr.version.VersionInfo("aprsd").version_string()
|
__version__ = pbr.version.VersionInfo("aprsd").version_string()
|
||||||
|
@ -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):
|
||||||
|
16
aprsd/dev.py
16
aprsd/dev.py
@ -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__":
|
||||||
|
@ -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"])
|
||||||
|
@ -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()
|
||||||
|
@ -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()
|
||||||
|
@ -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)
|
||||||
|
@ -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:
|
||||||
|
@ -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"])
|
||||||
|
@ -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))
|
||||||
|
@ -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"
|
||||||
|
@ -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:
|
||||||
|
@ -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:
|
||||||
|
@ -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
|
||||||
|
@ -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
|
||||||
|
|
||||||
|
@ -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(
|
||||||
|
@ -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(
|
||||||
|
@ -3,6 +3,7 @@ import time
|
|||||||
|
|
||||||
from aprsd import plugin, trace
|
from aprsd import plugin, trace
|
||||||
|
|
||||||
|
|
||||||
LOG = logging.getLogger("APRSD")
|
LOG = logging.getLogger("APRSD")
|
||||||
|
|
||||||
|
|
||||||
|
@ -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")
|
||||||
|
|
||||||
|
|
||||||
|
@ -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()
|
||||||
|
@ -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:
|
||||||
|
@ -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")
|
||||||
|
|
||||||
|
|
||||||
|
@ -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)
|
||||||
|
|
||||||
|
@ -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")
|
||||||
|
|
||||||
|
|
||||||
|
@ -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"],
|
||||||
|
@ -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.
|
||||||
|
@ -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)
|
||||||
|
@ -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
|
||||||
|
@ -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
|
||||||
|
@ -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"))
|
||||||
|
|
||||||
|
|
||||||
|
@ -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
2
gray.conf
Normal file
@ -0,0 +1,2 @@
|
|||||||
|
formatters = add-trailing-comma,autoflake,fixit,isort,pyupgrade,unify
|
||||||
|
min-python-version = 3.8
|
@ -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.
|
||||||
|
1
setup.py
1
setup.py
@ -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
|
||||||
|
@ -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)
|
||||||
|
|
||||||
|
@ -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:
|
||||||
|
@ -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
20
tox.ini
@ -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
|
||||||
|
Loading…
Reference in New Issue
Block a user