Skip to content

Commit

Permalink
Parse config files with input envars (#35)
Browse files Browse the repository at this point in the history
  • Loading branch information
DavidHuber-NOAA authored Jul 4, 2024
1 parent 1356acd commit d314e06
Show file tree
Hide file tree
Showing 2 changed files with 31 additions and 7 deletions.
24 changes: 17 additions & 7 deletions src/wxflow/configuration.py
Original file line number Diff line number Diff line change
Expand Up @@ -67,20 +67,26 @@ def find_config(self, config_name: str) -> str:
raise UnknownConfigError(
f'{config_name} does not exist (known: {repr(config_name)}), ABORT!')

def parse_config(self, files: Union[str, bytes, list]) -> Dict[str, Any]:
def parse_config(self, files: Union[str, bytes, list], **envvars) -> Dict[str, Any]:
"""
Given the name of config file(s), key-value pair of all variables in the config file(s)
are returned as a dictionary
:param files: config file or list of config files
:type files: list or str or unicode
:param envvars: environment variables to be set prior to sourcing config files
:type envvars: Any
:return: Key value pairs representing the environment variables defined
in the script.
in the script.
:rtype: dict
"""
if isinstance(files, (str, bytes)):
files = [files]
files = [self.find_config(file) for file in files]
return cast_strdict_as_dtypedict(self._get_script_env(files))

return cast_strdict_as_dtypedict(self._get_script_env(files, **envvars))

def print_config(self, files: Union[str, bytes, list]) -> None:
"""
Expand All @@ -94,18 +100,22 @@ def print_config(self, files: Union[str, bytes, list]) -> None:
pprint(config, width=4)

@classmethod
def _get_script_env(cls, scripts: List) -> Dict[str, Any]:
def _get_script_env(cls, scripts: List, **envvars) -> Dict[str, Any]:
default_env = cls._get_shell_env([])
and_script_env = cls._get_shell_env(scripts)
and_script_env = cls._get_shell_env(scripts, **envvars)
vars_just_in_script = set(and_script_env) - set(default_env)
union_env = dict(default_env)
union_env.update(and_script_env)
return dict([(v, union_env[v]) for v in vars_just_in_script])

@staticmethod
def _get_shell_env(scripts: List) -> Dict[str, Any]:
def _get_shell_env(scripts: List, **envvars) -> Dict[str, Any]:
varbls = dict()
runme = ''.join([f'source {s} ; ' for s in scripts])
runme = ''
if envvars:
runme += '; '.join([f'export {key}={value}' for key, value in envvars.items()])
runme += '; '
runme += ''.join([f'source {s}; ' for s in scripts])
magic = f'--- ENVIRONMENT BEGIN {random.randint(0,64**5)} ---'
runme += f'/bin/echo -n "{magic}" ; /usr/bin/env -0'
bash_path = shutil.which('bash')
Expand Down
14 changes: 14 additions & 0 deletions tests/test_configuration.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,8 +5,11 @@

from wxflow import Configuration, cast_as_dtype

SOME_INPUT_ENVVAR1 = "input_envvar"

file0 = """#!/bin/bash
export SOME_ENVVAR1="${USER}"
export SOME_INPUT_ENVVAR1="${SOME_INPUT_ENVVAR1:-}"
export SOME_LOCALVAR1="myvar1"
export SOME_LOCALVAR2="myvar2.0"
export SOME_LOCALVAR3="myvar3_file0"
Expand Down Expand Up @@ -37,6 +40,7 @@

file0_dict = {
'SOME_ENVVAR1': os.environ['USER'],
'SOME_INPUT_ENVVAR1': "",
'SOME_LOCALVAR1': "myvar1",
'SOME_LOCALVAR2': "myvar2.0",
'SOME_LOCALVAR3': "myvar3_file0",
Expand All @@ -59,6 +63,9 @@
'SOME_BOOL6': False
}

file0_dict_set_envvar = file0_dict.copy()
file0_dict_set_envvar["SOME_INPUT_ENVVAR1"] = SOME_INPUT_ENVVAR1

file1_dict = {
'SOME_LOCALVAR3': "myvar3_file1",
'SOME_LOCALVAR4': "myvar4",
Expand Down Expand Up @@ -168,3 +175,10 @@ def test_parse_config2(tmp_path, create_configs):
ff_dict = file0_dict.copy()
ff_dict.update(file1_dict)
assert ff_dict == ff


@pytest.mark.skip(reason="fails in GH runner, passes on localhost")
def test_parse_config_w_envvar(tmp_path, create_configs):
cfg = Configuration(tmp_path)
f0 = cfg.parse_config('config.file0', SOME_INPUT_ENVVAR1=SOME_INPUT_ENVVAR1)
assert file0_dict_set_envvar == f0

0 comments on commit d314e06

Please sign in to comment.