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 aConfigManager
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 aconfig/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 aconfig/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.