Overridable config for shared libraries.
Partly inspired by Django’s from django.conf import settings settings object.
The goal is to allow shared libraries to be configured by a settings file in the project which imports them (like how Django libraries can expect the Django settings object to exist).
pip install flexisettings
We want the shared lib to be able to load config values from the app which is importing it.
A suggested layout would be as found in test_project/test_lib in this repo. For example, create a test_lib/conf/__init__.py like:
from flexisettings import Settings settings = Settings(initial_namespace='TEST_LIB', defaults='test_lib.conf.defaults')
We have a concept of customisable ‘namespace’ (prefix) for config values. This is as defined by the ConfigLoader lib we are making use of.
initial_namespace is the default namespace for config values of your shared lib. Projects who want to use your lib will be able to customise the namespace, but as they are used for bootstrapping there are two config values which will always use the default name (APP_CONFIG and CONFIG_NAMESPACE).
So for example, say myapp wants to use test_lib. myapp can customise the namespace by defining TEST_LIB_CONFIG_NAMESPACE = 'CUSTOM'.
defaults is the import path to a python module or object in your shared lib which contains default values for your config. These keys should not be namespaced.
For example if you want the config namespace for your shared lib to be configurable via env var you could create test_lib/conf/defaults.py like:
import os # namespace for config keys loaded from e.g. Django conf or env vars CONFIG_NAMESPACE = os.getenv('TEST_LIB_CONFIG_NAMESPACE', 'TEST_LIB') APP_CONFIG = os.getenv('TEST_LIB_APP_CONFIG', None)
Then myapp would be able to export TEST_LIB_CONFIG_NAMESPACE=CUSTOM.
That explains namespace customisation a bit, what about the APP_CONFIG?
Say for example that myapp is a Django website and test_lib has the defaults file shown above. In your myapp project you could:
export TEST_LIB_CONFIG_NAMESPACE=CUSTOM export TEST_LIB_APP_CONFIG=django.conf.settings
Then in myapp/settings.py you could have:
CUSTOM_VAR1 = 'whatever'
Now, recall the test_lib/conf/__init__.py that we created at the start. In your test_lib code you could have:
from test_lib.conf import settings assert settings.VAR1 == 'whatever'
As you can see the VAR1 was set in the importing project’s Django settings with the CUSTOM_ prefix but is available in your shared lib’s settings object under its non-prefixed name.
This project is tested against:
Running the tests
The cli does not support ‘workflows’ at the moment so you have to run the two Python version jobs separately:
circleci build --job python-2.7
circleci build --job python-3.6
py.test (single python version)
It’s also possible to run the tests locally, allowing for debugging of errors that occur.
Now decide which Python version you want to test and create a virtualenv:
pyenv virtualenv 3.6.4 flexisettings pip install -r requirements-test.txt
The code in test_project demonstrates collaborative config between a shared library test_lib and the app that wants to use it app. Set the path to the test project