Skip to content

Commit

Permalink
completed yaml and added text based tests
Browse files Browse the repository at this point in the history
  • Loading branch information
caronc committed Oct 7, 2023
1 parent 6535602 commit 03a6e84
Show file tree
Hide file tree
Showing 3 changed files with 96 additions and 38 deletions.
57 changes: 28 additions & 29 deletions apprise/config/ConfigBase.py
Original file line number Diff line number Diff line change
Expand Up @@ -374,7 +374,7 @@ def __normalize_tag_groups(group_tags):
"""
# Prepare a key set list we can use
tag_groups = set([x for x in group_tags.keys()])
tag_groups = set([str(x) for x in group_tags.keys()])

def _expand(tags, ignore=None):
"""
Expand All @@ -394,10 +394,6 @@ def _expand(tags, ignore=None):
if tag in ignore:
continue

if tag not in tag_groups:
results.add(tag)
continue

# Track our groups
groups.add(tag)

Expand All @@ -413,7 +409,7 @@ def _expand(tags, ignore=None):
if gtag in ignore:
continue

# Go deeper
# Go deeper (recursion)
ignore.add(tag)
group_tags[gtag] = _expand(set([gtag]), ignore=ignore)
results |= group_tags[gtag]
Expand All @@ -425,7 +421,7 @@ def _expand(tags, ignore=None):

for tag in tag_groups:
# Get our tags
group_tags[tag] = _expand(set([tag]))
group_tags[tag] |= _expand(set([tag]))
if not group_tags[tag]:
ConfigBase.logger.warning(
'The group {} has no tags assigned to it'.format(tag))
Expand Down Expand Up @@ -643,14 +639,6 @@ def config_parse_text(content, asset=None):
r'((?P<url>[a-z0-9]{2,9}://.*)|(?P<assign>[a-z0-9, \t_-]+))|'
r'include\s+(?P<config>.+))?\s*$', re.I)

def _expanded(tags, carry=None):
"""
Recursively expands a tag specified
"""

# Initialize our carry forward
carry = {} if carry is None else carry

try:
# split our content up to read line by line
content = re.split(r'\r*\n', content)
Expand Down Expand Up @@ -701,7 +689,7 @@ def _expanded(tags, carry=None):
else cwe312_url(url)

if assign:
groups = set(parse_list(result.group('tags')))
groups = set(parse_list(result.group('tags'), cast=str))
if not groups:
# no tags were assigned
ConfigBase.logger.warning(
Expand All @@ -710,7 +698,7 @@ def _expanded(tags, carry=None):
continue

# Get our tags
tags = set(parse_list(assign))
tags = set(parse_list(assign, cast=str))
if not tags:
# no tags were assigned
ConfigBase.logger.warning(
Expand Down Expand Up @@ -739,7 +727,7 @@ def _expanded(tags, carry=None):

# Build a list of tags to associate with the newly added
# notifications if any were set
results['tag'] = set(parse_list(result.group('tags')))
results['tag'] = set(parse_list(result.group('tags'), cast=str))

# Set our Asset Object
results['asset'] = asset
Expand Down Expand Up @@ -908,7 +896,7 @@ def config_parse_yaml(content, asset=None):
tags = result.get('tag', None)
if tags and isinstance(tags, (list, tuple, str)):
# Store any preset tags
global_tags = set(parse_list(tags))
global_tags = set(parse_list(tags, cast=str))

#
# groups root directive
Expand All @@ -926,16 +914,27 @@ def config_parse_yaml(content, asset=None):
entry, no + 1))
continue

for group, tags in entry.items():
for _groups, tags in entry.items():
for group in parse_list(_groups, cast=str):
if isinstance(tags, (list, tuple)):
_tags = set()
for e in tags:
if isinstance(e, dict):
_tags |= set(e.keys())
else:
_tags |= set(parse_list(e, cast=str))

# Final assignment
tags = _tags

if isinstance(tags, dict):
# Allow entries with comments
tags = set(tags.keys())
else:
tags = set(parse_list(tags, cast=str))

else: # isinstance(tags, (str, list, tuple)):
tags = set(parse_list(tags))
if group not in group_tags:
group_tags[group] = tags

group_tags[group] = tags
else:
group_tags[group] |= tags

#
# include root directive
Expand Down Expand Up @@ -1127,8 +1126,8 @@ def config_parse_yaml(content, asset=None):
# The below ensures our tags are set correctly
if 'tag' in _results:
# Tidy our list up
_results['tag'] = \
set(parse_list(_results['tag'])) | global_tags
_results['tag'] = set(
parse_list(_results['tag'], cast=str)) | global_tags

else:
# Just use the global settings
Expand Down Expand Up @@ -1201,7 +1200,7 @@ def config_parse_yaml(content, asset=None):
ConfigBase.logger.warning(
'Could not load Apprise YAML configuration '
'entry #{}, item #{}'
.format(results['entry'], results['item']))
.format(entry['entry'], entry['item']))
ConfigBase.logger.debug('Loading Exception: %s' % str(e))
continue

