def test_config_base_config_parse_yaml_list():
    """
    API: ConfigBase.config_parse_yaml list parsing

    """

    # general reference used below
    asset = AppriseAsset()

    # Invalid url/schema
    result, config = ConfigBase.config_parse_yaml("""
# no lists... just no
urls: [milk, pumpkin pie, eggs, juice]

# Including by list is okay
include: [file:///absolute/path/, relative/path, http://test.com]

""",
                                                  asset=asset)

    # Invalid data gets us an empty result set
    assert isinstance(result, list)
    assert len(result) == 0

    # There were 3 include entries
    assert len(config) == 3
    assert 'file:///absolute/path/' in config
    assert 'relative/path' in config
    assert 'http://test.com' in config
def test_yaml_vs_text_tagging():
    """
    API: ConfigBase YAML vs TEXT tagging
    """

    yaml_result, _ = ConfigBase.config_parse_yaml("""
    urls:
      - mailtos://lead2gold:[email protected]:
         tag: mytag
    """)
    assert yaml_result

    text_result, _ = ConfigBase.config_parse_text("""
    mytag=mailtos://lead2gold:[email protected]
    """)
    assert text_result

    # Now we compare our results and verify they are the same
    assert len(yaml_result) == len(text_result)
    assert isinstance(yaml_result[0], plugins.NotifyEmail)
    assert isinstance(text_result[0], plugins.NotifyEmail)
    assert 'mytag' in text_result[0]
    assert 'mytag' in yaml_result[0]
