1
0
mirror of https://github.com/craigerl/aprsd.git synced 2024-11-14 20:32:00 -05:00

Added new Config object.

The config object now has builtin dot notation getter with default

config.get("some.path.here", default="Not found")
This commit is contained in:
Hemna 2021-10-04 15:22:10 -04:00
parent a6ed7b894b
commit 491644ece6
6 changed files with 86 additions and 76 deletions

View File

@ -125,23 +125,19 @@ class KISSClient(Client):
if "kiss" not in config: if "kiss" not in config:
return False return False
if "serial" in config["kiss"]: if config.get("kiss.serial.enabled", default=False):
if config["kiss"]["serial"].get("enabled", False): return True
return True
if "tcp" in config["kiss"]: if config.get("kiss.tcp.enabled", default=False):
if config["kiss"]["tcp"].get("enabled", False): return True
return True
@staticmethod @staticmethod
def transport(config): def transport(config):
if "serial" in config["kiss"]: if config.get("kiss.serial.enabled", default=False):
if config["kiss"]["serial"].get("enabled", False): return TRANSPORT_SERIALKISS
return TRANSPORT_SERIALKISS
if "tcp" in config["kiss"]: if config.get("kiss.tcp.enabled", default=False):
if config["kiss"]["tcp"].get("enabled", False): return TRANSPORT_TCPKISS
return TRANSPORT_TCPKISS
def decode_packet(self, *args, **kwargs): def decode_packet(self, *args, **kwargs):
"""We get a frame, which has to be decoded.""" """We get a frame, which has to be decoded."""

View File