Expand Down
6 changes: 4 additions & 2 deletions apprise/utils.py
Original file line number Diff line number Diff line change
Expand Up @@ -1120,7 +1120,7 @@ def urlencode(query, doseq=False, safe='', encoding=None, errors=None):
errors=errors)


def parse_list(*args):
def parse_list(*args, cast=None):
"""
Take a string list and break it into a delimited
list of arguments. This funciton also supports
Expand All @@ -1143,6 +1143,9 @@ def parse_list(*args):

result = []
for arg in args:
if not isinstance(arg, (str, set, list, bool, tuple)) and arg and cast:
arg = cast(arg)

if isinstance(arg, str):
result += re.split(STRING_DELIMITERS, arg)

Expand All @@ -1155,7 +1158,6 @@ def parse_list(*args):
# Since Python v3 returns a filter (iterator) whereas Python v2 returned
# a list, we need to change it into a list object to remain compatible with
# both distribution types.
# TODO: Review after dropping support for Python 2.
return sorted([x for x in filter(bool, list(set(result)))])


Expand Down
71 changes: 64 additions & 7 deletions test/test_config_base.py
Original file line number Diff line number Diff line change
Expand Up @@ -377,6 +377,9 @@ def test_config_base_config_tag_groups_text():
# Tag that recursively looks to more tags
groupD = groupC
# Assigned ourselves
groupX = groupX
# Set up a recursive loop
groupE = groupF
groupF = groupE
Expand All @@ -388,8 +391,16 @@ def test_config_base_config_tag_groups_text():
groupJ = groupK
groupK = groupG
# Bad assignments
groupM = , , ,
, , = , , ,
# int's and floats are okay
1 = 2
a = 5
# A comment line over top of a URL
groupB = mailto://userb:[email protected]
4, groupB = mailto://userb:[email protected]
# Tag Assignments
tagA,groupB=json://localhost
Expand All @@ -408,8 +419,9 @@ def test_config_base_config_tag_groups_text():
assert len(result) == 4

# Our first element is our group tags
assert len(result[0].tags) == 1
assert len(result[0].tags) == 2
assert 'groupB' in result[0].tags
assert '4' in result[0].tags

# No additional configuration is loaded
assert len(config) == 0
Expand All @@ -424,6 +436,22 @@ def test_config_base_config_tag_groups_text():
assert len([x for x in apobj.find('groupC')]) == 2
assert len([x for x in apobj.find('groupD')]) == 3

# Invalid Assignment
result, config = ConfigBase.config_parse_text("""
# Must have something to equal or it's a bad line
group =
# A tag Assignments that is never gotten to as the line
# above is bad
groupD=form://localhost
""")

# We expect to parse 3 entries from the above
assert isinstance(result, list)
assert isinstance(config, list)
assert len(result) == 0
assert len(config) == 0

# Invalid Assignment
result, config = ConfigBase.config_parse_text("""
# Rundant assignment
Expand Down Expand Up @@ -1160,17 +1188,40 @@ def test_config_base_config_tag_groups_yaml():
# No assignment type 2
- group5:
# Integer assignment
- group6: 3
- group6: 3, 4, 5, test
- group6: 3.5, tagC
# Recursion
- groupA: groupB
- groupB: groupA
# And Again... (just because)
- groupA: groupB
- groupB: groupA
# Self assignment
- groupX: groupX
# Set up a larger recursive loop
- groupG: groupH
- groupH: groupI
- groupI: groupJ
- groupJ: groupK
- groupH: groupI, groupJ
- groupI: groupJ, groupG
- groupJ: groupK, groupH, groupI
- groupK: groupG
# No tags assigned
- groupK: ",, , ,"
- " , ": ",, , ,"
# Multi Assignments
- groupL, groupM: tagD, tagA
- 4, groupN:
- tagD
- tagE, TagA
# Add one more tag to groupL making it different then GroupM by 1
- groupL: tagB
#
# Define your notification urls:
#
Expand All @@ -1192,8 +1243,11 @@ def test_config_base_config_tag_groups_yaml():
assert len(result) == 4

# Our first element is our group tags
assert len(result[0].tags) == 2
assert len(result[0].tags) == 5
assert 'group2' in result[0].tags
assert 'group3' in result[0].tags
assert 'groupL' in result[0].tags
assert 'groupM' in result[0].tags
assert 'tagA' in result[0].tags

# No additional configuration is loaded
Expand All @@ -1208,9 +1262,12 @@ def test_config_base_config_tag_groups_yaml():
assert len([x for x in apobj.find('tagD')]) == 1
assert len([x for x in apobj.find('group1')]) == 2
assert len([x for x in apobj.find('group2')]) == 3
assert len([x for x in apobj.find('group3')]) == 2 # Fix this as this IS the value we want
assert len([x for x in apobj.find('group3')]) == 2
assert len([x for x in apobj.find('group4')]) == 0
assert len([x for x in apobj.find('group5')]) == 0
assert len([x for x in apobj.find('group6')]) == 2
assert len([x for x in apobj.find('4')]) == 1
assert len([x for x in apobj.find('groupN')]) == 1


def test_config_base_config_parse_yaml_globals():
Expand Down

0 comments on commit 03a6e84

Please sign in to comment.