From 25c1c4a264ab084ed7f2339537269f8d5475a3e3 Mon Sep 17 00:00:00 2001 From: JonahKr <38377070+JonahKr@users.noreply.github.com> Date: Fri, 28 Aug 2020 14:42:21 +0200 Subject: [PATCH] Fixing Example and Adding Keyword Arguments as option for parameters (#37) Add ability to pass parameters to HermesApp object Co-authored-by: Koen Vervloesem Co-authored-by: Max Bachmann --- docs/usage.rst | 5 +- examples/async_advice_app.py | 2 +- rhasspyhermes_app/__init__.py | 18 ++++- tests/test_arguments.py | 136 ++++++++++++++++++++++++++++++++++ 4 files changed, 157 insertions(+), 4 deletions(-) create mode 100644 tests/test_arguments.py diff --git a/docs/usage.rst b/docs/usage.rst index 8205d48..dc76439 100644 --- a/docs/usage.rst +++ b/docs/usage.rst @@ -31,6 +31,9 @@ Try the example app `time_app.py`_ with the ``--help`` flag to see what settings .. _`time_app.py`: https://github.com/rhasspy/rhasspy-hermes-app/blob/master/examples/time_app.py +You can pass all the settings as keyword arguments inside the constructor aswell: +:meth:`HermesApp("ExampleApp", host = "192.168.178.123", port = 12183)` + ******* Asyncio ******* @@ -65,7 +68,7 @@ If the API of this library changes, your app possibly stops working when it upda .. code-block:: - rhasspy-hermes-app==0.2.0 + rhasspy-hermes-app==1.0.0 This way your app keeps working when the Rhasspy Hermes App adds incompatible changes in a new version. diff --git a/examples/async_advice_app.py b/examples/async_advice_app.py index 73dcaea..255280b 100644 --- a/examples/async_advice_app.py +++ b/examples/async_advice_app.py @@ -16,7 +16,7 @@ None of the authors, contributors, administrators, or anyone else connected with Rhasspy_Hermes_App, in any way whatsoever, can be responsible for your use of the api endpoint. """ -URL = 'https://api.advicslip.com/advice' +URL = 'https://api.adviceslip.com/advice' @app.on_intent("GetAdvice") async def get_advice(intent: NluIntent): diff --git a/rhasspyhermes_app/__init__.py b/rhasspyhermes_app/__init__.py index 83c07df..d6386b9 100644 --- a/rhasspyhermes_app/__init__.py +++ b/rhasspyhermes_app/__init__.py @@ -3,6 +3,7 @@ import asyncio import logging import re +from copy import deepcopy from dataclasses import dataclass from typing import Awaitable, Callable, Dict, List, Optional, Union @@ -85,6 +86,7 @@ def __init__( name: str, parser: Optional[argparse.ArgumentParser] = None, mqtt_client: Optional[mqtt.Client] = None, + **kwargs ): """Initialize the Rhasspy Hermes app. @@ -103,8 +105,18 @@ def __init__( # Add default arguments hermes_cli.add_hermes_args(parser) - # Parse command-line arguments - self.args = parser.parse_args() + # overwrite argument defaults inside parser with argparse.SUPPRESS + # so arguments that are not provided get ignored + suppress_parser = deepcopy(parser) + for action in suppress_parser._actions: + action.default = argparse.SUPPRESS + + supplied_args = vars(suppress_parser.parse_args()) + default_args = vars(parser.parse_args([])) + + # Command-line arguments take precedence over the arguments of the HermesApp.__init__ + args = {**default_args, **kwargs, **supplied_args} + self.args = argparse.Namespace(**args) # Set up logging hermes_cli.setup_logging(self.args) @@ -115,6 +127,7 @@ def __init__( mqtt_client = mqtt.Client() # Initialize HermesClient + # pylint: disable=no-member super().__init__(name, mqtt_client, site_ids=self.args.site_id) self._callbacks_hotword: List[Callable[[HotwordDetected], Awaitable[None]]] = [] @@ -593,6 +606,7 @@ def run(self): self._subscribe_callbacks() # Try to connect + # pylint: disable=no-member _LOGGER.debug("Connecting to %s:%s", self.args.host, self.args.port) hermes_cli.connect(self.mqtt_client, self.args) self.mqtt_client.loop_start() diff --git a/tests/test_arguments.py b/tests/test_arguments.py new file mode 100644 index 0000000..4f47220 --- /dev/null +++ b/tests/test_arguments.py @@ -0,0 +1,136 @@ +"""Tests for HermesApp arguments.""" +import argparse +import pytest +import sys + +from rhasspyhermes_app import HermesApp + + +def test_default_arguments(mocker): + """Test whether default arguments are set up correctly in a HermesApp object.""" + app = HermesApp("Test default arguments", mqtt_client=mocker.MagicMock()) + + assert app.args.host == "localhost" + assert app.args.port == 1883 + assert app.args.tls == False + assert app.args.username is None + assert app.args.password is None + + +def test_arguments_from_cli(mocker): + """Test whether arguments from the command line are set up correctly in a HermesApp object.""" + mocker.patch( + "sys.argv", + [ + "rhasspy-hermes-app-test", + "--host", + "rhasspy.home", + "--port", + "8883", + "--tls", + "--username", + "rhasspy-hermes-app", + "--password", + "test", + ], + ) + app = HermesApp("Test arguments in init", mqtt_client=mocker.MagicMock()) + + assert app.args.host == "rhasspy.home" + assert app.args.port == 8883 + assert app.args.tls == True + assert app.args.username == "rhasspy-hermes-app" + assert app.args.password == "test" + + +def test_arguments_in_init(mocker): + """Test whether arguments are set up correctly while initializing a HermesApp object.""" + app = HermesApp( + "Test arguments in init", + mqtt_client=mocker.MagicMock(), + host="rhasspy.home", + port=8883, + tls=True, + username="rhasspy-hermes-app", + password="test", + ) + + assert app.args.host == "rhasspy.home" + assert app.args.port == 8883 + assert app.args.tls == True + assert app.args.username == "rhasspy-hermes-app" + assert app.args.password == "test" + + +def test_if_cli_arguments_overwrite_init_arguments(mocker): + """Test whether arguments from the command line overwrite arguments to a HermesApp object.""" + mocker.patch( + "sys.argv", + [ + "rhasspy-hermes-app-test", + "--host", + "rhasspy.home", + "--port", + "1883", + "--username", + "rhasspy-hermes-app", + "--password", + "test", + ], + ) + app = HermesApp( + "Test arguments in init", + mqtt_client=mocker.MagicMock(), + host="rhasspy.local", + port=8883, + username="rhasspy-hermes-app-test", + password="covfefe", + ) + + assert app.args.host == "rhasspy.home" + assert app.args.port == 1883 + assert app.args.username == "rhasspy-hermes-app" + assert app.args.password == "test" + + +def test_if_cli_arguments_overwrite_init_arguments_with_argument_parser(mocker): + """Test whether arguments from the command line overwrite arguments to a HermesApp object + if the user supplies their own ArgumentParser object.""" + mocker.patch( + "sys.argv", + [ + "rhasspy-hermes-app-test", + "--host", + "rhasspy.home", + "--port", + "1883", + "--username", + "rhasspy-hermes-app", + "--password", + "test", + "--test-argument", + "foobar", + "--test-flag", + ], + ) + parser = argparse.ArgumentParser(prog="rhasspy-hermes-app-test") + parser.add_argument("--test-argument", default="foo") + parser.add_argument("--test-flag", action="store_true") + + app = HermesApp( + "Test arguments in init", + parser=parser, + mqtt_client=mocker.MagicMock(), + host="rhasspy.local", + port=8883, + username="rhasspy-hermes-app-test", + password="covfefe", + test_argument="bar", + ) + + assert app.args.host == "rhasspy.home" + assert app.args.port == 1883 + assert app.args.username == "rhasspy-hermes-app" + assert app.args.password == "test" + assert app.args.test_argument == "foobar" + assert app.args.test_flag == True