Skip to main content

Python application configuration

Project description

bison

Python application configuration

What is Bison?

Bison is a configuration solution for Python applications that aims to be simple and intuitive. It supports:

  • reading from YAML config files
  • reading from environment variables
  • setting explicit values
  • setting defaults
  • configuration validation
  • configuration access/manipulation with dot notation

Instead of implementing custom configuration reading and parsing, you can use Bison to handle it for you.

Bison was inspired by Viper and the lack of good application configuration solutions for Python (at least, in my opinion). Documentation for Bison can be found on ReadtheDocs

Bison uses the following precedence order. Each item in the list takes precedence over the item below it.

  • override (e.g. calling Bison.set())
  • environment
  • config file
  • defaults

Installation

Bison can be installed with pip

pip install bison

or with pipenv

pipenv install bison

Using Bison

Creating a configuration Scheme

A configuration scheme is not required by Bison, but having one allows you to set default values for configuration fields as well as do configuration validation. It is pretty easy to create a new Scheme:

scheme = bison.Scheme()

A Scheme is really just a container for configuration options, so without any options, a Scheme is somewhat useless.

Configuration Options

There are currently three types of configuration options:

  • bison.Option
  • bison.DictOption
  • bison.ListOption

Their intended functionality should be mostly obvious from their names. An Option represents a singular value in a configuration. A DictOption represents a dictionary or mapping of values in a configuration. A ListOption represents a list of values in a configuration.

See the documentation for more on how options can be configured.

Any number of options can be added to a Scheme, but as a simple example we can define a Scheme which expects a key "log", and a key "count".

scheme = bison.Scheme(
    bison.Option('log'),
    bison.Option('count'),
)

Configuration Validation

Validation operates based on the constraints set on the options. Above, there are no constraints (other than the need for those keys to exist), so any value for "log" and "count" will pass validation.

An option can be constrained in different ways by using its keyword arguments. For example, to ensure the value for "count" is an integer,

bison.Option('count', field_type=int)

Or, to restrict the values to a set of choices

bison.Option('log', choices=['debug', 'info', 'warn', 'error'])

The documentation goes into more detail about other validation settings.

Setting Defaults

If a default value is not set on an option, it is considered required. In these cases, if the key specified by that value is not present in the parse configuration, it will cause a validation failure.

If a default value is set, then the absence of that field in the configuration will not cause a validation failure.

bison.Option('log', default='info')

Configuring Bison

Once you have a Scheme to use (if you'd like to), it will need to be passed to a Bison object to manage the config building.

scheme = bison.Scheme()
config = bison.Bison(scheme)

There are a few options that can be set on the Bison object to change how it searches for and builds the unified configuration.

For reading configuration files

config.config_name = 'config'  # name of the config file (no extension)
config.add_config_paths(       # paths to look in for the config file
    '.',
    '/tmp/app'
)
config.config_format = bison.YAML # the config format to use

For reading environment variables

config.env_prefix = "MY_APP"  # the prefix to use for environment variables
config.auto_env = True  #  automatically bind all options to env variables based on their key

Building the unified config

Once the scheme has been set (if using) and Bison has been configured, the only thing left to do is to read in all the config sources and parse them into a unified config. This is done simply with

config.parse()

Example

Below is a complete example for parsing a hypothetical application configuration which is described by the following YAML config.

log: debug
port: 5000
settings:
  requests:
    timeout: 3
backends:
  - host: 10.1.2.3
    port: 5001
  - host: 10.1.2.4
    port: 5013
  - host: 10.1.2.5
    port: 5044
import bison

# the scheme for the configuration. this allows us to set defaults
# and validate configuration data
config_scheme = bison.Scheme(
    bison.Option('log', default='info', choices=['debug', 'info', 'warn', 'error']),
    bison.Option('port', field_type=int),
    bison.DictOption('settings', scheme=bison.Scheme(
        bison.DictOption('requests', scheme=bison.Scheme(
            bison.Option('timeout', field_type=int)
        ))
    )),
    bison.ListOption('backends', member_scheme=bison.Scheme(
        bison.Option('host', field_type=str),
        bison.Option('port', field_type=int)
    ))
)

# create a new Bison instance to store and manage configuration data
config = bison.Bison(scheme=config_scheme)

# set the config file name to 'app' (default is 'config') and set the
# search paths to '.' and '/tmp/app/config'
config.config_name = 'app'
config.add_config_paths('.', '/tmp/app/config')

# set the environment variable prefix and enable auto-env
config.env_prefix = 'MY_APP'
config.auto_env = True

# finally, parse the config sources to build the unified configuration
config.parse()

See the example directory for this example along with demonstrations of how to access configuration data.

Future Work

There is more that can be done to improve Bison and expand its functionality. If you wish to contribute, open a pull request. If you have questions or feature requests, open an issue. Below are some high level ideas for future improvements:

  • Support additional configuration formats (JSON, TOML, ...)
  • Versioned configurations

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

bison-0.1.3.macosx-10.15-x86_64.tar.gz (45.7 kB view details)

Uploaded Source

Built Distribution

bison-0.1.3-py2.py3-none-any.whl (24.4 kB view details)

Uploaded Python 2 Python 3

File details

Details for the file bison-0.1.3.macosx-10.15-x86_64.tar.gz.

File metadata

  • Download URL: bison-0.1.3.macosx-10.15-x86_64.tar.gz
  • Upload date:
  • Size: 45.7 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/3.4.1 importlib_metadata/3.7.3 pkginfo/1.7.0 requests/2.25.1 requests-toolbelt/0.9.1 tqdm/4.51.0 CPython/3.8.0

File hashes

Hashes for bison-0.1.3.macosx-10.15-x86_64.tar.gz
Algorithm Hash digest
SHA256 4b7ce2fb4ed2cbddb2dff604c34b6f4251dd8d6d178e50b3069ab623f0a8a2f6
MD5 a4609c5ede7b71836cdc1b4d80c9957d
BLAKE2b-256 7eca24c64e66d81924aeaee9db3085f0d5a355463fb8c1a187e441e5e1e68797

See more details on using hashes here.

File details

Details for the file bison-0.1.3-py2.py3-none-any.whl.

File metadata

  • Download URL: bison-0.1.3-py2.py3-none-any.whl
  • Upload date:
  • Size: 24.4 kB
  • Tags: Python 2, Python 3
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/3.4.1 importlib_metadata/3.7.3 pkginfo/1.7.0 requests/2.25.1 requests-toolbelt/0.9.1 tqdm/4.51.0 CPython/3.8.0

File hashes

Hashes for bison-0.1.3-py2.py3-none-any.whl
Algorithm Hash digest
SHA256 323e9613c7aa38319b4319e61a14f4b582785f0d568025c11633f32423f195c8
MD5 bce2be931ae319dd249d2a704ec51cee
BLAKE2b-256 cf26420810309eda0aafe7c89d2f35028f5bdcdb8a8d6583c107752a033bafe6

See more details on using hashes here.

Supported by

AWS AWS Cloud computing and Security Sponsor Datadog Datadog Monitoring Fastly Fastly CDN Google Google Download Analytics Microsoft Microsoft PSF Sponsor Pingdom Pingdom Monitoring Sentry Sentry Error logging StatusPage StatusPage Status page