mirror of
https://github.com/caronc/apprise.git
synced 2025-08-10 00:38:02 +02:00
Added support for recent CPython and PyPy versions; Droped Python v2.7 Support (#680)
This commit is contained in:
@ -26,16 +26,9 @@
|
||||
from __future__ import print_function
|
||||
import re
|
||||
import sys
|
||||
import six
|
||||
import pytest
|
||||
import requests
|
||||
try:
|
||||
# Python 3.x
|
||||
from unittest import mock
|
||||
|
||||
except ImportError:
|
||||
# Python 2.7
|
||||
import mock
|
||||
from unittest import mock
|
||||
|
||||
from os.path import dirname
|
||||
from os.path import join
|
||||
@ -58,19 +51,14 @@ from apprise.plugins import __reset_matrix
|
||||
from apprise.utils import parse_list
|
||||
import inspect
|
||||
|
||||
# Sending notifications requires the coroutines to be awaited, so we need to
|
||||
# wrap the original function when mocking it.
|
||||
import apprise.py3compat.asyncio as py3aio
|
||||
|
||||
# Disable logging for a cleaner testing output
|
||||
import logging
|
||||
logging.disable(logging.CRITICAL)
|
||||
|
||||
# Sending notifications requires the coroutines to be awaited, so we need to
|
||||
# wrap the original function when mocking it. But don't import for Python 2.
|
||||
if not six.PY2:
|
||||
import apprise.py3compat.asyncio as py3aio
|
||||
else:
|
||||
class py3aio:
|
||||
def notify():
|
||||
pass
|
||||
|
||||
# Attachment Directory
|
||||
TEST_VAR_DIR = join(dirname(__file__), 'var')
|
||||
|
||||
@ -86,7 +74,6 @@ def test_apprise():
|
||||
apprise_test(do_notify)
|
||||
|
||||
|
||||
@pytest.mark.skipif(sys.version_info.major <= 2, reason="Requires Python 3.x+")
|
||||
def test_apprise_async():
|
||||
"""
|
||||
API: Apprise() object asynchronous methods
|
||||
@ -154,12 +141,12 @@ def apprise_test(do_notify):
|
||||
assert len(a) == 2
|
||||
|
||||
# We can retrieve elements from our list too by reference:
|
||||
assert isinstance(a[0].url(), six.string_types) is True
|
||||
assert isinstance(a[0].url(), str) is True
|
||||
|
||||
# We can iterate over our list too:
|
||||
count = 0
|
||||
for o in a:
|
||||
assert isinstance(o.url(), six.string_types) is True
|
||||
assert isinstance(o.url(), str) is True
|
||||
count += 1
|
||||
# verify that we did indeed iterate over each element
|
||||
assert len(a) == count
|
||||
@ -547,7 +534,6 @@ def test_apprise_tagging(mock_post, mock_get):
|
||||
|
||||
@mock.patch('requests.get')
|
||||
@mock.patch('requests.post')
|
||||
@pytest.mark.skipif(sys.version_info.major <= 2, reason="Requires Python 3.x+")
|
||||
def test_apprise_tagging_async(mock_post, mock_get):
|
||||
"""
|
||||
API: Apprise() object tagging functionality asynchronous methods
|
||||
@ -669,7 +655,6 @@ def apprise_tagging_test(mock_post, mock_get, do_notify):
|
||||
tag=[(object, ), ]) is None
|
||||
|
||||
|
||||
@pytest.mark.skipif(sys.version_info.major <= 2, reason="Requires Python 3.x+")
|
||||
def test_apprise_schemas(tmpdir):
|
||||
"""
|
||||
API: Apprise().schema() tests
|
||||
@ -918,20 +903,11 @@ def test_apprise_asset(tmpdir):
|
||||
must_exist=True) is not None
|
||||
|
||||
# Test case where we can't access the image file
|
||||
if sys.version_info.major <= 2:
|
||||
# Python v2.x
|
||||
with mock.patch('__builtin__.open', side_effect=OSError()):
|
||||
assert a.image_raw(NotifyType.INFO, NotifyImageSize.XY_256) is None
|
||||
with mock.patch('builtins.open', side_effect=OSError()):
|
||||
assert a.image_raw(NotifyType.INFO, NotifyImageSize.XY_256) is None
|
||||
|
||||
# Our content is retrivable again
|
||||
assert a.image_raw(NotifyType.INFO, NotifyImageSize.XY_256) is not None
|
||||
else:
|
||||
# Python >= v3.x
|
||||
with mock.patch('builtins.open', side_effect=OSError()):
|
||||
assert a.image_raw(NotifyType.INFO, NotifyImageSize.XY_256) is None
|
||||
|
||||
# Our content is retrivable again
|
||||
assert a.image_raw(NotifyType.INFO, NotifyImageSize.XY_256) is not None
|
||||
# Our content is retrivable again
|
||||
assert a.image_raw(NotifyType.INFO, NotifyImageSize.XY_256) is not None
|
||||
|
||||
# Disable all image references
|
||||
a = AppriseAsset(image_path_mask=False, image_url_mask=False)
|
||||
@ -1376,7 +1352,7 @@ def test_apprise_details():
|
||||
assert 'details' in entry['requirements']
|
||||
assert 'packages_required' in entry['requirements']
|
||||
assert 'packages_recommended' in entry['requirements']
|
||||
assert isinstance(entry['requirements']['details'], six.string_types)
|
||||
assert isinstance(entry['requirements']['details'], str)
|
||||
assert isinstance(entry['requirements']['packages_required'], list)
|
||||
assert isinstance(entry['requirements']['packages_recommended'], list)
|
||||
|
||||
@ -1403,7 +1379,7 @@ def test_apprise_details():
|
||||
assert 'details' in entry['requirements']
|
||||
assert 'packages_required' in entry['requirements']
|
||||
assert 'packages_recommended' in entry['requirements']
|
||||
assert isinstance(entry['requirements']['details'], six.string_types)
|
||||
assert isinstance(entry['requirements']['details'], str)
|
||||
assert isinstance(entry['requirements']['packages_required'], list)
|
||||
assert isinstance(entry['requirements']['packages_recommended'], list)
|
||||
|
||||
@ -1498,7 +1474,7 @@ def test_apprise_details_plugin_verification():
|
||||
# A Service Name MUST be defined
|
||||
assert 'service_name' in entry
|
||||
assert isinstance(
|
||||
entry['service_name'], (six.string_types, LazyTranslation))
|
||||
entry['service_name'], (str, LazyTranslation))
|
||||
|
||||
# Acquire our protocols
|
||||
protocols = parse_list(
|
||||
@ -1527,10 +1503,10 @@ def test_apprise_details_plugin_verification():
|
||||
if 'alias_of' not in arg:
|
||||
# Minimum requirement of an argument
|
||||
assert 'name' in arg
|
||||
assert isinstance(arg['name'], six.string_types)
|
||||
assert isinstance(arg['name'], str)
|
||||
|
||||
assert 'type' in arg
|
||||
assert isinstance(arg['type'], six.string_types)
|
||||
assert isinstance(arg['type'], str)
|
||||
assert is_valid_type_re.match(arg['type']) is not None
|
||||
|
||||
if 'min' in arg:
|
||||
@ -1555,7 +1531,7 @@ def test_apprise_details_plugin_verification():
|
||||
assert isinstance(arg['required'], bool)
|
||||
|
||||
if 'prefix' in arg:
|
||||
assert isinstance(arg['prefix'], six.string_types)
|
||||
assert isinstance(arg['prefix'], str)
|
||||
if section == 'kwargs':
|
||||
# The only acceptable prefix types for kwargs
|
||||
assert arg['prefix'] in (':', '+', '-')
|
||||
@ -1566,7 +1542,7 @@ def test_apprise_details_plugin_verification():
|
||||
|
||||
if 'map_to' in arg:
|
||||
# must be a string
|
||||
assert isinstance(arg['map_to'], six.string_types)
|
||||
assert isinstance(arg['map_to'], str)
|
||||
# Track our map_to object
|
||||
map_to_entries.add(arg['map_to'])
|
||||
|
||||
@ -1601,9 +1577,9 @@ def test_apprise_details_plugin_verification():
|
||||
# Regex must ALWAYS be in the format (regex, option)
|
||||
assert isinstance(arg['regex'], (tuple, list))
|
||||
assert len(arg['regex']) == 2
|
||||
assert isinstance(arg['regex'][0], six.string_types)
|
||||
assert isinstance(arg['regex'][0], str)
|
||||
assert arg['regex'][1] is None or isinstance(
|
||||
arg['regex'][1], six.string_types)
|
||||
arg['regex'][1], str)
|
||||
|
||||
# Compile the regular expression to verify that it is
|
||||
# valid
|
||||
@ -1632,10 +1608,10 @@ def test_apprise_details_plugin_verification():
|
||||
|
||||
# must be a string
|
||||
assert isinstance(
|
||||
arg['alias_of'], (six.string_types, list, tuple, set))
|
||||
arg['alias_of'], (str, list, tuple, set))
|
||||
|
||||
aliases = [arg['alias_of']] \
|
||||
if isinstance(arg['alias_of'], six.string_types) \
|
||||
if isinstance(arg['alias_of'], str) \
|
||||
else arg['alias_of']
|
||||
|
||||
for alias_of in aliases:
|
||||
@ -1687,7 +1663,7 @@ def test_apprise_details_plugin_verification():
|
||||
# 'alias_of': ('apitoken', 'webtoken'),
|
||||
# },
|
||||
# }
|
||||
if isinstance(arg['alias_of'], six.string_types):
|
||||
if isinstance(arg['alias_of'], str):
|
||||
assert len(entry['details'][section][key]) == 1
|
||||
else: # is tuple,list, or set
|
||||
assert len(entry['details'][section][key]) == 2
|
||||
@ -1711,23 +1687,12 @@ def test_apprise_details_plugin_verification():
|
||||
(tuple, set, list),
|
||||
)
|
||||
|
||||
if six.PY2:
|
||||
# inspect our object
|
||||
# getargspec() is deprecated in Python v3
|
||||
spec = inspect.getargspec(
|
||||
common.NOTIFY_SCHEMA_MAP[protocols[0]].__init__)
|
||||
spec = inspect.getfullargspec(
|
||||
common.NOTIFY_SCHEMA_MAP[protocols[0]].__init__)
|
||||
|
||||
function_args = \
|
||||
(set(parse_list(spec.keywords)) - set(['kwargs'])) \
|
||||
| (set(spec.args) - set(['self'])) | valid_kwargs
|
||||
else:
|
||||
# Python v3+ uses getfullargspec()
|
||||
spec = inspect.getfullargspec(
|
||||
common.NOTIFY_SCHEMA_MAP[protocols[0]].__init__)
|
||||
|
||||
function_args = \
|
||||
(set(parse_list(spec.varkw)) - set(['kwargs'])) \
|
||||
| (set(spec.args) - set(['self'])) | valid_kwargs
|
||||
function_args = \
|
||||
(set(parse_list(spec.varkw)) - set(['kwargs'])) \
|
||||
| (set(spec.args) - set(['self'])) | valid_kwargs
|
||||
|
||||
# Iterate over our map_to_entries and make sure that everything
|
||||
# maps to a function argument
|
||||
@ -1790,7 +1755,6 @@ def test_apprise_details_plugin_verification():
|
||||
assert arg in defined_tokens
|
||||
|
||||
|
||||
@pytest.mark.skipif(sys.version_info.major <= 2, reason="Requires Python 3.x+")
|
||||
@mock.patch('requests.post')
|
||||
@mock.patch('apprise.py3compat.asyncio.notify', wraps=py3aio.notify)
|
||||
def test_apprise_async_mode(mock_async_notify, mock_post, tmpdir):
|
||||
@ -1902,13 +1866,13 @@ def test_notify_matrix_dynamic_importing(tmpdir):
|
||||
# Test no app_id
|
||||
base.join('NotifyBadFile1.py').write(
|
||||
"""
|
||||
class NotifyBadFile1(object):
|
||||
class NotifyBadFile1:
|
||||
pass""")
|
||||
|
||||
# No class of the same name
|
||||
base.join('NotifyBadFile2.py').write(
|
||||
"""
|
||||
class BadClassName(object):
|
||||
class BadClassName:
|
||||
pass""")
|
||||
|
||||
# Exception thrown
|
||||
|
Reference in New Issue
Block a user