def test_config_base_config_parse_yaml():
    """
    API: ConfigBase.config_parse_yaml object

    """

    # general reference used below
    asset = AppriseAsset()

    # Garbage Handling
    assert isinstance(ConfigBase.config_parse_yaml(object()), list)
    assert isinstance(ConfigBase.config_parse_yaml(None), list)
    assert isinstance(ConfigBase.config_parse_yaml(''), list)

    # Invalid Version
    result = ConfigBase.config_parse_yaml("version: 2a", asset=asset)

    # Invalid data gets us an empty result set
    assert isinstance(result, list)
    assert len(result) == 0

    # Invalid Syntax (throws a ScannerError)
    result = ConfigBase.config_parse_yaml("""
# if no version is specified then version 1 is presumed
version: 1

urls
""",
                                          asset=asset)

    # Invalid data gets us an empty result set
    assert isinstance(result, list)
    assert len(result) == 0

    # Missing url token
    result = ConfigBase.config_parse_yaml("""
# if no version is specified then version 1 is presumed
version: 1

""",
                                          asset=asset)

    # Invalid data gets us an empty result set
    assert isinstance(result, list)
    assert len(result) == 0

    # No urls defined
    result = ConfigBase.config_parse_yaml("""
# if no version is specified then version 1 is presumed
version: 1

urls:
""",
                                          asset=asset)

    # Invalid data gets us an empty result set
    assert isinstance(result, list)
    assert len(result) == 0

    # Invalid url defined
    result = ConfigBase.config_parse_yaml("""
# if no version is specified then version 1 is presumed
version: 1

# Invalid URL definition; yet the answer to life at the same time
urls: 43
""",
                                          asset=asset)

    # Invalid data gets us an empty result set
    assert isinstance(result, list)
    assert len(result) == 0

    # Invalid url/schema
    result = ConfigBase.config_parse_yaml("""
# if no version is specified then version 1 is presumed
version: 1

urls:
  - invalid://

""",
                                          asset=asset)

    # Invalid data gets us an empty result set
    assert isinstance(result, list)
    assert len(result) == 0

    # Invalid url/schema
    result = ConfigBase.config_parse_yaml("""
# if no version is specified then version 1 is presumed
version: 1

urls:
  - invalid://:
    - a: b

""",
                                          asset=asset)

    # Invalid data gets us an empty result set
    assert isinstance(result, list)
    assert len(result) == 0

    # Invalid url/schema
    result = ConfigBase.config_parse_yaml("""
urls:
  - just some free text that isn't valid:
    - a garbage entry to go with it

""",
                                          asset=asset)

    # Invalid data gets us an empty result set
    assert isinstance(result, list)
    assert len(result) == 0

    # Invalid url/schema
    result = ConfigBase.config_parse_yaml("""
# if no version is specified then version 1 is presumed
version: 1

urls:
  - not even a proper url

""",
                                          asset=asset)

    # Invalid data gets us an empty result set
    assert isinstance(result, list)
    assert len(result) == 0

    # Invalid url/schema
    result = ConfigBase.config_parse_yaml("""
# no lists... just no
urls: [milk, pumpkin pie, eggs, juice]

""",
                                          asset=asset)

    # Invalid data gets us an empty result set
    assert isinstance(result, list)
    assert len(result) == 0

    # Invalid url/schema
    result = ConfigBase.config_parse_yaml("""
urls:
  # a very invalid sns entry
  - sns://T1JJ3T3L2/
  - sns://:@/:
    - invalid: test
  - sns://T1JJ3T3L2/:
    - invalid: test

  # some strangness
  -
    -
      - test

""",
                                          asset=asset)

    # Invalid data gets us an empty result set
    assert isinstance(result, list)
    assert len(result) == 0

    # Valid Configuration
    result = ConfigBase.config_parse_yaml("""
# if no version is specified then version 1 is presumed
version: 1

#
# Define your notification urls:
#
urls:
  - pbul://o.gn5kj6nfhv736I7jC3cj3QLRiyhgl98b
  - mailto://test:[email protected]
""",
                                          asset=asset)

    # We expect to parse 2 entries from the above
    assert isinstance(result, list)
    assert len(result) == 2
    assert len(result[0].tags) == 0

    # Valid Configuration
    result = ConfigBase.config_parse_yaml("""
urls:
  - json://localhost:
    - tag: my-custom-tag, my-other-tag

  # How to stack multiple entries:
  - mailto://:
    - user: jeff
      pass: 123abc
      from: [email protected]

    - user: jack
      pass: pass123
      from: [email protected]

      # This is an illegal entry; the schema can not be changed
      schema: json

  # accidently left a colon at the end of the url; no problem
  # we'll accept it
  - mailto://oscar:[email protected]:

  # A telegram entry (returns a None in parse_url())
  - tgram://invalid

""",
                                          asset=asset)

    # We expect to parse 4 entries from the above because the tgram:// entry
    # would have failed to be loaded
    assert isinstance(result, list)
    assert len(result) == 4
    assert len(result[0].tags) == 2

    # Global Tags
    result = ConfigBase.config_parse_yaml("""
# Global Tags stacked as a list
tag:
  - admin
  - devops

urls:
  - json://localhost
  - dbus://
""",
                                          asset=asset)

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

    # all entries will have our global tags defined in them
    for entry in result:
        assert 'admin' in entry.tags
        assert 'devops' in entry.tags

    # Global Tags
    result = ConfigBase.config_parse_yaml("""
# Global Tags
tag: admin, devops

urls:
  # The following tags will get added to the global set
  - json://localhost:
    - tag: string-tag, my-other-tag, text

  # Tags can be presented in this list format too:
  - dbus://:
    - tag:
      - list-tag
      - dbus
""",
                                          asset=asset)

    # all entries will have our global tags defined in them
    for entry in result:
        assert 'admin' in entry.tags
        assert 'devops' in entry.tags

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

    # json:// has 2 globals + 3 defined
    assert len(result[0].tags) == 5
    assert 'text' in result[0].tags

    # json:// has 2 globals + 2 defined
    assert len(result[1].tags) == 4
    assert 'list-tag' in result[1].tags

    # An invalid set of entries
    result = ConfigBase.config_parse_yaml("""
urls:
  # The following tags will get added to the global set
  - json://localhost:
    -
      -
        - entry
""",
                                          asset=asset)

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

    # An asset we'll manipulate
    asset = AppriseAsset()

    # Global Tags
    result = ConfigBase.config_parse_yaml("""
# Test the creation of our apprise asset object
asset:
  app_id: AppriseTest
  app_desc: Apprise Test Notifications
  app_url: http://nuxref.com

  # Support setting empty values
  image_url_mask:
  image_url_logo:

  image_path_mask: tmp/path

  # invalid entry
  theme:
    -
      -
        - entry

  # Now for some invalid entries
  invalid: entry
  __init__: can't be over-ridden
  nolists:
    - we don't support these entries
    - in the apprise object

urls:
  - json://localhost:
""",
                                          asset=asset)

    # We expect to parse 3 entries from the above
    assert isinstance(result, list)
    assert len(result) == 1
    assert asset.app_id == "AppriseTest"
    assert asset.app_desc == "Apprise Test Notifications"
    assert asset.app_url == "http://nuxref.com"

    # the theme was not updated and remains the same as it was
    assert asset.theme == AppriseAsset().theme

    # Empty string assignment
    assert isinstance(asset.image_url_mask, six.string_types) is True
    assert asset.image_url_mask == ""
    assert isinstance(asset.image_url_logo, six.string_types) is True
    assert asset.image_url_logo == ""

    # For on-lookers looking through this file; here is a perfectly formatted
    # YAML configuration file for your reference so you can see it without
    # all of the errors like the ones identified above
    result = ConfigBase.config_parse_yaml("""
# if no version is specified then version 1 is presumed. Thus this is a
# completely optional field. It's a good idea to just add this line because it
# will help with future ambiguity (if it ever occurs).
version: 1

# Define an Asset object if you wish (Optional)
asset:
  app_id: AppriseTest
  app_desc: Apprise Test Notifications
  app_url: http://nuxref.com

# Optionally define some global tags to associate with ALL of your
# urls below.
tag: admin, devops

# Define your URLs (Mandatory!)
urls:
  # Either on-line each entry like this:
  - json://localhost

  # Or add a colon to the end of the URL where you can optionally provide
  # over-ride entries.  One of the most likely entry to be used here
  # is the tag entry.  This gets extended to the global tag (if defined)
  # above
  - xml://localhost:
    - tag: customer

  # The more elements you specify under a URL the more times the URL will
  # get replicated and used. Hence this entry actually could be considered
  # 2 URLs being called with just the destination email address changed:
  - mailto://george:[email protected]:
     - to: [email protected]
     - to: [email protected]

  # Again... to re-iterate, the above mailto:// would actually fire two (2)
  # separate emails each with a different destination address specified.
  # Be careful when defining your arguments and differentiating between
  # when to use the dash (-) and when not to.  Each time you do, you will
  # cause another instance to be created.

  # Defining more then 1 element to a muti-set is easy, it looks like this:
  - mailto://jackson:[email protected]:
     - to: [email protected]
       tag: jeff, customer

     - to: [email protected]
       tag: chris, customer
""",
                                          asset=asset)

    # okay, here is how we get our total based on the above (read top-down)
    # +1  json:// entry
    # +1  xml:// entry
    # +2  mailto:// entry to [email protected] and [email protected]
    # +2  mailto:// entry to [email protected] and [email protected]
    # = 6
    assert len(result) == 6

    # all six entries will have our global tags defined in them
    for entry in result:
        assert 'admin' in entry.tags
        assert 'devops' in entry.tags

    # Entries can be directly accessed as they were added

    # our json:// had no additional tags added; so just the global ones
    # So just 2; admin and devops (these were already validated above in the
    # for loop
    assert len(result[0].tags) == 2

    # our xml:// object has 1 tag added (customer)
    assert len(result[1].tags) == 3
    assert 'customer' in result[1].tags

    # You get the idea, here is just a direct mapping to the remaining entries
    # in the same order they appear above
    assert len(result[2].tags) == 2
    assert len(result[3].tags) == 2

    assert len(result[4].tags) == 4
    assert 'customer' in result[4].tags
    assert 'jeff' in result[4].tags

    assert len(result[5].tags) == 4
    assert 'customer' in result[5].tags
    assert 'chris' in result[5].tags
