mirror of
https://github.com/caronc/apprise.git
synced 2024-12-11 17:30:52 +01:00
CLI environment variable over-ride support (#1231)
This commit is contained in:
parent
1065c021d3
commit
01c1082ad8
12
README.md
12
README.md
@ -39,6 +39,7 @@ System Administrators and DevOps who wish to send a notification now no longer n
|
||||
* [Configuration Files](#cli-configuration-files)
|
||||
* [File Attachments](#cli-file-attachments)
|
||||
* [Loading Custom Notifications/Hooks](#cli-loading-custom-notificationshooks)
|
||||
* [Environment Variables](#cli-environment-variables)
|
||||
* [Developer API Usage](#developer-api-usage)
|
||||
* [Configuration Files](#api-configuration-files)
|
||||
* [File Attachments](#api-file-attachments)
|
||||
@ -352,6 +353,17 @@ apprise -vv --title 'custom override' \
|
||||
|
||||
You can read more about creating your own custom notifications and/or hooks [here](https://github.com/caronc/apprise/wiki/decorator_notify).
|
||||
|
||||
## CLI Environment Variables
|
||||
|
||||
Those using the Command Line Interface (CLI) can also leverage environment variables to pre-set the default settings:
|
||||
|
||||
| Variable | Description |
|
||||
|------------------------ | ----------------- |
|
||||
| `APPRISE_URLS` | Specify the default URLs to notify IF none are otherwise specified on the command line explicitly. If the `--config` (`-c`) is specified, then this will over-rides any reference to this variable. Use white space and/or a comma (`,`) to delimit multiple entries.
|
||||
| `APPRISE_CONFIG_PATH` | Explicitly specify the config search path to use (over-riding the default). The path(s) defined here must point to the absolute filename to open/reference. Use a semi-colon (`;`), line-feed (`\n`), and/or carriage return (`\r`) to delimit multiple entries.
|
||||
| `APPRISE_PLUGIN_PATH` | Explicitly specify the custom plugin search path to use (over-riding the default). Use a semi-colon (`;`), line-feed (`\n`), and/or carriage return (`\r`) to delimit multiple entries.
|
||||
| `APPRISE_STORAGE_PATH` | Explicitly specify the persistent storage path to use (over-riding the default).
|
||||
|
||||
# Developer API Usage
|
||||
|
||||
To send a notification from within your python application, just do the following:
|
||||
|
@ -68,6 +68,21 @@ DEFAULT_STORAGE_PRUNE_DAYS = \
|
||||
DEFAULT_STORAGE_UID_LENGTH = \
|
||||
int(os.environ.get('APPRISE_STORAGE_UID_LENGTH', 8))
|
||||
|
||||
# Defines the envrionment variable to parse if defined. This is ONLY
|
||||
# Referenced if:
|
||||
# - No Configuration Files were found/loaded/specified
|
||||
# - No URLs were provided directly into the CLI Call
|
||||
DEFAULT_ENV_APPRISE_URLS = 'APPRISE_URLS'
|
||||
|
||||
# Defines the over-ride path for the configuration files read
|
||||
DEFAULT_ENV_APPRISE_CONFIG_PATH = 'APPRISE_CONFIG_PATH'
|
||||
|
||||
# Defines the over-ride path for the plugins to load
|
||||
DEFAULT_ENV_APPRISE_PLUGIN_PATH = 'APPRISE_PLUGIN_PATH'
|
||||
|
||||
# Defines the over-ride path for the persistent storage
|
||||
DEFAULT_ENV_APPRISE_STORAGE_PATH = 'APPRISE_STORAGE_PATH'
|
||||
|
||||
# Defines our click context settings adding -h to the additional options that
|
||||
# can be specified to get the help menu to come up
|
||||
CONTEXT_SETTINGS = dict(help_option_names=['-h', '--help'])
|
||||
@ -496,11 +511,53 @@ def main(ctx, body, title, config, attach, urls, notification_type, theme, tag,
|
||||
# issue. For consistency, we also return a 2
|
||||
ctx.exit(2)
|
||||
|
||||
if not plugin_path:
|
||||
# Prepare a default set of plugin path
|
||||
plugin_path = \
|
||||
[path for path in DEFAULT_PLUGIN_PATHS
|
||||
if exists(path_decode(path))]
|
||||
#
|
||||
# Apply Environment Over-rides if defined
|
||||
#
|
||||
_config_paths = DEFAULT_CONFIG_PATHS
|
||||
if 'APPRISE_CONFIG' in os.environ:
|
||||
# Deprecate (this was from previous versions of Apprise <= 1.9.1)
|
||||
logger.deprecate(
|
||||
'APPRISE_CONFIG environment variable has been changed to '
|
||||
f'{DEFAULT_ENV_APPRISE_CONFIG_PATH}')
|
||||
logger.debug(
|
||||
'Loading provided APPRISE_CONFIG (deprecated) environment '
|
||||
'variable')
|
||||
_config_paths = (os.environ.get('APPRISE_CONFIG', '').strip(), )
|
||||
|
||||
elif DEFAULT_ENV_APPRISE_CONFIG_PATH in os.environ:
|
||||
logger.debug(
|
||||
f'Loading provided {DEFAULT_ENV_APPRISE_CONFIG_PATH} '
|
||||
'environment variable')
|
||||
_config_paths = re.split(
|
||||
r'[\r\n;]+', os.environ.get(
|
||||
DEFAULT_ENV_APPRISE_CONFIG_PATH).strip())
|
||||
|
||||
_plugin_paths = DEFAULT_PLUGIN_PATHS
|
||||
if DEFAULT_ENV_APPRISE_PLUGIN_PATH in os.environ:
|
||||
logger.debug(
|
||||
f'Loading provided {DEFAULT_ENV_APPRISE_PLUGIN_PATH} environment '
|
||||
'variable')
|
||||
_plugin_paths = re.split(
|
||||
r'[\r\n;]+', os.environ.get(
|
||||
DEFAULT_ENV_APPRISE_PLUGIN_PATH).strip())
|
||||
|
||||
if DEFAULT_ENV_APPRISE_STORAGE_PATH in os.environ:
|
||||
logger.debug(
|
||||
f'Loading provided {DEFAULT_ENV_APPRISE_STORAGE_PATH} environment '
|
||||
'variable')
|
||||
storage_path = \
|
||||
os.environ.get(DEFAULT_ENV_APPRISE_STORAGE_PATH).strip()
|
||||
|
||||
#
|
||||
# Continue with initialization process
|
||||
#
|
||||
|
||||
# Prepare a default set of plugin paths to scan; anything specified
|
||||
# on the CLI always trumps
|
||||
plugin_paths = \
|
||||
[path for path in _plugin_paths if exists(path_decode(path))] \
|
||||
if not plugin_path else plugin_path
|
||||
|
||||
if storage_uid_length < 2:
|
||||
click.echo(
|
||||
@ -533,7 +590,7 @@ def main(ctx, body, title, config, attach, urls, notification_type, theme, tag,
|
||||
async_mode=disable_async is not True,
|
||||
|
||||
# Load our plugins
|
||||
plugin_paths=plugin_path,
|
||||
plugin_paths=plugin_paths,
|
||||
|
||||
# Load our persistent storage path
|
||||
storage_path=path_decode(storage_path),
|
||||
@ -636,8 +693,7 @@ def main(ctx, body, title, config, attach, urls, notification_type, theme, tag,
|
||||
# 1. URLs by command line
|
||||
# 2. Configuration by command line
|
||||
# 3. URLs by environment variable: APPRISE_URLS
|
||||
# 4. Configuration by environment variable: APPRISE_CONFIG
|
||||
# 5. Default Configuration File(s) (if found)
|
||||
# 4. Default Configuration File(s)
|
||||
#
|
||||
elif urls and not storage_action:
|
||||
if tag:
|
||||
@ -662,8 +718,10 @@ def main(ctx, body, title, config, attach, urls, notification_type, theme, tag,
|
||||
a.add(AppriseConfig(
|
||||
paths=config, asset=asset, recursion=recursion_depth))
|
||||
|
||||
elif os.environ.get('APPRISE_URLS', '').strip():
|
||||
logger.debug('Loading provided APPRISE_URLS environment variable')
|
||||
elif os.environ.get(DEFAULT_ENV_APPRISE_URLS, '').strip():
|
||||
logger.debug(
|
||||
f'Loading provided {DEFAULT_ENV_APPRISE_URLS} environment '
|
||||
'variable')
|
||||
if tag:
|
||||
# Ignore any tags specified
|
||||
logger.warning(
|
||||
@ -671,19 +729,12 @@ def main(ctx, body, title, config, attach, urls, notification_type, theme, tag,
|
||||
tag = None
|
||||
|
||||
# Attempt to use our APPRISE_URLS environment variable (if populated)
|
||||
a.add(os.environ['APPRISE_URLS'].strip())
|
||||
|
||||
elif os.environ.get('APPRISE_CONFIG', '').strip():
|
||||
logger.debug('Loading provided APPRISE_CONFIG environment variable')
|
||||
# Fall back to config environment variable (if populated)
|
||||
a.add(AppriseConfig(
|
||||
paths=os.environ['APPRISE_CONFIG'].strip(),
|
||||
asset=asset, recursion=recursion_depth))
|
||||
a.add(os.environ[DEFAULT_ENV_APPRISE_URLS].strip())
|
||||
|
||||
else:
|
||||
# Load default configuration
|
||||
a.add(AppriseConfig(
|
||||
paths=[f for f in DEFAULT_CONFIG_PATHS if isfile(path_decode(f))],
|
||||
paths=[f for f in _config_paths if isfile(path_decode(f))],
|
||||
asset=asset, recursion=recursion_depth))
|
||||
|
||||
if not dry_run and not (a or storage_action):
|
||||
|
@ -29,10 +29,8 @@ import copy
|
||||
import re
|
||||
import sys
|
||||
import json
|
||||
import contextlib
|
||||
import os
|
||||
import binascii
|
||||
import locale
|
||||
import platform
|
||||
import typing
|
||||
import base64
|
||||
@ -1518,39 +1516,6 @@ def cwe312_url(url):
|
||||
)
|
||||
|
||||
|
||||
@contextlib.contextmanager
|
||||
def environ(*remove, **update):
|
||||
"""
|
||||
Temporarily updates the ``os.environ`` dictionary in-place.
|
||||
|
||||
The ``os.environ`` dictionary is updated in-place so that the modification
|
||||
is sure to work in all situations.
|
||||
|
||||
:param remove: Environment variable(s) to remove.
|
||||
:param update: Dictionary of environment variables and values to
|
||||
add/update.
|
||||
"""
|
||||
|
||||
# Create a backup of our environment for restoration purposes
|
||||
env_orig = os.environ.copy()
|
||||
loc_orig = locale.getlocale()
|
||||
try:
|
||||
os.environ.update(update)
|
||||
[os.environ.pop(k, None) for k in remove]
|
||||
yield
|
||||
|
||||
finally:
|
||||
# Restore our snapshot
|
||||
os.environ = env_orig.copy()
|
||||
try:
|
||||
# Restore locale
|
||||
locale.setlocale(locale.LC_ALL, loc_orig)
|
||||
|
||||
except locale.Error:
|
||||
# Handle this case
|
||||
pass
|
||||
|
||||
|
||||
def apply_template(template, app_mode=TemplateType.RAW, **kwargs):
|
||||
"""
|
||||
Takes a template in a str format and applies all of the keywords
|
||||
|
@ -159,6 +159,9 @@ visit the [Apprise GitHub page][serviceurls] and see what's available.
|
||||
|
||||
[serviceurls]: https://github.com/caronc/apprise/wiki#notification-services
|
||||
|
||||
The **environment variable** of `APPRISE_URLS` (comma/space delimited) can be specified to
|
||||
provide the default set of URLs you wish to notify if none are otherwise specified.
|
||||
|
||||
## EXAMPLES
|
||||
|
||||
Send a notification to as many servers as you want to specify as you can
|
||||
@ -215,8 +218,13 @@ files and loads them:
|
||||
~/.config/apprise/plugins
|
||||
/var/lib/apprise/plugins
|
||||
|
||||
The **environment variable** of `APPRISE_PLUGIN_PATH` can be specified to override
|
||||
the list identified above with one of your own. use a semi-colon (`;`), line-feed (`\n`),
|
||||
and/or carriage return (`\r`) to delimit multiple entries.
|
||||
|
||||
Simply create your own python file with the following bare minimum content in
|
||||
it:
|
||||
|
||||
from apprise.decorators import notify
|
||||
|
||||
# This example assumes you want your function to trigger on foobar://
|
||||
@ -263,6 +271,10 @@ in the following local locations for configuration files and loads them:
|
||||
The **configuration files** specified above can also be identified with a `.yml`
|
||||
extension or even just entirely removing the `.conf` extension altogether.
|
||||
|
||||
The **environment variable** of `APPRISE_CONFIG_PATH` can be specified to override
|
||||
the list identified above with one of your own. use a semi-colon (`;`), line-feed (`\n`),
|
||||
and/or carriage return (`\r`) to delimit multiple entries.
|
||||
|
||||
If a default configuration file is referenced in any way by the **apprise**
|
||||
tool, you no longer need to provide it a Service URL. Usage of the **apprise**
|
||||
tool simplifies to:
|
||||
@ -281,6 +293,23 @@ configuration that you want and only specifically notify a subset of them:
|
||||
[tagging]: https://github.com/caronc/apprise/wiki/CLI_Usage#label-leverage-tagging
|
||||
[pstorage]: https://github.com/caronc/apprise/wiki/persistent_storage
|
||||
|
||||
## ENVIRONMENT VARIABLES
|
||||
`APPRISE_URLS`:
|
||||
Specify the default URLs to notify IF none are otherwise specified on the command line
|
||||
explicitly. If the `--config` (`-c`) is specified, then this will over-rides any
|
||||
reference to this variable. Use white space and/or a comma (`,`) to delimit multiple entries.
|
||||
|
||||
`APPRISE_CONFIG_PATH`:
|
||||
Explicitly specify the config search path to use (over-riding the default).
|
||||
Use a semi-colon (`;`), line-feed (`\n`), and/or carriage return (`\r`) to delimit multiple entries.
|
||||
|
||||
`APPRISE_PLUGIN_PATH`:
|
||||
Explicitly specify the custom plugin search path to use (over-riding the default).
|
||||
Use a semi-colon (`;`), line-feed (`\n`), and/or carriage return (`\r`) to delimit multiple entries.
|
||||
|
||||
`APPRISE_STORAGE_PATH`:
|
||||
Explicitly specify the persistent storage path to use (over-riding the default).
|
||||
|
||||
## BUGS
|
||||
|
||||
If you find any bugs, please make them known at:
|
||||
|
@ -29,9 +29,11 @@
|
||||
from .rest import AppriseURLTester
|
||||
from .asyncio import OuterEventLoop
|
||||
from .module import reload_plugin
|
||||
from .environment import environ
|
||||
|
||||
__all__ = [
|
||||
'AppriseURLTester',
|
||||
'OuterEventLoop',
|
||||
'reload_plugin',
|
||||
'environ',
|
||||
]
|
||||
|
68
test/helpers/environment.py
Normal file
68
test/helpers/environment.py
Normal file
@ -0,0 +1,68 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
# BSD 2-Clause License
|
||||
#
|
||||
# Apprise - Push Notification Library.
|
||||
# Copyright (c) 2024, Chris Caron <lead2gold@gmail.com>
|
||||
#
|
||||
# Redistribution and use in source and binary forms, with or without
|
||||
# modification, are permitted provided that the following conditions are met:
|
||||
#
|
||||
# 1. Redistributions of source code must retain the above copyright notice,
|
||||
# this list of conditions and the following disclaimer.
|
||||
#
|
||||
# 2. Redistributions in binary form must reproduce the above copyright notice,
|
||||
# this list of conditions and the following disclaimer in the documentation
|
||||
# and/or other materials provided with the distribution.
|
||||
#
|
||||
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
# ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
|
||||
# LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
# CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||
# SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
# INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
# CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
# ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
# POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
import os
|
||||
import contextlib
|
||||
import locale
|
||||
|
||||
# Disable logging for a cleaner testing output
|
||||
import logging
|
||||
logging.disable(logging.CRITICAL)
|
||||
|
||||
|
||||
@contextlib.contextmanager
|
||||
def environ(*remove, **update):
|
||||
"""
|
||||
Temporarily updates the ``os.environ`` dictionary in-place.
|
||||
|
||||
The ``os.environ`` dictionary is updated in-place so that the modification
|
||||
is sure to work in all situations.
|
||||
|
||||
:param remove: Environment variable(s) to remove.
|
||||
:param update: Dictionary of environment variables and values to
|
||||
add/update.
|
||||
"""
|
||||
|
||||
# Create a backup of our environment for restoration purposes
|
||||
env_orig = os.environ.copy()
|
||||
loc_orig = locale.getlocale()
|
||||
try:
|
||||
os.environ.update(update)
|
||||
[os.environ.pop(k, None) for k in remove]
|
||||
yield
|
||||
|
||||
finally:
|
||||
# Restore our snapshot
|
||||
os.environ = env_orig.copy()
|
||||
try:
|
||||
# Restore locale
|
||||
locale.setlocale(locale.LC_ALL, loc_orig)
|
||||
|
||||
except locale.Error:
|
||||
# Handle this case
|
||||
pass
|
@ -40,7 +40,7 @@ from apprise import cli
|
||||
from apprise import NotifyBase
|
||||
from apprise import NotificationManager
|
||||
from click.testing import CliRunner
|
||||
from apprise.utils import environ
|
||||
from helpers import environ
|
||||
from apprise.locale import gettext_lazy as _
|
||||
|
||||
from importlib import reload
|
||||
@ -515,6 +515,22 @@ def test_apprise_cli_nux_env(tmpdir):
|
||||
assert result.exit_code == 0
|
||||
|
||||
with environ(APPRISE_CONFIG=str(t2)):
|
||||
# Deprecated test case
|
||||
result = runner.invoke(cli.main, [
|
||||
'-b', 'has myTag',
|
||||
'--tag', 'myTag',
|
||||
])
|
||||
assert result.exit_code == 0
|
||||
|
||||
with environ(APPRISE_CONFIG_PATH=str(t2)):
|
||||
# Our configuration file will load from our environmment variable
|
||||
result = runner.invoke(cli.main, [
|
||||
'-b', 'has myTag',
|
||||
'--tag', 'myTag',
|
||||
])
|
||||
assert result.exit_code == 0
|
||||
|
||||
with environ(APPRISE_CONFIG_PATH=str(t2) + ';/another/path'):
|
||||
# Our configuration file will load from our environmment variable
|
||||
result = runner.invoke(cli.main, [
|
||||
'-b', 'has myTag',
|
||||
@ -677,6 +693,17 @@ def test_apprise_cli_modules(tmpdir):
|
||||
|
||||
assert result.exit_code == 0
|
||||
|
||||
with environ(
|
||||
APPRISE_PLUGIN_PATH=str(notify_cmod) + ';' + str(notify_cmod2)):
|
||||
# Leverage our environment variables to specify the plugin path
|
||||
result = runner.invoke(cli.main, [
|
||||
'-b', 'body',
|
||||
'climod://',
|
||||
'climod2://',
|
||||
])
|
||||
|
||||
assert result.exit_code == 0
|
||||
|
||||
|
||||
@pytest.mark.skipif(
|
||||
sys.platform == "win32", reason="Unreliable results to be determined")
|
||||
|
127
test/test_apprise_helpers.py
Normal file
127
test/test_apprise_helpers.py
Normal file
@ -0,0 +1,127 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
# BSD 2-Clause License
|
||||
#
|
||||
# Apprise - Push Notification Library.
|
||||
# Copyright (c) 2024, Chris Caron <lead2gold@gmail.com>
|
||||
#
|
||||
# Redistribution and use in source and binary forms, with or without
|
||||
# modification, are permitted provided that the following conditions are met:
|
||||
#
|
||||
# 1. Redistributions of source code must retain the above copyright notice,
|
||||
# this list of conditions and the following disclaimer.
|
||||
#
|
||||
# 2. Redistributions in binary form must reproduce the above copyright notice,
|
||||
# this list of conditions and the following disclaimer in the documentation
|
||||
# and/or other materials provided with the distribution.
|
||||
#
|
||||
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
# ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
|
||||
# LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
# CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||
# SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
# INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
# CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
# ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
# POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
import os
|
||||
import sys
|
||||
import helpers
|
||||
|
||||
# Disable logging for a cleaner testing output
|
||||
import logging
|
||||
logging.disable(logging.CRITICAL)
|
||||
|
||||
# Ensure we don't create .pyc files for these tests
|
||||
sys.dont_write_bytecode = True
|
||||
|
||||
|
||||
def test_environ_temporary_change():
|
||||
"""helpers: environ() testing
|
||||
"""
|
||||
# This is a helper function; but it does enough that we want to verify
|
||||
# our usage of it works correctly; yes... we're testing a test
|
||||
|
||||
e_key1 = 'APPRISE_TEMP1'
|
||||
e_key2 = 'APPRISE_TEMP2'
|
||||
e_key3 = 'APPRISE_TEMP3'
|
||||
|
||||
e_val1 = 'ABCD'
|
||||
e_val2 = 'DEFG'
|
||||
e_val3 = 'HIJK'
|
||||
|
||||
os.environ[e_key1] = e_val1
|
||||
os.environ[e_key2] = e_val2
|
||||
os.environ[e_key3] = e_val3
|
||||
|
||||
# Ensure our environment variable stuck
|
||||
assert e_key1 in os.environ
|
||||
assert e_val1 in os.environ[e_key1]
|
||||
assert e_key2 in os.environ
|
||||
assert e_val2 in os.environ[e_key2]
|
||||
assert e_key3 in os.environ
|
||||
assert e_val3 in os.environ[e_key3]
|
||||
|
||||
with helpers.environ(e_key1, e_key3):
|
||||
# Eliminates Environment Variable 1 and 3
|
||||
assert e_key1 not in os.environ
|
||||
assert e_key2 in os.environ
|
||||
assert e_val2 in os.environ[e_key2]
|
||||
assert e_key3 not in os.environ
|
||||
|
||||
# after with is over, environment is restored to normal
|
||||
assert e_key1 in os.environ
|
||||
assert e_val1 in os.environ[e_key1]
|
||||
assert e_key2 in os.environ
|
||||
assert e_val2 in os.environ[e_key2]
|
||||
assert e_key3 in os.environ
|
||||
assert e_val3 in os.environ[e_key3]
|
||||
|
||||
d_key = 'APPRISE_NOT_SET'
|
||||
n_key = 'APPRISE_NEW_KEY'
|
||||
n_val = 'NEW_VAL'
|
||||
|
||||
# Verify that our temporary variables (defined above) are not pre-existing
|
||||
# environemnt variables as we'll be setting them below
|
||||
assert n_key not in os.environ
|
||||
assert d_key not in os.environ
|
||||
|
||||
# makes it easier to pass in the arguments
|
||||
updates = {
|
||||
e_key1: e_val3,
|
||||
e_key2: e_val1,
|
||||
n_key: n_val,
|
||||
}
|
||||
with helpers.environ(d_key, e_key3, **updates):
|
||||
# Attempt to eliminate an undefined key (silently ignored)
|
||||
# Eliminates Environment Variable 3
|
||||
# Environment Variable 1 takes on the value of Env 3
|
||||
# Environment Variable 2 takes on the value of Env 1
|
||||
# Set a brand new variable that previously didn't exist
|
||||
assert e_key1 in os.environ
|
||||
assert e_val3 in os.environ[e_key1]
|
||||
assert e_key2 in os.environ
|
||||
assert e_val1 in os.environ[e_key2]
|
||||
assert e_key3 not in os.environ
|
||||
|
||||
# Can't delete a variable that doesn't exist; so we're in the same
|
||||
# state here.
|
||||
assert d_key not in os.environ
|
||||
|
||||
# Our temporary variables will be found now
|
||||
assert n_key in os.environ
|
||||
assert n_val in os.environ[n_key]
|
||||
|
||||
# after with is over, environment is restored to normal
|
||||
assert e_key1 in os.environ
|
||||
assert e_val1 in os.environ[e_key1]
|
||||
assert e_key2 in os.environ
|
||||
assert e_val2 in os.environ[e_key2]
|
||||
assert e_key3 in os.environ
|
||||
assert e_val3 in os.environ[e_key3]
|
||||
|
||||
# Even our temporary variables are now missing
|
||||
assert n_key not in os.environ
|
||||
assert d_key not in os.environ
|
@ -34,7 +34,7 @@ import ctypes
|
||||
import pytest
|
||||
|
||||
from apprise import locale
|
||||
from apprise.utils import environ
|
||||
from helpers import environ
|
||||
from importlib import reload
|
||||
|
||||
# Disable logging for a cleaner testing output
|
||||
|
@ -2545,93 +2545,6 @@ def test_apprise_validate_regex():
|
||||
"- abcd -", r'-(?P<value>[ABCD]+)-', None, fmt="{value}") is None
|
||||
|
||||
|
||||
def test_environ_temporary_change():
|
||||
"""utils: environ() testing
|
||||
"""
|
||||
|
||||
e_key1 = 'APPRISE_TEMP1'
|
||||
e_key2 = 'APPRISE_TEMP2'
|
||||
e_key3 = 'APPRISE_TEMP3'
|
||||
|
||||
e_val1 = 'ABCD'
|
||||
e_val2 = 'DEFG'
|
||||
e_val3 = 'HIJK'
|
||||
|
||||
os.environ[e_key1] = e_val1
|
||||
os.environ[e_key2] = e_val2
|
||||
os.environ[e_key3] = e_val3
|
||||
|
||||
# Ensure our environment variable stuck
|
||||
assert e_key1 in os.environ
|
||||
assert e_val1 in os.environ[e_key1]
|
||||
assert e_key2 in os.environ
|
||||
assert e_val2 in os.environ[e_key2]
|
||||
assert e_key3 in os.environ
|
||||
assert e_val3 in os.environ[e_key3]
|
||||
|
||||
with utils.environ(e_key1, e_key3):
|
||||
# Eliminates Environment Variable 1 and 3
|
||||
assert e_key1 not in os.environ
|
||||
assert e_key2 in os.environ
|
||||
assert e_val2 in os.environ[e_key2]
|
||||
assert e_key3 not in os.environ
|
||||
|
||||
# after with is over, environment is restored to normal
|
||||
assert e_key1 in os.environ
|
||||
assert e_val1 in os.environ[e_key1]
|
||||
assert e_key2 in os.environ
|
||||
assert e_val2 in os.environ[e_key2]
|
||||
assert e_key3 in os.environ
|
||||
assert e_val3 in os.environ[e_key3]
|
||||
|
||||
d_key = 'APPRISE_NOT_SET'
|
||||
n_key = 'APPRISE_NEW_KEY'
|
||||
n_val = 'NEW_VAL'
|
||||
|
||||
# Verify that our temporary variables (defined above) are not pre-existing
|
||||
# environemnt variables as we'll be setting them below
|
||||
assert n_key not in os.environ
|
||||
assert d_key not in os.environ
|
||||
|
||||
# makes it easier to pass in the arguments
|
||||
updates = {
|
||||
e_key1: e_val3,
|
||||
e_key2: e_val1,
|
||||
n_key: n_val,
|
||||
}
|
||||
with utils.environ(d_key, e_key3, **updates):
|
||||
# Attempt to eliminate an undefined key (silently ignored)
|
||||
# Eliminates Environment Variable 3
|
||||
# Environment Variable 1 takes on the value of Env 3
|
||||
# Environment Variable 2 takes on the value of Env 1
|
||||
# Set a brand new variable that previously didn't exist
|
||||
assert e_key1 in os.environ
|
||||
assert e_val3 in os.environ[e_key1]
|
||||
assert e_key2 in os.environ
|
||||
assert e_val1 in os.environ[e_key2]
|
||||
assert e_key3 not in os.environ
|
||||
|
||||
# Can't delete a variable that doesn't exist; so we're in the same
|
||||
# state here.
|
||||
assert d_key not in os.environ
|
||||
|
||||
# Our temporary variables will be found now
|
||||
assert n_key in os.environ
|
||||
assert n_val in os.environ[n_key]
|
||||
|
||||
# after with is over, environment is restored to normal
|
||||
assert e_key1 in os.environ
|
||||
assert e_val1 in os.environ[e_key1]
|
||||
assert e_key2 in os.environ
|
||||
assert e_val2 in os.environ[e_key2]
|
||||
assert e_key3 in os.environ
|
||||
assert e_val3 in os.environ[e_key3]
|
||||
|
||||
# Even our temporary variables are now missing
|
||||
assert n_key not in os.environ
|
||||
assert d_key not in os.environ
|
||||
|
||||
|
||||
def test_apply_templating():
|
||||
"""utils: apply_template() testing
|
||||
"""
|
||||
|
Loading…
Reference in New Issue
Block a user