cfeconfig

Manage app configuration with CLI options, Config File, or Env.


License
MIT
Install
pip install cfeconfig==0.5.1

Documentation

CFEconfig

This module exists to support the 12-factor App approach to configuration, while also supporting convenient CLIs. This provides overlapping functionality with the click module, so you may not need this if you're already using click, though by using both modules, you may benefit from our distinct way of handling of config files and environment variables.

You can specify your configurable options in 3 ways, in any combination:

  • Via environment variables named as 'PREFIX_OPTION_NAME' where prefix is a string you choose to identify the application instance.
  • Via a YAML format configuration file of key-value pairs.
  • Via arguments to your main script.

If the same option is specified in more than one place, CLI options take precendence over Config File options which take precendence over Environment Variables. This rule is the origin of the package name: CFE = CLI->File->Environment.

Further, and unlike click, we push CLI and File-based options into the Environment, so that applications and modules which do not use this module can still read them. Code that does call config.get, will receive immutable values representing the state of the Environment variables at the time of program start-up[1] , regardless of what has happened to environment variables since.

We assume, but do not require, the use of the docopt module to handle configuration via command-line arguments. Any dict[str, str] of config values will do, if you prefer to use alternate argument parsing.

Typical usage

  1. Read command-line args first, e.g., opts = docopt.docopt(__doc__)
  2. Read and store environment variables, with config.load(opts, 'some_env_var_prefix').
  3. Throughout the application, use config.get() to get a dict of configuration values or config.get('option_name') to get a specific option value.
    """Usage: myapp.py [--foo] [--bar]"""
    from cfeconfig import config
    from docopt import docopt

    from mylib import myfunction

    opts = docopt(__doc__)
    config.load(opts, 'myapp', 'config.yml')  # Push opts to Environment.
    CONFIG = config.get()
    myfunction(CONFIG)

See DocTests in module functions for examples.

Theoretical Example usage with click

    import os

    from click import click
    from cfeconfig import config

    @click.command
    @click.option('--a')
    @click.option('--b')
    def cli(**kwargs):
        config.load(kwargs, 'myapp')
        do_stuff()  # More likely we're calling some code in our library.

    def do_stuff():
        CONFIG = config.get()
        assert CONFIG['A'] == os.environ['MYAPP_A']

    if __name__ == '__main__':
        cli()

[1] More precisely, at the time config.load() was called.