@ -1,3 +1,4 @@
import collections
import logging import logging
import os import os
from pathlib import Path from pathlib import Path
@ -134,6 +135,60 @@ DEFAULT_SAVE_FILE = f"{home}/.config/aprsd/aprsd.p"
DEFAULT_CONFIG_FILE = f"{home}/.config/aprsd/aprsd.yml" DEFAULT_CONFIG_FILE = f"{home}/.config/aprsd/aprsd.yml"
class Config(collections.UserDict):
def _get(self, d, keys, default=None):
"""
Example:
d = {'meta': {'status': 'OK', 'status_code': 200}}
deep_get(d, ['meta', 'status_code']) # => 200
deep_get(d, ['garbage', 'status_code']) # => None
deep_get(d, ['meta', 'garbage'], default='-') # => '-'
"""
if type(keys) is str and "." in keys:
keys = keys.split(".")
assert type(keys) is list
if d is None:
return default
if not keys:
return d
if type(d) is str:
return default
return self._get(d.get(keys[0]), keys[1:], default)
def get(self, path, default=None):
return self._get(self.data, path, default=default)
def exists(self, path):
"""See if a conf value exists."""
test = "-3.14TEST41.3-"
return (self.get(path, default=test) != test)
def check_option(self, path, default_fail=None):
"""Make sure the config option doesn't have default value."""
if not self.exists(path):
raise Exception(
"Option '{}' was not in config file".format(
path,
),
)
val = self.get(path)
if val == default_fail:
# We have to fail and bail if the user hasn't edited
# this config option.
raise Exception(
"Config file needs to be changed from provided"
" defaults for '{}'".format(
path,
),
)
def add_config_comments(raw_yaml): def add_config_comments(raw_yaml):
end_idx = utils.end_substr(raw_yaml, "aprs:") end_idx = utils.end_substr(raw_yaml, "aprs:")
if end_idx != -1: if end_idx != -1:
@ -223,7 +278,7 @@ def get_config(config_file):
if os.path.exists(config_file_expanded): if os.path.exists(config_file_expanded):
with open(config_file_expanded) as stream: with open(config_file_expanded) as stream:
config = yaml.load(stream, Loader=yaml.FullLoader) config = yaml.load(stream, Loader=yaml.FullLoader)
return config return Config(config)
else: else:
if config_file == DEFAULT_CONFIG_FILE: if config_file == DEFAULT_CONFIG_FILE:
click.echo( click.echo(
@ -249,33 +304,28 @@ def get_config(config_file):
# If the required params don't exist, # If the required params don't exist,
# it will look in the environment # it will look in the environment
def parse_config(config_file): def parse_config(config_file):
# for now we still use globals....ugh config = get_config(config_file)
global CONFIG
def fail(msg): def fail(msg):
click.echo(msg) click.echo(msg)
sys.exit(-1) sys.exit(-1)
def check_option(config, chain, default_fail=None): def check_option(config, path, default_fail=None):
try: try:
config = check_config_option(config, chain, default_fail=default_fail) config.check_option(path, default_fail=default_fail)
except Exception as ex: except Exception as ex:
fail(repr(ex)) fail(repr(ex))
else: else:
return config return config
config = get_config(config_file)
# special check here to make sure user has edited the config file # special check here to make sure user has edited the config file
# and changed the ham callsign # and changed the ham callsign
check_option( check_option(
config, config,
[ "ham.callsign",
"ham",
"callsign",
],
default_fail=DEFAULT_CONFIG_DICT["ham"]["callsign"], default_fail=DEFAULT_CONFIG_DICT["ham"]["callsign"],
) )
check_option( check_option(
config, config,
["services", "aprs.fi", "apiKey"], ["services", "aprs.fi", "apiKey"],
@ -283,7 +333,7 @@ def parse_config(config_file):
) )
check_option( check_option(
config, config,
["aprs", "login"], "aprs.login",
default_fail=DEFAULT_CONFIG_DICT["aprs"]["login"], default_fail=DEFAULT_CONFIG_DICT["aprs"]["login"],
) )
check_option( check_option(
@ -293,21 +343,21 @@ def parse_config(config_file):
) )
# Ensure they change the admin password # Ensure they change the admin password
if config["aprsd"]["web"]["enabled"] is True: if config.get("aprsd.web.enabled") is True:
check_option( check_option(
config, config,
["aprsd", "web", "users", "admin"], ["aprsd", "web", "users", "admin"],
default_fail=DEFAULT_CONFIG_DICT["aprsd"]["web"]["users"]["admin"], default_fail=DEFAULT_CONFIG_DICT["aprsd"]["web"]["users"]["admin"],
) )
if config["aprsd"]["watch_list"]["enabled"] is True: if config.get("aprsd.watch_list.enabled") is True:
check_option( check_option(
config, config,
["aprsd", "watch_list", "alert_callsign"], ["aprsd", "watch_list", "alert_callsign"],
default_fail=DEFAULT_CONFIG_DICT["aprsd"]["watch_list"]["alert_callsign"], default_fail=DEFAULT_CONFIG_DICT["aprsd"]["watch_list"]["alert_callsign"],
) )
if config["aprsd"]["email"]["enabled"] is True: if config.get("aprsd.email.enabled") is True:
# Check IMAP server settings # Check IMAP server settings
check_option(config, ["aprsd", "email", "imap", "host"]) check_option(config, ["aprsd", "email", "imap", "host"])
check_option(config, ["aprsd", "email", "imap", "port"]) check_option(config, ["aprsd", "email", "imap", "port"])
@ -337,31 +387,3 @@ def parse_config(config_file):
) )
return config return config
def conf_option_exists(conf, chain):
_key = chain.pop(0)
if _key in conf:
return conf_option_exists(conf[_key], chain) if chain else conf[_key]
def check_config_option(config, chain, default_fail=None):
result = conf_option_exists(config, chain.copy())
if result is None:
raise Exception(
"'{}' was not in config file".format(
chain,
),
)
else:
if default_fail:
if result == default_fail:
# We have to fail and bail if the user hasn't edited
# this config option.
raise Exception(
"Config file needs to be edited from provided defaults for {}.".format(
chain,
),
)
else:
return config

View File

