mirror of https://github.com/caronc/apprise
Bugfix: Decorator handles multiple URLs correctly now (#678)
parent
e9f040a2d0
commit
f7244cce3d
|
@ -41,6 +41,10 @@ install:
|
||||||
- if [[ $TOXENV != 'bare' ]]; then pip install -r all-plugin-requirements.txt; fi
|
- if [[ $TOXENV != 'bare' ]]; then pip install -r all-plugin-requirements.txt; fi
|
||||||
# pypy and bare installs do not include dbus-python
|
# pypy and bare installs do not include dbus-python
|
||||||
- if [[ $TOXENV != 'bare' ]] && [[ $TRAVIS_PYTHON_VERSION != 'pypy'* ]]; then travis_retry pip install dbus-python; fi
|
- 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
|
# run tests
|
||||||
script:
|
script:
|
||||||
|
|
|
@ -52,24 +52,6 @@ class CustomNotifyPlugin(NotifyBase):
|
||||||
'{schema}://',
|
'{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
|
@staticmethod
|
||||||
def parse_url(url):
|
def parse_url(url):
|
||||||
"""
|
"""
|
||||||
|
@ -112,7 +94,7 @@ class CustomNotifyPlugin(NotifyBase):
|
||||||
url = '{}://'.format(plugin_name)
|
url = '{}://'.format(plugin_name)
|
||||||
|
|
||||||
# Keep a default set of arguments to apply to all called references
|
# 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)
|
url, default_schema=plugin_name, verify_host=False, simple=True)
|
||||||
|
|
||||||
if plugin_name in common.NOTIFY_SCHEMA_MAP:
|
if plugin_name in common.NOTIFY_SCHEMA_MAP:
|
||||||
|
@ -145,7 +127,25 @@ class CustomNotifyPlugin(NotifyBase):
|
||||||
__send = staticmethod(send_func)
|
__send = staticmethod(send_func)
|
||||||
|
|
||||||
# Update our default arguments
|
# 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,
|
def send(self, body, title='', notify_type=common.NotifyType.INFO,
|
||||||
*args, **kwargs):
|
*args, **kwargs):
|
||||||
|
|
|
@ -26,6 +26,7 @@ from os.path import dirname
|
||||||
from os.path import join
|
from os.path import join
|
||||||
from apprise.decorators import notify
|
from apprise.decorators import notify
|
||||||
from apprise import Apprise
|
from apprise import Apprise
|
||||||
|
from apprise import AppriseConfig
|
||||||
from apprise import AppriseAsset
|
from apprise import AppriseAsset
|
||||||
from apprise import AppriseAttachment
|
from apprise import AppriseAttachment
|
||||||
from apprise import common
|
from apprise import common
|
||||||
|
@ -308,3 +309,140 @@ def test_notify_complex_decoration():
|
||||||
|
|
||||||
# Tidy
|
# Tidy
|
||||||
del common.NOTIFY_SCHEMA_MAP['utiltest']
|
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']
|
||||||
|
|
1
tox.ini
1
tox.ini
|
@ -35,7 +35,6 @@ deps=
|
||||||
commands =
|
commands =
|
||||||
python setup.py compile_catalog
|
python setup.py compile_catalog
|
||||||
coverage run --parallel -m pytest {posargs}
|
coverage run --parallel -m pytest {posargs}
|
||||||
flake8 . --count --show-source --statistics
|
|
||||||
|
|
||||||
[testenv:py38]
|
[testenv:py38]
|
||||||
deps=
|
deps=
|
||||||
|
|
Loading…
Reference in New Issue