Configuration environments

Dict (ConfigDictEnv)

class everett.manager.ConfigDictEnv(cfg)

Source for pulling configuration out of a dict.

This is handy for testing. You might also use it if you wanted to move all your defaults values into one centralized place.

Keys are prefixed by namespaces and the whole thing is uppercased.

For example, namespace “bar” for key “foo” becomes BAR_FOO in the dict.

For example:

from everett.manager import ConfigDictEnv, ConfigManager

config = ConfigManager([
    ConfigDictEnv({
        "FOO_BAR": "someval",
        "BAT": "1",
    })
])

Keys are not case sensitive. This also works:

from everett.manager import ConfigDictEnv, ConfigManager

config = ConfigManager([
    ConfigDictEnv({
        "foo_bar": "someval",
        "bat": "1",
    })
])

print config("foo_bar")
print config("FOO_BAR")
print config.with_namespace("foo")("bar")

Also, ConfigManager has a convenience classmethod for creating a ConfigManager with just a dict environment:

from everett.manager import ConfigManager

config = ConfigManager.from_dict({
    "FOO_BAR": "bat"
})

Changed in version 0.3: Keys are no longer case-sensitive.

Parameters:

cfg (Dict) –

Process environment (ConfigOSEnv)

class everett.manager.ConfigOSEnv

Source for pulling configuration out of the environment.

This source lets you specify configuration in the environment. This is useful for infrastructure related configuration like usernames and ports and secret configuration like passwords.

Keys are prefixed by namespaces and the whole thing is uppercased.

For example, key “foo” will be FOO in the environment.

For example, namespace “bar” for key “foo” becomes BAR_FOO in the environment.

Key and namespace can consist of alphanumeric characters and _.

Note

Unlike other config environments, this one is case sensitive in that keys defined in the environment must be all uppercase.

For example, these are good:

FOO=bar
FOO_BAR=bar
FOO_BAR1=bar

This is bad:

foo=bar

To use, instantiate and toss in the source list:

from everett.manager import ConfigOSEnv, ConfigManager

config = ConfigManager([
    ConfigOSEnv()
])

ENV files (ConfigEnvFileEnv)

class everett.manager.ConfigEnvFileEnv(possible_paths)

Source for pulling configuration out of .env files.

This source lets you specify configuration in an .env file. This is useful for local development when in production you use values in environment variables.

Keys are prefixed by namespaces and the whole thing is uppercased.

For example, key “foo” will be FOO in the file.

For example, namespace “bar” for key “foo” becomes BAR_FOO in the file.

Key and namespace can consist of alphanumeric characters and _.

To use, instantiate and toss in the source list:

from everett.manager import ConfigEnvFileEnv, ConfigManager

config = ConfigManager([
    ConfigEnvFileEnv('.env')
])

For multiple paths:

from everett.manager import ConfigEnvFileEnv, ConfigManager

config = ConfigManager([
    ConfigEnvFileEnv([
        '.env',
        'config/prod.env'
    ])
])

Here’s an example .env file:

DEBUG=true

# secrets
SECRET_KEY=ou812

# database setup
DB_HOST=localhost
DB_PORT=5432

# CSP reporting
CSP_SCRIPT_SRC="'self' www.googletagmanager.com"
Parameters:

possible_paths (str | List[str]) –

Python objects (ConfigObjEnv)

class everett.manager.ConfigObjEnv(obj, force_lower=True)

Source for pulling configuration values out of a Python object.

This is handy for a few weird situations. For example, you can use this to “bridge” Everett configuration with command line arguments. The argparse Namespace works fine here.

Namespace (the Everett one–not the argparse one) is prefixed. So key “foo” in namespace “bar” is “foo_bar”.

For example:

import argparse

from everett.manager import ConfigObjEnv, ConfigManager

parser = argparse.ArgumentParser()
parser.add_argument(
    "--debug", help="to debug or not to debug"
)
parsed_vals = parser.parse_known_args()[0]

config = ConfigManager([
    ConfigObjEnv(parsed_vals)
])

print config("debug", parser=bool)

Keys are not case-sensitive–everything is converted to lowercase before pulling it from the object.

Note

ConfigObjEnv has nothing to do with the library configobj.

New in version 0.6.

Parameters:
  • obj (Any) –

  • force_lower (bool) –

INI files (ConfigIniEnv)

class everett.ext.inifile.ConfigIniEnv(possible_paths)

Source for pulling configuration from INI files.

This requires optional dependencies. You can install them with:

$ pip install 'everett[ini]'

Takes a path or list of possible paths to look for a INI file. It uses the first INI file it can find.

If it finds no INI files in the possible paths, then this configuration source will be a no-op.

This will expand ~ as well as work relative to the current working directory.

This example looks just for the INI file specified in the environment:

from everett.manager import ConfigManager
from everett.ext.inifile import ConfigIniEnv

config = ConfigManager([
    ConfigIniEnv(possible_paths=os.environ.get("FOO_INI"))
])