Exemple #4
0
def test_config_base_config_parse_yaml():
    """
    API: ConfigBase.config_parse_yaml object

    """

    # general reference used below
    asset = AppriseAsset()

    # Garbage Handling
    for garbage in (object(), None, '', 42):
        # A response is always correctly returned
        result = ConfigBase.config_parse_yaml(garbage)
        # response is a tuple...
        assert isinstance(result, tuple)
        # containing 2 items (plugins, config)
        assert len(result) == 2
        # In the case of garbage in, we get garbage out; both lists are empty
        assert result == (list(), list())

    # Invalid Version
    result, config = ConfigBase.config_parse_yaml("version: 2a", asset=asset)

    # Invalid data gets us an empty result set
    assert isinstance(result, list)
    assert len(result) == 0

    # There were no include entries defined
    assert len(config) == 0

    # Invalid Syntax (throws a ScannerError)
    result, config = ConfigBase.config_parse_yaml("""
# if no version is specified then version 1 is presumed
version: 1

urls
""",
                                                  asset=asset)

    # Invalid data gets us an empty result set
    assert isinstance(result, list)
    assert len(result) == 0

    # There were no include entries defined
    assert len(config) == 0

    # Missing url token
    result, config = ConfigBase.config_parse_yaml("""
# if no version is specified then version 1 is presumed
version: 1

""",
                                                  asset=asset)

    # Invalid data gets us an empty result set
    assert isinstance(result, list)
    assert len(result) == 0

    # There were no include entries defined
    assert len(config) == 0

    # No urls defined
    result, config = ConfigBase.config_parse_yaml("""
# if no version is specified then version 1 is presumed
version: 1

urls:
""",
                                                  asset=asset)

    # Invalid data gets us an empty result set
    assert isinstance(result, list)
    assert len(result) == 0

    # There were no include entries defined
    assert len(config) == 0

    # Invalid url defined
    result, config = ConfigBase.config_parse_yaml("""
# if no version is specified then version 1 is presumed
version: 1

# Invalid URL definition; yet the answer to life at the same time
urls: 43
""",
                                                  asset=asset)

    # Invalid data gets us an empty result set
    assert isinstance(result, list)
    assert len(result) == 0

    # There were no include entries defined
    assert len(config) == 0

    # Invalid url/schema
    result, config = ConfigBase.config_parse_yaml("""
# if no version is specified then version 1 is presumed
version: 1

urls:
  - invalid://

""",
                                                  asset=asset)

    # Invalid data gets us an empty result set
    assert isinstance(result, list)
    assert len(result) == 0

    # There were no include entries defined
    assert len(config) == 0

    # Invalid url/schema
    result, config = ConfigBase.config_parse_yaml("""
# if no version is specified then version 1 is presumed
version: 1

urls:
  - invalid://:
    - a: b

""",
                                                  asset=asset)

    # Invalid data gets us an empty result set
    assert isinstance(result, list)
    assert len(result) == 0

    # There were no include entries defined
    assert len(config) == 0

    # Invalid url/schema
    result, config = ConfigBase.config_parse_yaml("""
# Include entry with nothing associated with it
include:

urls:
  - just some free text that isn't valid:
    - a garbage entry to go with it

""",
                                                  asset=asset)

    # Invalid data gets us an empty result set
    assert isinstance(result, list)
    assert len(result) == 0

    # There were no include entries defined
    assert len(config) == 0

    # Invalid url/schema
    result, config = ConfigBase.config_parse_yaml("""
# if no version is specified then version 1 is presumed
version: 1

urls:
  - not even a proper url

""",
                                                  asset=asset)

    # Invalid data gets us an empty result set
    assert isinstance(result, list)
    assert len(result) == 0

    # There were no include entries defined
    assert len(config) == 0

    # Invalid url/schema
    result, config = ConfigBase.config_parse_yaml("""
# no lists... just no
urls: [milk, pumpkin pie, eggs, juice]

# Including by list is okay
include: [file:///absolute/path/, relative/path, http://test.com]

""",
                                                  asset=asset)

    # Invalid data gets us an empty result set
    assert isinstance(result, list)
    assert len(result) == 0

    # There were 3 include entries
    assert len(config) == 3
    assert 'file:///absolute/path/' in config
    assert 'relative/path' in config
    assert 'http://test.com' in config

    # Invalid url/schema
    result, config = ConfigBase.config_parse_yaml("""
urls:
  # a very invalid sns entry
  - sns://T1JJ3T3L2/
  - sns://:@/:
    - invalid: test
  - sns://T1JJ3T3L2/:
    - invalid: test

  # some strangeness
  -
    -
      - test

""",
                                                  asset=asset)

    # Invalid data gets us an empty result set
    assert isinstance(result, list)
    assert len(result) == 0

    # There were no include entries defined
    assert len(config) == 0

    # Valid Configuration
    result, config = ConfigBase.config_parse_yaml("""
# if no version is specified then version 1 is presumed
version: 1

# Including by dict
include:
  # File includes
  - file:///absolute/path/
  - relative/path
  # Trailing colon shouldn't disrupt include
  - http://test.com:

  # invalid (numeric)
  - 4

  # some strangeness
  -
    -
      - test

#
# Define your notification urls:
#
urls:
  - pbul://o.gn5kj6nfhv736I7jC3cj3QLRiyhgl98b
  - mailto://test:[email protected]
  - https://apprise.ryver.com/application/webhook/ckhrjW8w672m6HG
  - https://not.a.native.url/
""",
                                                  asset=asset)

    # We expect to parse 3 entries from the above
    # The Ryver one is in a native form and the 4th one is invalid
    assert isinstance(result, list)
    assert len(result) == 3
    assert len(result[0].tags) == 0

    # There were 3 include entries
    assert len(config) == 3
    assert 'file:///absolute/path/' in config
    assert 'relative/path' in config
    assert 'http://test.com' in config

    # Valid Configuration
    result, config = ConfigBase.config_parse_yaml("""
# A single line include is supported
include: http://localhost:8080/notify/apprise

urls:
  - json://localhost:
    - tag: my-custom-tag, my-other-tag

  # How to stack multiple entries:
  - mailto://user:[email protected]:
    - to: [email protected]
    - to: [email protected]

      # This is an illegal entry; the schema can not be changed
      schema: json

  # accidently left a colon at the end of the url; no problem
  # we'll accept it
  - mailto://oscar:[email protected]:

  # A Ryver URL (using Native format); still accepted
  - https://apprise.ryver.com/application/webhook/ckhrjW8w672m6HG:

  # An invalid URL with colon (ignored)
  - https://not.a.native.url/:

  # A telegram entry (returns a None in parse_url())
  - tgram://invalid

""",
                                                  asset=asset)

    # We expect to parse 4 entries from the above because the tgram:// entry
    # would have failed to be loaded
    assert isinstance(result, list)
    assert len(result) == 5
    assert len(result[0].tags) == 2

    # Our single line included
    assert len(config) == 1
    assert 'http://localhost:8080/notify/apprise' in config

    # Global Tags
    result, config = ConfigBase.config_parse_yaml("""
# Global Tags stacked as a list
tag:
  - admin
  - devops

urls:
  - json://localhost
  - dbus://
""",
                                                  asset=asset)

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

    # There were no include entries defined
    assert len(config) == 0

    # all entries will have our global tags defined in them
    for entry in result:
        assert 'admin' in entry.tags
        assert 'devops' in entry.tags

    # Global Tags
    result, config = ConfigBase.config_parse_yaml("""
# Global Tags
tag: admin, devops

urls:
  # The following tags will get added to the global set
  - json://localhost:
    - tag: string-tag, my-other-tag, text

  # Tags can be presented in this list format too:
  - dbus://:
    - tag:
      - list-tag
      - dbus
""",
                                                  asset=asset)

    # all entries will have our global tags defined in them
    for entry in result:
        assert 'admin' in entry.tags
        assert 'devops' in entry.tags

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

    # json:// has 2 globals + 3 defined
    assert len(result[0].tags) == 5
    assert 'text' in result[0].tags

    # json:// has 2 globals + 2 defined
    assert len(result[1].tags) == 4
    assert 'list-tag' in result[1].tags

    # There were no include entries defined
    assert len(config) == 0

    # An invalid set of entries
    result, config = ConfigBase.config_parse_yaml("""
urls:
  # The following tags will get added to the global set
  - json://localhost:
    -
      -
        - entry
""",
                                                  asset=asset)

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

    # There were no include entries defined
    assert len(config) == 0

    # An asset we'll manipulate
    asset = AppriseAsset()

    # Global Tags
    result, config = ConfigBase.config_parse_yaml("""
# Test the creation of our apprise asset object
asset:
  app_id: AppriseTest
  app_desc: Apprise Test Notifications
  app_url: http://nuxref.com

  # Support setting empty values
  image_url_mask:
  image_url_logo:

  image_path_mask: tmp/path

  # invalid entry
  theme:
    -
      -
        - entry

  # Now for some invalid entries
  invalid: entry
  __init__: can't be over-ridden
  nolists:
    - we don't support these entries
    - in the apprise object

urls:
  - json://localhost:
""",
                                                  asset=asset)

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

    # There were no include entries defined
    assert len(config) == 0

    assert asset.app_id == "AppriseTest"
    assert asset.app_desc == "Apprise Test Notifications"
    assert asset.app_url == "http://nuxref.com"

    # the theme was not updated and remains the same as it was
    assert asset.theme == AppriseAsset().theme

    # Empty string assignment
    assert isinstance(asset.image_url_mask, six.string_types) is True
    assert asset.image_url_mask == ""
    assert isinstance(asset.image_url_logo, six.string_types) is True
    assert asset.image_url_logo == ""

    # For on-lookers looking through this file; here is a perfectly formatted
    # YAML configuration file for your reference so you can see it without
    # all of the errors like the ones identified above
    result, config = ConfigBase.config_parse_yaml("""
# if no version is specified then version 1 is presumed. Thus this is a
# completely optional field. It's a good idea to just add this line because it
# will help with future ambiguity (if it ever occurs).
version: 1

# Define an Asset object if you wish (Optional)
asset:
  app_id: AppriseTest
  app_desc: Apprise Test Notifications
  app_url: http://nuxref.com

# Optionally define some global tags to associate with ALL of your
# urls below.
tag: admin, devops

# Define your URLs (Mandatory!)
urls:
  # Either on-line each entry like this:
  - json://localhost

  # Or add a colon to the end of the URL where you can optionally provide
  # over-ride entries.  One of the most likely entry to be used here
  # is the tag entry.  This gets extended to the global tag (if defined)
  # above
  - xml://localhost:
    - tag: customer

  # The more elements you specify under a URL the more times the URL will
  # get replicated and used. Hence this entry actually could be considered
  # 2 URLs being called with just the destination email address changed:
  - mailto://george:[email protected]:
     - to: [email protected]
     - to: [email protected]

  # Again... to re-iterate, the above mailto:// would actually fire two (2)
  # separate emails each with a different destination address specified.
  # Be careful when defining your arguments and differentiating between
  # when to use the dash (-) and when not to.  Each time you do, you will
  # cause another instance to be created.

  # Defining more then 1 element to a muti-set is easy, it looks like this:
  - mailto://jackson:[email protected]:
     - to: [email protected]
       tag: jeff, customer

     - to: [email protected]
       tag: chris, customer
""",
                                                  asset=asset)

    # okay, here is how we get our total based on the above (read top-down)
    # +1  json:// entry
    # +1  xml:// entry
    # +2  mailto:// entry to [email protected] and [email protected]
    # +2  mailto:// entry to [email protected] and [email protected]
    # = 6
    assert len(result) == 6

    # all six entries will have our global tags defined in them
    for entry in result:
        assert 'admin' in entry.tags
        assert 'devops' in entry.tags

    # Entries can be directly accessed as they were added

    # our json:// had no additional tags added; so just the global ones
    # So just 2; admin and devops (these were already validated above in the
    # for loop
    assert len(result[0].tags) == 2

    # our xml:// object has 1 tag added (customer)
    assert len(result[1].tags) == 3
    assert 'customer' in result[1].tags

    # You get the idea, here is just a direct mapping to the remaining entries
    # in the same order they appear above
    assert len(result[2].tags) == 2
    assert len(result[3].tags) == 2

    assert len(result[4].tags) == 4
    assert 'customer' in result[4].tags
    assert 'jeff' in result[4].tags

    assert len(result[5].tags) == 4
    assert 'customer' in result[5].tags
    assert 'chris' in result[5].tags

    # There were no include entries defined
    assert len(config) == 0

    # Valid Configuration (multi inline configuration entries)
    result, config = ConfigBase.config_parse_yaml("""
# A configuration file that contains 2 includes separated by a comma and/or
# space:
include: http://localhost:8080/notify/apprise, http://localhost/apprise/cfg

""",
                                                  asset=asset)

    # We will have loaded no results
    assert isinstance(result, list)
    assert len(result) == 0

    # But our two configuration files will be present:
    assert len(config) == 2
    assert 'http://localhost:8080/notify/apprise' in config
    assert 'http://localhost/apprise/cfg' in config

    # Valid Configuration (another way of specifying more then one include)
    result, config = ConfigBase.config_parse_yaml("""
# A configuration file that contains 4 includes on their own
# lines beneath the keyword `include`:
include:
   http://localhost:8080/notify/apprise
   http://localhost/apprise/cfg01
   http://localhost/apprise/cfg02
   http://localhost/apprise/cfg03

""",
                                                  asset=asset)

    # We will have loaded no results
    assert isinstance(result, list)
    assert len(result) == 0

    # But our 4 configuration files will be present:
    assert len(config) == 4
    assert 'http://localhost:8080/notify/apprise' in config
    assert 'http://localhost/apprise/cfg01' in config
    assert 'http://localhost/apprise/cfg02' in config
    assert 'http://localhost/apprise/cfg03' in config

    # Valid Configuration (we allow comma separated entries for
    # each defined bullet)
    result, config = ConfigBase.config_parse_yaml("""
# A configuration file that contains 4 includes on their own
# lines beneath the keyword `include`:
include:
   - http://localhost:8080/notify/apprise, http://localhost/apprise/cfg01
     http://localhost/apprise/cfg02
   - http://localhost/apprise/cfg03

""",
                                                  asset=asset)

    # We will have loaded no results
    assert isinstance(result, list)
    assert len(result) == 0

    # But our 4 configuration files will be present:
    assert len(config) == 4
    assert 'http://localhost:8080/notify/apprise' in config
    assert 'http://localhost/apprise/cfg01' in config
    assert 'http://localhost/apprise/cfg02' in config
    assert 'http://localhost/apprise/cfg03' in config