Configuration library for Python applications
Project description
=======
Everett
=======
Everett is a configuration library.
:Code: https://github.com/willkg/everett
:Issues: https://github.com/willkg/everett/issues
:License: MPL v2
:Documentation: https://everett.readthedocs.io/
Goals
=====
This library tries to do configuration with minimal "fanciness":
Configuration with Everett:
* is composeable and flexible
* can pull configuration from a variety of specified sources (environment, ini
files, dict, write-your-own)
* supports parsing values (bool, int, lists, ..., write-your-own)
* supports key namespaces
* facilitates writing tests that change configuration values
* supports component architectures with auto-documentation of configuration with
a Sphinx ``autoconfig`` directive
Everett is inspired by `python-decouple
<https://github.com/henriquebastos/python-decouple>`_ and `configman
<https://configman.readthedocs.io/en/latest/>`_.
Why not other libs?
===================
Most other libraries I looked at had one or more of the following issues:
* were tied to a specific web app framework
* didn't allow you to specify configuration sources
* had a global configuration object
* made it really hard to override specific configuration when writing tests
* had no facilities for auto-documenting configuration for components
Quick start
===========
You're writing a web app using some framework that doesn't provide
infrastructure for configuration.
You want to pull configuration from an INI file stored in a place specified by
``FOO_INI`` in the environment. You want to pull infrastructure values from the
environment. Values from the environment should override values from the INI
file.
First, you set up your ``ConfigManager`` in your webapp::
from everett.manager import ConfigManager, ConfigOSEnv, ConfigIniEnv
class MyWSGIApp(SomeFrameworkApp):
def __init__(self):
self.config = ConfigManager([
ConfigOSEnv(),
ConfigIniEnv([
os.environ.get('FOO_INI'),
'~/.foo.ini',
'/etc/foo.ini'
]),
])
# Set ``is_debug`` based on configuration
self.is_debug = self.config('debug', parser=bool)
def get_app():
return MyWSGIApp()
Let's write some tests that verify behavior based on the ``debug`` configuration
value::
from everett.manager import config_override
@config_override(DEBUG='true')
def test_debug_true():
app = get_app()
...
@config_override(DEBUG='false')
def test_debug_false():
app = get_app()
...
(``config_override`` works as a class decorator and a context manager, too.)
That probably covers most configuration requirements.
However, say your app needs to connect to RabbitMQ. One way to implement that
functionality is to wrap it up in a self-contained component::
from everett.component import RequiredConfigMixin, ConfigOptions
class RabbitMQComponent(RequiredConfigMixin):
required_config = ConfigOptions()
required_config.add_option(
'host',
doc='RabbitMQ host to connect to'
)
required_config.add_option(
'port',
default='5672',
doc='Port to use',
parser=int
)
required_config.add_option(
'queue_name',
doc='Queue to insert things into'
)
def __init__(self, config):
# Bind the configuration to just the configuration this
# component requires such that this component is
# self-contained.
self.config = config.with_options(self)
self.host = self.config('host')
self.port = self.config('port')
self.queue_name = self.config('queue_name')
Then in your app, you instantiate a ``RabbitMQComponent``, but with configuration
in the ``rmq`` namespace::
queue = RabbitMQComponent(config.with_namespace('rmq'))
In your environment, you would provide ``RMQ_HOST``, etc for this component.
Say your app actually needs to connect to two separate queues--one for regular
processing and one for priority processing::
regular_queue = RabbitMQComponent(
config.with_namespace('regular').with_namespace('rmq')
)
priority_queue = RabbitMQComponent(
config.with_namespace('priority').with_namespace('rmq')
)
In your environment, you provide the regular queue configuration with
``RMQ_REGULAR_HOST``, etc and the priority queue configuration with
``RMQ_PRIORITY_HOST``, etc.
Same component code--two different instances.
Install
=======
>From PyPI
---------
Run::
$ pip install everett
For hacking
-----------
Run::
# Clone the repository
$ git clone https://github.com/willkg/everett
# Create a virtualenvironment
...
# Install Everett and dev requirements
$ pip install -r requirements-dev.txt
History
=======
0.4 (October 27th, 2016)
------------------------
Feature: Add ``raw_value`` argument to config calls. This makes it easier to
write code that prints configuration.
Bug: Fix ``listify(None)`` to return ``[]``.
Documentation fixes and updates.
0.3.1 (October 12th, 2016)
--------------------------
Bug: Fix ``alternate_keys`` with components. Previously it worked for everything
but components. Now it works with components, too.
0.3 (October 6th, 2016)
-----------------------
Feature: Add ``ConfigManager.from_dict()`` shorthand for building configuration
instances.
Feature: Add ``.get_namespace()`` to ``ConfigManager`` and friends for getting
the complete namespace for a given config instance as a list of strings.
Feature: Make ``ConfigDictEnv`` case-insensitive to keys and namespaces.
Feature: Add ``alternate_keys`` to config call. This lets you specify a list
of keys in order to try if the primary key doesn't find a value. This is
helpful for deprecating keys that you used to use in a backwards-compatible
way.
Feature: Add ``root:`` prefix to keys allowing you to look outside of the
current namespace and at the configuration root for configuration values.
0.2 (August 16th, 2016)
-----------------------
Feature: Add ``ConfigEnvFileEnv`` for supporting ``.env`` files. Thank you,
Paul!
Feature: Change ``ConfigIniEnv`` to take a single path or list of paths. Thank
you, Paul!
Feature: Add "on" and "off" as valid boolean values. This makes it easier to use
config for feature flippers. Thank you, Paul!
Feature: Make ``NO_VALUE`` falsy.
Bug: Fix ``__call__`` returning None--it should return ``NO_VALUE``.
Lots of docs updates: finished the section about making your own parsers, added
a section on using dj-database-url, added a section on django-cache-url and
expanded on existing examples.
0.1 (August 1st, 2016)
----------------------
Initial writing.
Everett
=======
Everett is a configuration library.
:Code: https://github.com/willkg/everett
:Issues: https://github.com/willkg/everett/issues
:License: MPL v2
:Documentation: https://everett.readthedocs.io/
Goals
=====
This library tries to do configuration with minimal "fanciness":
Configuration with Everett:
* is composeable and flexible
* can pull configuration from a variety of specified sources (environment, ini
files, dict, write-your-own)
* supports parsing values (bool, int, lists, ..., write-your-own)
* supports key namespaces
* facilitates writing tests that change configuration values
* supports component architectures with auto-documentation of configuration with
a Sphinx ``autoconfig`` directive
Everett is inspired by `python-decouple
<https://github.com/henriquebastos/python-decouple>`_ and `configman
<https://configman.readthedocs.io/en/latest/>`_.
Why not other libs?
===================
Most other libraries I looked at had one or more of the following issues:
* were tied to a specific web app framework
* didn't allow you to specify configuration sources
* had a global configuration object
* made it really hard to override specific configuration when writing tests
* had no facilities for auto-documenting configuration for components
Quick start
===========
You're writing a web app using some framework that doesn't provide
infrastructure for configuration.
You want to pull configuration from an INI file stored in a place specified by
``FOO_INI`` in the environment. You want to pull infrastructure values from the
environment. Values from the environment should override values from the INI
file.
First, you set up your ``ConfigManager`` in your webapp::
from everett.manager import ConfigManager, ConfigOSEnv, ConfigIniEnv
class MyWSGIApp(SomeFrameworkApp):
def __init__(self):
self.config = ConfigManager([
ConfigOSEnv(),
ConfigIniEnv([
os.environ.get('FOO_INI'),
'~/.foo.ini',
'/etc/foo.ini'
]),
])
# Set ``is_debug`` based on configuration
self.is_debug = self.config('debug', parser=bool)
def get_app():
return MyWSGIApp()
Let's write some tests that verify behavior based on the ``debug`` configuration
value::
from everett.manager import config_override
@config_override(DEBUG='true')
def test_debug_true():
app = get_app()
...
@config_override(DEBUG='false')
def test_debug_false():
app = get_app()
...
(``config_override`` works as a class decorator and a context manager, too.)
That probably covers most configuration requirements.
However, say your app needs to connect to RabbitMQ. One way to implement that
functionality is to wrap it up in a self-contained component::
from everett.component import RequiredConfigMixin, ConfigOptions
class RabbitMQComponent(RequiredConfigMixin):
required_config = ConfigOptions()
required_config.add_option(
'host',
doc='RabbitMQ host to connect to'
)
required_config.add_option(
'port',
default='5672',
doc='Port to use',
parser=int
)
required_config.add_option(
'queue_name',
doc='Queue to insert things into'
)
def __init__(self, config):
# Bind the configuration to just the configuration this
# component requires such that this component is
# self-contained.
self.config = config.with_options(self)
self.host = self.config('host')
self.port = self.config('port')
self.queue_name = self.config('queue_name')
Then in your app, you instantiate a ``RabbitMQComponent``, but with configuration
in the ``rmq`` namespace::
queue = RabbitMQComponent(config.with_namespace('rmq'))
In your environment, you would provide ``RMQ_HOST``, etc for this component.
Say your app actually needs to connect to two separate queues--one for regular
processing and one for priority processing::
regular_queue = RabbitMQComponent(
config.with_namespace('regular').with_namespace('rmq')
)
priority_queue = RabbitMQComponent(
config.with_namespace('priority').with_namespace('rmq')
)
In your environment, you provide the regular queue configuration with
``RMQ_REGULAR_HOST``, etc and the priority queue configuration with
``RMQ_PRIORITY_HOST``, etc.
Same component code--two different instances.
Install
=======
>From PyPI
---------
Run::
$ pip install everett
For hacking
-----------
Run::
# Clone the repository
$ git clone https://github.com/willkg/everett
# Create a virtualenvironment
...
# Install Everett and dev requirements
$ pip install -r requirements-dev.txt
History
=======
0.4 (October 27th, 2016)
------------------------
Feature: Add ``raw_value`` argument to config calls. This makes it easier to
write code that prints configuration.
Bug: Fix ``listify(None)`` to return ``[]``.
Documentation fixes and updates.
0.3.1 (October 12th, 2016)
--------------------------
Bug: Fix ``alternate_keys`` with components. Previously it worked for everything
but components. Now it works with components, too.
0.3 (October 6th, 2016)
-----------------------
Feature: Add ``ConfigManager.from_dict()`` shorthand for building configuration
instances.
Feature: Add ``.get_namespace()`` to ``ConfigManager`` and friends for getting
the complete namespace for a given config instance as a list of strings.
Feature: Make ``ConfigDictEnv`` case-insensitive to keys and namespaces.
Feature: Add ``alternate_keys`` to config call. This lets you specify a list
of keys in order to try if the primary key doesn't find a value. This is
helpful for deprecating keys that you used to use in a backwards-compatible
way.
Feature: Add ``root:`` prefix to keys allowing you to look outside of the
current namespace and at the configuration root for configuration values.
0.2 (August 16th, 2016)
-----------------------
Feature: Add ``ConfigEnvFileEnv`` for supporting ``.env`` files. Thank you,
Paul!
Feature: Change ``ConfigIniEnv`` to take a single path or list of paths. Thank
you, Paul!
Feature: Add "on" and "off" as valid boolean values. This makes it easier to use
config for feature flippers. Thank you, Paul!
Feature: Make ``NO_VALUE`` falsy.
Bug: Fix ``__call__`` returning None--it should return ``NO_VALUE``.
Lots of docs updates: finished the section about making your own parsers, added
a section on using dj-database-url, added a section on django-cache-url and
expanded on existing examples.
0.1 (August 1st, 2016)
----------------------
Initial writing.
Project details
Release history Release notifications | RSS feed
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
everett-0.4.tar.gz
(32.8 kB
view hashes)
Built Distribution
everett-0.4-py2.py3-none-any.whl
(17.0 kB
view hashes)
Close
Hashes for everett-0.4-py2.py3-none-any.whl
Algorithm | Hash digest | |
---|---|---|
SHA256 | cb09a80fbbba76d17c7297d4fd98ead47d36972f989c37da98130ec7c84402c3 |
|
MD5 | 1b23d6e9f0daae2983461c7d63576e0a |
|
BLAKE2b-256 | 1e64b5262e7492a2932b520184e3ba63a5fc28f10a6f9843747f0f2b897136cb |