@ -174,20 +174,13 @@ def setup_logging(config, loglevel, quiet):
LOG.addHandler(fh) LOG.addHandler(fh)
imap_logger = None imap_logger = None
if config["aprsd"]["email"].get("enabled", False) and config["aprsd"]["email"][ if config.get("aprsd.email.enabled", default=False) and config.get("aprsd.email.imap.debug", default=False):
"imap"
].get("debug", False):
imap_logger = logging.getLogger("imapclient.imaplib") imap_logger = logging.getLogger("imapclient.imaplib")
imap_logger.setLevel(log_level) imap_logger.setLevel(log_level)
imap_logger.addHandler(fh) imap_logger.addHandler(fh)
if ( if config.get("aprsd.web.enabled", default=False):
aprsd_config.check_config_option(
config, ["aprsd", "web", "enabled"],
default_fail=False,
)
):
qh = logging.handlers.QueueHandler(threads.logging_queue) qh = logging.handlers.QueueHandler(threads.logging_queue)
q_log_formatter = logging.Formatter( q_log_formatter = logging.Formatter(
fmt=aprsd_config.QUEUE_LOG_FORMAT, fmt=aprsd_config.QUEUE_LOG_FORMAT,
@ -498,7 +491,7 @@ def server(
keepalive = threads.KeepAliveThread(config=config) keepalive = threads.KeepAliveThread(config=config)
keepalive.start() keepalive.start()
web_enabled = aprsd_config.check_config_option(config, ["aprsd", "web", "enabled"], default_fail=False) web_enabled = config.get("aprsd.web.enabled", default=False)
if web_enabled: if web_enabled:
flask_enabled = True flask_enabled = True

View File

@ -56,7 +56,6 @@ class EmailInfo:
self._delay = val self._delay = val
class EmailPlugin(plugin.APRSDRegexCommandPluginBase): class EmailPlugin(plugin.APRSDRegexCommandPluginBase):
"""Email Plugin.""" """Email Plugin."""

View File

@ -2,7 +2,7 @@ import logging
import re import re
import time import time
from aprsd import config, plugin, plugin_utils, trace from aprsd import plugin, plugin_utils, trace
LOG = logging.getLogger("APRSD") LOG = logging.getLogger("APRSD")
@ -24,7 +24,7 @@ class LocationPlugin(plugin.APRSDRegexCommandPluginBase):
# get last location of a callsign, get descriptive name from weather service # get last location of a callsign, get descriptive name from weather service
try: try:
config.check_config_option(self.config, ["services", "aprs.fi", "apiKey"]) self.config.check_option(["services", "aprs.fi", "apiKey"])
except Exception as ex: except Exception as ex:
LOG.error(f"Failed to find config aprs.fi:apikey {ex}") LOG.error(f"Failed to find config aprs.fi:apikey {ex}")
return "No aprs.fi apikey found" return "No aprs.fi apikey found"

View File

@ -5,21 +5,21 @@ from aprsd.plugins import email
class TestEmail(unittest.TestCase): class TestEmail(unittest.TestCase):
def test_get_email_from_shortcut(self): def test_get_email_from_shortcut(self):
email.CONFIG = {"aprsd": {"email": {"shortcuts": {}}}} config = {"aprsd": {"email": {"shortcuts": {}}}}
email_address = "something@something.com" email_address = "something@something.com"
addr = f"-{email_address}" addr = f"-{email_address}"
actual = email.get_email_from_shortcut(addr) actual = email.get_email_from_shortcut(config, addr)
self.assertEqual(addr, actual) self.assertEqual(addr, actual)
email.CONFIG = {"aprsd": {"email": {"nothing": "nothing"}}} config = {"aprsd": {"email": {"nothing": "nothing"}}}
actual = email.get_email_from_shortcut(addr) actual = email.get_email_from_shortcut(config, addr)
self.assertEqual(addr, actual) self.assertEqual(addr, actual)
email.CONFIG = {"aprsd": {"email": {"shortcuts": {"not_used": "empty"}}}} config = {"aprsd": {"email": {"shortcuts": {"not_used": "empty"}}}}
actual = email.get_email_from_shortcut(addr) actual = email.get_email_from_shortcut(config, addr)
self.assertEqual(addr, actual) self.assertEqual(addr, actual)
email.CONFIG = {"aprsd": {"email": {"shortcuts": {"-wb": email_address}}}} config = {"aprsd": {"email": {"shortcuts": {"-wb": email_address}}}}
short = "-wb" short = "-wb"
actual = email.get_email_from_shortcut(short) actual = email.get_email_from_shortcut(config, short)
self.assertEqual(email_address, actual) self.assertEqual(email_address, actual)