Skip to content

Instantly share code, notes, and snippets.

@juftin
Created November 16, 2019 23:21
Show Gist options
  • Save juftin/82f8680a6bb55cbbc41b31f3a7b0d1e2 to your computer and use it in GitHub Desktop.
Save juftin/82f8680a6bb55cbbc41b31f3a7b0d1e2 to your computer and use it in GitHub Desktop.
A safe way to read yml files with environmental variable integration
#!/usr/bin/env python
from os import environ
from re import compile
from yaml import SafeLoader, load
def yml(path=None, data=None, tag=None):
"""
Load a yaml configuration file (path) or data object(data)
and resolve any environment variables. The environment
variables must be in this format to be parsed: ${VAR_NAME}.
E.g.:
database:
host: ${HOST}
port: ${PORT}
${KEY}: ${VALUE}
app:
log_path: '/var/${LOG_PATH}'
something_else: '${AWESOME_ENV_VAR}/var/${A_SECOND_AWESOME_VAR}'
:param str path: the path to the yaml file
:param str data: the yaml data itself as a stream
:param str tag: the tag to look for
:return: the dict configuration
:rtype: dict[str, T]
"""
pattern = compile('.*?\${(\w+)}.*?')
loader = SafeLoader
loader.add_implicit_resolver(tag=tag, regexp=pattern, first=None)
def env_var_constructor(loader, node):
"""
Extracts the environment variable from the node's value
:param yaml.Loader loader: the yaml loader
:param node: the current node in the yaml
:return: the parsed string that contains the value of the environment
variable
"""
value = loader.construct_scalar(node=node)
match = pattern.findall(string=value)
if match:
full_value = value
for g in match:
full_value = full_value.replace(
f'${{{g}}}', environ.get(key=g, default=g))
return full_value
return value
loader.add_constructor(tag=tag, constructor=env_var_constructor)
if path:
with open(path) as conf_data:
return load(stream=conf_data, Loader=loader)
elif data:
return load(stream=data, Loader=loader)
else:
raise ValueError('Either a path or data should be defined as input')
yaml = yml("testing/yml.yml")
print(yaml)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment