sloria / environs

simplified environment variable parsing

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

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.