Skip to main content

Python application configuration

Project description

<p align="center">
<a href="https://travis-ci.org/edaniszewski/bison"><img src="https://travis-ci.org/edaniszewski/bison.svg?branch=master" /></a>
<a href='https://coveralls.io/github/edaniszewski/bison'><img src='https://coveralls.io/repos/github/edaniszewski/bison/badge.svg' /></a>
<a href="https://pypi-hypernode.com/pypi/bison"><img src="https://img.shields.io/pypi/v/bison.svg"></a>
<a href="LICENSE"><img src="https://img.shields.io/github/license/edaniszewski/bison.svg"></a>

<h1 align="center">bison</h1>
</p>

<p align="center">Python application configuration</p>


## 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][viper] and the lack of good
application configuration solutions for Python (at least, in my opinion). Documentation
for Bison can be found on [ReadtheDocs][docs]

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:

```python
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][docs] 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".

```python
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,
```python
bison.Option('count', field_type=int)
```

Or, to restrict the values to a set of choices
```python
bison.Option('log', choices=['debug', 'info', 'warn', 'error'])
```

The [documentation][docs] 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.

```python
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.

```python
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
```python
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
```python
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
```python
config.parse()
```

### Example
Below is a complete example for parsing a hypothetical application configuration which
is described by the following YAML config.
```yaml
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
```

```python
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](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


[docs]: http://readthedocs
[viper]: https://github.com/spf13/viper

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.0.tar.gz (23.4 kB view details)

Uploaded Source

Built Distribution

bison-0.1.0-py2.py3-none-any.whl (27.6 kB view details)

Uploaded Python 2 Python 3

File details

Details for the file bison-0.1.0.tar.gz.

File metadata

  • Download URL: bison-0.1.0.tar.gz
  • Upload date:
  • Size: 23.4 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/1.9.0 pkginfo/1.4.2 requests/2.18.4 setuptools/38.5.2 requests-toolbelt/0.8.0 tqdm/4.19.6 CPython/3.6.5

File hashes

Hashes for bison-0.1.0.tar.gz
Algorithm Hash digest
SHA256 5e7b54f9164daf3409c7b047ae6fe8cb47a39a47a70cab93054c7e2bffc25ff3
MD5 9bec8d85942dcb9a28f493052d875a7c
BLAKE2b-256 28041e83ca95c5f50f90f050a368d9a7ac578e7331c7a2e975c89f7c1b255985

See more details on using hashes here.

File details

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

File metadata

  • Download URL: bison-0.1.0-py2.py3-none-any.whl
  • Upload date:
  • Size: 27.6 kB
  • Tags: Python 2, Python 3
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/1.9.0 pkginfo/1.4.2 requests/2.18.4 setuptools/38.5.2 requests-toolbelt/0.8.0 tqdm/4.19.6 CPython/3.6.5

File hashes

Hashes for bison-0.1.0-py2.py3-none-any.whl
Algorithm Hash digest
SHA256 79fa44a2b3ea68b9b9dd62baec646191324cb227c41980eb96a0c52d47188ccc
MD5 5c5e20a58251879114d6a5e2b0ffa12c
BLAKE2b-256 28ffc55f567dc3c852a8d051ff77e3eacb550afe1089389920b8bcf816f28bfb

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