diff --git a/README.md b/README.md index 86ea4a3..51c4e02 100644 --- a/README.md +++ b/README.md @@ -1,14 +1,21 @@ # Override # A simple, pure Python configuration tool. -TL;DR: It inserts a templated Python shim file between your application and your config. +TL;DR: It inserts a templated Python shim file between your application and your config, at 'build time'. + +* [Usage](#usage) + + [Pure Python Configs](#pure-python-configs) + + [Overriding](#overriding) + + [Template](#template) + + [Tips, Tricks & Pitfalls](#tips--tricks---pitfalls) +* [API](#api) ## Summary ## Instead of juggling lots of configurations and copying between them, you can: - Use Python to obtain and modify configurations as normal. - Inherit configurations using standard Python import behaviour. - Change configuration parameters at run time using command line or environment variables. -- Leverages import caching - once the import hierarchy is resolved, other code from the process +- Leverage import caching - once the import hierarchy is resolved, other code from the process will be using Python's import cache. There are no repetitive function calls involved in 'getting' your config. - Keep your local/development config `.gitignore`'d, and it will inherit new @@ -26,20 +33,6 @@ The simplest use case looks something like this: application ``` -### Template ### -The shim looks like this (yes, pep8 compliant): -``` -# -*- coding: utf-8 -*- -# This file is auto-generated from settings in: -# C:\Users\david\Documents\coding\override\example\example2.py - -from my_configs.one import * -post_import(locals()) - -from override import RuntimeUpdates as _RTU -_RTU('set').apply_all(locals()) -``` - ## Usage ## ### Pure Python Configs ### @@ -74,22 +67,36 @@ Here's an extreme example of hierarchy, in which each file imports the one above - some_code.py # and, at last, you use your config variable ### Overriding ### -Normally you would just run your project: +Normally you would just run your project, and use the config in your code: ``` python my_project.py ``` -But you can override your settings on the command line: +But you can override your config on the command line: ``` -python my_project.py --set=key.subkey=value +python my_project.py --override=key.subkey=value ``` Or using an environment variable: ``` -export set=key.subkey=value +export override=key.subkey=value python my_project.py ``` +### Template ### +The shim looks like this (yes, pep8 compliant): +``` +# -*- coding: utf-8 -*- +# This file is auto-generated from settings in: +# C:\Users\david\Documents\coding\override\example\example2.py + +from my_configs.one import * +post_import(locals()) + +from override import RuntimeUpdates as _RTU +_RTU('set').apply_all(locals()) +``` + ### Tips, Tricks & Pitfalls ### You may want to consider that: - Configs are Python and expected to be loaded from a trusted source. You could always, say, diff --git a/override/project.py b/override/project.py index fac349e..f69172e 100644 --- a/override/project.py +++ b/override/project.py @@ -25,21 +25,35 @@ class Project: """ - A project is an instance of the configuration system. + A project is an instance of a configuration system. + + Describes where config modules can be imported from + and where the shim file is to be placed """ def __init__( self, config_path='configs', config_module='config.py', - template=DEFAULT_TEMPLATE, - template_path=None, relative_root=None, - runtime_override_key=None, + runtime_override_key='override', post_import_handler=None, post_load_handler=None, - post_configure_callback=None + post_configure_callback=None, + template=DEFAULT_TEMPLATE, + template_path=None, ): + """ + :param config_path: full name of the shim file to be generated (path can be relative) + :param config_module: python module path to use when importing config variants + :param relative_root: [opt] path from which others are relative + :param runtime_override_key: [opt] the string used when overriding settings for cli and env + :param post_import_handler: [opt] string name of function to invoke after hierarchy load + :param post_load_handler: [opt] string name of function to invoke after hierarchy + overrides load + :param post_configure_callback: [opt] function to be directly called whenever this config is written + :param template: [opt] a string defining the shim + :param template_path: [opt] a path to a file containing a shim template (path can be relative) + """ self.config_path = config_path self.config_module = config_module self.template_path = template_path @@ -91,6 +105,7 @@ def apply_config(self, name=None): post_import_handler=self.post_import_handler, post_load_handler=self.post_load_handler, )) + logger.info('writing config `%s` into %s', self.selected, self.config_path) self.validate_config() with open(self.config_path, 'w') as fh: