Usage

Basic Concepts

Config Engine works defining configuration options in a consistent manner by registering Option objects to a Configuration object. The Option objects can represent a particular option type and may have their own options for defining constraints on the option values. For example a NumberOption has the ability to define a range using minimum and maximum values.

A Configuration does not need to have all options registered before attempting to read configuration. This allows individual modules and libraries that share the use of Config Engine to be able to register their own option sets independently as long as they do not have name conflicts.

Registering and Reading Options

While it is possible to have multiple instances of the py:class:~conf_engine.configuration.Configuration object, it’s typically not needed. Most use cases can take advantage of the module level object. In the below example the module level object is used to register a string option for both a username and password.

Registering and reading options.
from conf_engine import config
from conf_engine import options

# Create option list.
options = [
    options.StringOption('username'),
    options.StringOption('password'),
    options.BooleanOption('debug', default=False)
]

# Register options.
config.register_options(options)

# Read option values.
username = config.username
password = config.password


In the above example a debug mode option is also registered with a default value of False. Default values will be returned if a value for the option cannot be found in any of the configuration sources.

Option Groups

Groups can be used to organize options with a similar purpose. For example an application may need to access two different APIs. By utilizing groups the credentials for each API can be defined separately using similar naming semantics.

Registering and accessing option groups.
from conf_engine import config
from conf_engine import options

# Create option list.
api1_options = [
    options.StringOption('api_url'),
    options.StringOption('token')
]
api2_options = [
    options.StringOption('api_url'),
    options.StringOption('token'),
    options.NumberOption('version')
]

# Register options.
config.register_options(api1_options, group='api1')
config.register_options(api2_options, group='api2')

# Read option values.
api1_username = config.api1.username
api2_version = config.api2.version

Creating and Consuming Configuration

Configuration data can be consumed by Config Engine from either operating system environment variables or from ini style files. When consuming from environment variables options names are capitalized and prepended with their group name followed by an _ character. For ini style configuration all options must be defined in sections. The section name corresponds with the option group and the [DEFAULT] section is used for any options defined with no group.

By default Config Engine will look int the current working directory for any files with the .ini extension and load them as configuration. However it is possible to define the location of configuration data by using the --config-file and --config-directory CLI options when starting your application.

Configuration Data Caching

By default Config Engine will store the value of a configuration option once it has been read from the configuration source. However, this caching behavior can be disabled by passing cache=False when creating a Configuration object, or a ConfigGroup.

Cached data can also be invalidated by calling the flush_cache() method on either the Configuration object, or the ConfigGroup as well.

Registering and accessing option groups.
from conf_engine import Configuration
from conf_engine import options

# Create option list.
cache_options = [
    options.StringOption('username'),
    options.StringOption('password'),
]

no_cache_options = [
    options.BooleanOption('debug', default=False)
]

# Create two configuration groups, one that caches, and one that does not.
# Then register the options.
caching_config = Configuration(cache=True)
no_cache_config = Configuration(cache=False)
caching_config.register_options(cache_options)
no_cache_config.register_options(no_cache_options)

# This will only read from source once, and then use that
# value in subsequent lookups
print(caching_config.username)

# This will only read from configuration source, and never
# from the cache.
print(no_cache_options.debug)


Namespaces

The environment parser supports an optional namespace which will prepend each option with the namespace and an underscore to help ensure that the given option doesn’t have a name collision with other unrelated environment variables. Namespaces require the use of a declared configuration object rather than using the one provided in the ConfEngine module. Declaring options and accessing option values through the configuration object remains unchanged.

Using namespaces.
"""
Export your var before running the script.

.. code-block:
    ~# export TESTNS_MYGROUP_MY_VAR=namespaces
"""

from conf_engine import Configuration, options

# Create config object.
config = Configuration(namespace='testns')
# Register options.
config.register_option(options.StringOption('my_var'))

assert config.my_var == 'namespaces'