From a7bbde4a439258691feb0429e371828d5b024a64 Mon Sep 17 00:00:00 2001 From: Hemna Date: Sun, 12 Dec 2021 16:13:08 -0500 Subject: [PATCH] Send Message command defaults to config The APRS_LOGIN and APRS_PASSWORD arguments now fallback to the config file if it exists. First it checks the passed in parameters, then checks the environement vars, then checks the parsed config to find the login and password. This patch also adds unit tests for the send-message command to check the fallback. --- ChangeLog | 1 + aprsd/cmds/send_message.py | 23 ++++---- tests/cmds/__init__.py | 0 tests/cmds/test_send_message.py | 94 +++++++++++++++++++++++++++++++++ 4 files changed, 109 insertions(+), 9 deletions(-) create mode 100644 tests/cmds/__init__.py create mode 100644 tests/cmds/test_send_message.py diff --git a/ChangeLog b/ChangeLog index 790a128..f6566f6 100644 --- a/ChangeLog +++ b/ChangeLog @@ -4,6 +4,7 @@ CHANGES v2.5.7 ------ +* Updated Changelog * Fixed an KISS config disabled issue * Fixed a bug with multiple notify plugins enabled * Unify the logging to file and stdout diff --git a/aprsd/cmds/send_message.py b/aprsd/cmds/send_message.py index b2125a0..ea2b234 100644 --- a/aprsd/cmds/send_message.py +++ b/aprsd/cmds/send_message.py @@ -20,13 +20,13 @@ LOG = logging.getLogger("APRSD") "--aprs-login", envvar="APRS_LOGIN", show_envvar=True, - help="What callsign to send the message from.", + help="What callsign to send the message from. Defaults to config entry.", ) @click.option( "--aprs-password", envvar="APRS_PASSWORD", show_envvar=True, - help="the APRS-IS password for APRS_LOGIN", + help="the APRS-IS password for APRS_LOGIN. Defaults to config entry.", ) @click.option( "--no-ack", @@ -65,15 +65,20 @@ def send_message( quiet = ctx.obj["quiet"] if not aprs_login: - click.echo("Must set --aprs_login or APRS_LOGIN") - return + if not config.exists("aprs.login"): + click.echo("Must set --aprs_login or APRS_LOGIN") + ctx.exit(-1) + return + else: + config["aprs"]["login"] = aprs_login if not aprs_password: - click.echo("Must set --aprs-password or APRS_PASSWORD") - return - - config["aprs"]["login"] = aprs_login - config["aprs"]["password"] = aprs_password + if not config.exists("aprs.password"): + click.echo("Must set --aprs-password or APRS_PASSWORD") + ctx.exit(-1) + return + else: + config["aprs"]["password"] = aprs_password LOG.info(f"APRSD LISTEN Started version: {aprsd.__version__}") if type(command) is tuple: diff --git a/tests/cmds/__init__.py b/tests/cmds/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/tests/cmds/test_send_message.py b/tests/cmds/test_send_message.py new file mode 100644 index 0000000..e67e8f1 --- /dev/null +++ b/tests/cmds/test_send_message.py @@ -0,0 +1,94 @@ +import typing as t +import unittest +from unittest import mock + +from click.testing import CliRunner + +from aprsd import config as aprsd_config +from aprsd.aprsd import cli +from aprsd.cmds import send_message # noqa + + +F = t.TypeVar("F", bound=t.Callable[..., t.Any]) + + +class TestSendMessageCommand(unittest.TestCase): + + def _build_config(self, login=None, password=None): + config = {"aprs": {}} + if login: + config["aprs"]["login"] = login + + if password: + config["aprs"]["password"] = password + + return aprsd_config.Config(config) + + @mock.patch("aprsd.config.parse_config") + @mock.patch("aprsd.log.setup_logging") + def test_no_login(self, mock_logging, mock_parse_config): + """Make sure we get an error if there is no login and config.""" + + runner = CliRunner() + mock_parse_config.return_value = self._build_config() + + result = runner.invoke( + cli, ["send-message", "WB4BOR", "wx"], + catch_exceptions=False, + ) + # rich.print(f"EXIT CODE {result.exit_code}") + # rich.print(f"Exception {result.exception}") + # rich.print(f"OUTPUT {result.output}") + assert result.exit_code == -1 + assert "Must set --aprs_login or APRS_LOGIN" in result.output + + @mock.patch("aprsd.config.parse_config") + @mock.patch("aprsd.log.setup_logging") + def test_no_password(self, mock_logging, mock_parse_config): + """Make sure we get an error if there is no password and config.""" + + runner = CliRunner() + mock_parse_config.return_value = self._build_config(login="something") + + result = runner.invoke( + cli, ["send-message", "WB4BOR", "wx"], + catch_exceptions=False, + ) + assert result.exit_code == -1 + assert "Must set --aprs-password or APRS_PASSWORD" in result.output + + @mock.patch("aprsd.config.parse_config") + @mock.patch("aprsd.log.setup_logging") + def test_no_tocallsign(self, mock_logging, mock_parse_config): + """Make sure we get an error if there is no tocallsign.""" + + runner = CliRunner() + mock_parse_config.return_value = self._build_config( + login="something", + password="another", + ) + + result = runner.invoke( + cli, ["send-message"], + catch_exceptions=False, + ) + assert result.exit_code == 2 + assert "Error: Missing argument 'TOCALLSIGN'" in result.output + + @mock.patch("aprsd.config.parse_config") + @mock.patch("aprsd.log.setup_logging") + def test_no_command(self, mock_logging, mock_parse_config): + """Make sure we get an error if there is no command.""" + + runner = CliRunner() + mock_parse_config.return_value = self._build_config( + login="something", + password="another", + ) + + result = runner.invoke( + cli, ["send-message", "WB4BOR"], + catch_exceptions=False, + ) + assert result.exit_code == 2 + assert "Error: Missing argument 'COMMAND...'" in result.output