diff --git a/.travis.yml b/.travis.yml index de7698d3..8088d5d0 100644 --- a/.travis.yml +++ b/.travis.yml @@ -41,6 +41,10 @@ install: - if [[ $TOXENV != 'bare' ]]; then pip install -r all-plugin-requirements.txt; fi # pypy and bare installs do not include dbus-python - if [[ $TOXENV != 'bare' ]] && [[ $TRAVIS_PYTHON_VERSION != 'pypy'* ]]; then travis_retry pip install dbus-python; fi + # Python 3.7 importlib-metadata becomes incompatible with flake8 unless we use + # a version that still supports EntryPoints.get(); tox.ini updated to not call flake; this was + # the only way around the Travis CI Builder issues + - if [[ $TOXENV == 'py37' ]]; then pip uninstall --yes flake8; fi # run tests script: diff --git a/apprise/decorators/CustomNotifyPlugin.py b/apprise/decorators/CustomNotifyPlugin.py index fa487558..04f8c168 100644 --- a/apprise/decorators/CustomNotifyPlugin.py +++ b/apprise/decorators/CustomNotifyPlugin.py @@ -52,24 +52,6 @@ class CustomNotifyPlugin(NotifyBase): '{schema}://', ) - # Our default arguments will get populated after we're instatiated by the - # wrapper class - _default_args = {} - - def __init__(self, **kwargs): - """ - Our initialization - - """ - super(CustomNotifyPlugin, self).__init__(**kwargs) - - # Apply our updates based on what was parsed - dict_full_update(self._default_args, kwargs) - - # Update our arguments (applying them to what we originally) - # initialized as - self._default_args['url'] = url_assembly(**self._default_args) - @staticmethod def parse_url(url): """ @@ -112,7 +94,7 @@ class CustomNotifyPlugin(NotifyBase): url = '{}://'.format(plugin_name) # Keep a default set of arguments to apply to all called references - default_args = parse_url( + base_args = parse_url( url, default_schema=plugin_name, verify_host=False, simple=True) if plugin_name in common.NOTIFY_SCHEMA_MAP: @@ -145,7 +127,25 @@ class CustomNotifyPlugin(NotifyBase): __send = staticmethod(send_func) # Update our default arguments - _default_args = default_args + _base_args = base_args + + def __init__(self, **kwargs): + """ + Our initialization + + """ + # init parent + super(CustomNotifyPluginWrapper, self).__init__(**kwargs) + + self._default_args = {} + + # Apply our updates based on what was parsed + dict_full_update(self._default_args, self._base_args) + dict_full_update(self._default_args, kwargs) + + # Update our arguments (applying them to what we originally) + # initialized as + self._default_args['url'] = url_assembly(**self._default_args) def send(self, body, title='', notify_type=common.NotifyType.INFO, *args, **kwargs): diff --git a/test/test_decorator_notify.py b/test/test_decorator_notify.py index e8536f3a..0d0a2ac0 100644 --- a/test/test_decorator_notify.py +++ b/test/test_decorator_notify.py @@ -26,6 +26,7 @@ from os.path import dirname from os.path import join from apprise.decorators import notify from apprise import Apprise +from apprise import AppriseConfig from apprise import AppriseAsset from apprise import AppriseAttachment from apprise import common @@ -308,3 +309,140 @@ def test_notify_complex_decoration(): # Tidy del common.NOTIFY_SCHEMA_MAP['utiltest'] + + +def test_notify_multi_instance_decoration(tmpdir): + """decorators: Test multi-instance @notify + """ + + # Verify our schema we're about to declare doesn't already exist + # in our schema map: + assert 'multi' not in common.NOTIFY_SCHEMA_MAP + + verify_obj = [] + + # Define a function here on the spot + @notify(on="multi", name="Apprise @notify Decorator Testing") + def my_inline_notify_wrapper( + body, title, notify_type, attach, meta, *args, **kwargs): + + # Track what is added + verify_obj.append({ + 'body': body, + 'title': title, + 'notify_type': notify_type, + 'attach': attach, + 'meta': meta, + 'args': args, + 'kwargs': kwargs, + }) + + # Now after our hook being inline... it's been loaded + assert 'multi' in common.NOTIFY_SCHEMA_MAP + + # Prepare our config + t = tmpdir.mkdir("multi-test").join("apprise.yml") + t.write("""urls: + - multi://user1:pass@hostname + - multi://user2:pass2@hostname + """) + + # Create ourselves a config object + ac = AppriseConfig(paths=str(t)) + + # Create ourselves an apprise object + aobj = Apprise() + + # Add our configuration + aobj.add(ac) + + # The number of configuration files that exist + assert len(ac) == 1 + + # no notifications are loaded + assert len(ac.servers()) == 2 + + # Nothing stored yet in our object + assert len(verify_obj) == 0 + + assert aobj.notify("Hello World", title="My Title") is True + + assert len(verify_obj) == 2 + + # Python 3.6 does not nessisarily return list in order + # So let's be sure it's sorted by the user id field to make the remaining + # checks on this test easy + verify_obj = sorted(verify_obj, key=lambda x: x['meta']['user']) + + # Our content was populated after the notify() call + obj = verify_obj[0] + assert obj['body'] == "Hello World" + assert obj['title'] == "My Title" + assert obj['notify_type'] == common.NotifyType.INFO + + meta = obj['meta'] + assert isinstance(meta, dict) + + # No format was defined + assert 'body_format' in obj['kwargs'] + assert obj['kwargs']['body_format'] is None + + # The meta argument allows us to further parse the URL parameters + # specified + assert isinstance(obj['kwargs'], dict) + + assert 'asset' in meta + assert isinstance(meta['asset'], AppriseAsset) + + assert 'tag' in meta + assert isinstance(meta['tag'], set) + + assert len(meta) == 7 + # We carry all of our default arguments from the @notify's initialization + assert meta['schema'] == 'multi' + assert meta['host'] == 'hostname' + assert meta['user'] == 'user1' + assert meta['password'] == 'pass' + + # Verify our URL is correct + assert meta['url'] == 'multi://user1:pass@hostname' + + # + # Now verify our second URL saved correct + # + + # Our content was populated after the notify() call + obj = verify_obj[1] + assert obj['body'] == "Hello World" + assert obj['title'] == "My Title" + assert obj['notify_type'] == common.NotifyType.INFO + + meta = obj['meta'] + assert isinstance(meta, dict) + + # No format was defined + assert 'body_format' in obj['kwargs'] + assert obj['kwargs']['body_format'] is None + + # The meta argument allows us to further parse the URL parameters + # specified + assert isinstance(obj['kwargs'], dict) + + assert 'asset' in meta + assert isinstance(meta['asset'], AppriseAsset) + + assert 'tag' in meta + assert isinstance(meta['tag'], set) + + assert len(meta) == 7 + # We carry all of our default arguments from the @notify's initialization + assert meta['schema'] == 'multi' + assert meta['host'] == 'hostname' + assert meta['user'] == 'user2' + assert meta['password'] == 'pass2' + + # Verify our URL is correct + assert meta['url'] == 'multi://user2:pass2@hostname' + + # Tidy + del common.NOTIFY_SCHEMA_MAP['multi'] diff --git a/tox.ini b/tox.ini index 734249db..a3652a98 100644 --- a/tox.ini +++ b/tox.ini @@ -35,7 +35,6 @@ deps= commands = python setup.py compile_catalog coverage run --parallel -m pytest {posargs} - flake8 . --count --show-source --statistics [testenv:py38] deps=