If there’s no FOO_INI in the environment, then the path will be ignored.

Here’s an example that looks for the INI file specified in the environment variable FOO_INI and failing that will look for .antenna.ini in the user’s home directory:

from everett.manager import ConfigManager
from everett.ext.inifile import ConfigIniEnv

config = ConfigManager([
    ConfigIniEnv(
        possible_paths=[
            os.environ.get("FOO_INI"),
            "~/.antenna.ini"
        ]
    )
])

This example looks for a config/local.ini file which overrides values in a config/base.ini file both are relative to the current working directory:

from everett.manager import ConfigManager
from everett.ext.inifile import ConfigIniEnv

config = ConfigManager([
    ConfigIniEnv(possible_paths="config/local.ini"),
    ConfigIniEnv(possible_paths="config/base.ini")
])

Note how you can have multiple ConfigIniEnv files and this is how you can set Everett up to have values in one INI file override values in another INI file.

INI files must have a “main” section. This is where keys that aren’t in a namespace are placed.

Minimal INI file:

[main]

In the INI file, namespace is a section. So key “user” in namespace “foo” is:

[foo]
user=someval

Everett uses configobj, so it supports nested sections like this:

[main]
foo=bar

[namespace]
foo2=bar2

  [[namespace2]]
  foo3=bar3

Which gives you these:

  • FOO

  • NAMESPACE_FOO2

  • NAMESPACE_NAMESPACE2_FOO3

See more details here: http://configobj.readthedocs.io/en/latest/configobj.html#the-config-file-format

Parameters:

possible_paths (str | List[str]) – either a single string with a file path (e.g. "/etc/project.ini" or a list of strings with file paths

YAML files (ConfigYamlEnv)

class everett.ext.yamlfile.ConfigYamlEnv(possible_paths)

Source for pulling configuration from YAML files.

This requires optional dependencies. You can install them with:

$ pip install 'everett[yaml]'

Takes a path or list of possible paths to look for a YAML file. It uses the first YAML file it can find.

If it finds no YAML files in the possible paths, then this configuration source will be a no-op.

This will expand ~ as well as work relative to the current working directory.

This example looks just for the YAML file specified in the environment:

from everett.manager import ConfigManager
from everett.ext.yamlfile import ConfigYamlEnv

config = ConfigManager([
    ConfigYamlEnv(os.environ.get('FOO_YAML'))
])

If there’s no FOO_YAML in the environment, then the path will be ignored.

Here’s an example that looks for the YAML file specified in the environment variable FOO_YAML and failing that will look for .antenna.yaml in the user’s home directory:

from everett.manager import ConfigManager
from everett.ext.yamlfile import ConfigYamlEnv

config = ConfigManager([
    ConfigYamlEnv([
        os.environ.get('FOO_YAML'),
        '~/.antenna.yaml'
    ])
])

This example looks for a config/local.yaml file which overrides values in a config/base.yaml file both are relative to the current working directory:

from everett.manager import ConfigManager
from everett.ext.yamlfile import ConfigYamlEnv

config = ConfigManager([
    ConfigYamlEnv('config/local.yaml'),
    ConfigYamlEnv('config/base.yaml')
])

Note how you can have multiple ConfigYamlEnv files. This is how you can set Everett up to have values in one YAML file override values in another YAML file.

Everett looks for keys and values in YAML files. YAML files can be split into multiple documents, but Everett only looks at the first one.

Keys are case-insensitive. You can do namespaces either in the key itself using _ as a separator or as nested mappings.

All values should be double-quoted.

Here’s an example:

foo: "bar"
FOO2: "bar"
namespace_foo: "bar"
namespace:
    namespace2:
        foo: "bar"

Giving you these namespaced keys:

  • FOO

  • FOO2

  • NAMESPACE_FOO

  • NAMESPACE_NAMEPSACE2_FOO

Parameters:

possible_paths (str | List[str]) – either a single string with a file path (e.g. "/etc/project.yaml" or a list of strings with file paths

Implementing your own configuration environments

You can implement your own configuration environments. For example, maybe you want to pull configuration from a database or Redis or a post-it note on the refrigerator.

They just need to implement the .get() method. A no-op implementation is this:

# environments.py

from everett import NO_VALUE
from everett.manager import listify


class NoOpEnv(object):
    def get(self, key, namespace=None):
        # The namespace is either None, a string or a list of
        # strings. This converts it into a list.
        namespace = listify(namespace)

        # FIXME: Your code to extract the key in namespace here.

        # At this point, the key doesn't exist in the namespace
        # for this environment, so return a ``NO_VALUE``.
        return NO_VALUE

Generally, environments should return a value if the key exists in that environment and should return NO_VALUE if and only if the key does not exist in that environment.

For exceptions, it depends on what you want to have happen. It’s ok to let exceptions go unhandled–Everett will wrap them in a everett.ConfigurationError. If your environment promises never to throw an exception, then you should handle them all and return NO_VALUE since with that promise all exceptions would indicate the key is not in the environment.