Environs powered yaml files
gnarvaja opened this issue · comments
In many situations I found using code like this is pretty usefull when using yaml files but also want to follow the 12factor design pattern of using environment variables...
import yaml
from environs import EnvError, Env
envvar_matcher = re.compile(r'\$\{([A-Za-z0-9_]+)(:-[^\}]*)?\}')
env = Env()
class EnvVarLoader(yaml.FullLoader):
pass
def envvar_constructor(loader, node):
'''
Extract the matched value, expand env variable, and replace the match
${REQUIRED_ENV_VARIABLE} or ${ENV_VARIABLE:-default}
For using with yaml.FullLoader
'''
global env
value = node.value
match = envvar_matcher.match(value)
env_var = match.group(1)
default_value = match.group(2)
if default_value is not None:
return env.str(env_var, default_value[2:]) + value[match.end():]
else:
return env.str(env_var) + value[match.end():]
yaml.add_implicit_resolver('!envvar', envvar_matcher, Loader=EnvVarLoader)
yaml.add_constructor('!envvar', envvar_constructor, Loader=EnvVarLoader)
# Loads yaml replacing environment variables
data = yaml.load(open("my-config.yaml"), Loader=EnvVarLoader)
And the my-config.yaml
file being something like
user: ${USER}
image_dir: ${HOME:-/tmp}
I was thinking if this EnvVarLoader
can be included in environs. Should be optional since adds pyyaml
as extra dependency (will be an extra similar to django
).
I can do the pull-request. Just wanted to verify with you if it's aligned with your vision of environs or outside the scope. I think yaml is a very standard way of configuration and combining that with environs will be very powerful.
Instead of hardcoding FullLoader as base loader, it can be received as parameter. The same with the env
variable. Something like:
data = yaml.load(open("my-config.yaml"), Loader=environs.yaml_loader(env=myEnv, base_loader=yaml.FullLoader))
And perhaps some markup when the variable is not str.
Thanks for the suggestion! This is a neat idea.
I'd really like to keep the maintenance burden on this library as small as possible, so for now I'm going to pass on adding this to core. I think it'd make for a nice 3rd-party lib though. If you end up publishing it, let me know here and I can link to it in the README.
Ok, I understand. If you need help with the maintenance burden, I can help. I like environs, I use it a lot and I think I can help sharing the maintenance of the package if you want.
I am a Python developer since 2004, and I already got into environ's code when I added the expansion var feature.
I am @gnarvaja on Twitter, reach out me there if you want or by email (guillermo.narvaja arroba-at radiocut.fm )
Thanks for offering your help (and your help thus far), @gnarvaja . I'll definitely reach out if/when bus factor starts becoming an issue.