Function Configuration module - funconf¶
Overview.¶
To simplify the management of function default keyword argument values funconf introduces two new decorators. The first function wraps_kwargs() makes it trivial to dynamically define the default kwargs for a function. The second function lazy_string_cast() automatically casts basestring values to the type of the keyword default values found in the function it is wrapping and the type of the values found in the key:value object passed into its constructor.
For configuration, funconf borrows from concepts discussed in Python’s core library ConfigParser. A configuration consists of sections made up of option:value entries, or two levels of mappings that take on the form section:option:value.
The file format YAML has been chosen to allow for option values to exist as different types instead of being restricted to string type values.
The configuration file¶
Example of a simple YAML configuration file:
$ cat my.conf
#
# Foo
#
foo:
bar: 4
moo:
- how
- are
- you
#
# Bread
#
bread:
butter: win
milk: fail
This file contains two sections foo and bread. foo has two options bar and moo. bar is an integer value of 4 and moo is a list of strings containing ['how', 'are', 'you'].
The above configuration could be generated through a process of adding each option: value into a Config object then casting it to a string. For example:
config = funconf.Config()
config.set('foo', 'bar', 4)
config.set('foo', 'bar', ['how', 'are', 'you'])
config.set('bread', 'butter', 'milk')
config.set('bread', 'milk', 'fail')
print(config)
A configuration object¶
The Config class is the root class container for all of the configuration sections. It implements the MutableMapping type which allows it to seamlessly integrate into the wraps_kwargs() function.
As a dictionary dict(config) the Config object looks like:
{'bread_butter': 'win',
'bread_milk': 'fail',
'foo_bar': 4,
'foo_moo': ['how', 'are', 'you']}
Notice how the configuration section:options have been concatenated. This facilitates the simple wrapping of an entire configuration file into the kwargs of a function. The following example will print an equivalent dictionary to the printout in the previous example.
@config
def myfunc(**kwargs):
print(kwargs)
A configuration section¶
To access sections and option values the following pattern holds true:
assert config.bread.milk == 'fail'
assert config.bread['milk'] == 'fail'
assert config['bread_milk'] == 'fail'
A section is represented by the ConfigSection object. This object implements the MutableMapping type in the same way the Config object is implemented and is compatible with the wraps_kwargs() function. The ConfigSection represented str(config.bread) looks like:
bread:
butter: win
milk: fail
Just like the Config class, the ConfigSection can be used as a decorator to a function too. Here is an example:
@config.bread
def myfunc(**kwargs):
print(kwargs)
Code reference guide¶
- funconf.wraps_kwargs(default_kwargs)[source]¶
Decorate a function to define and extend its default keyword argument values.
The following example will redefine myfunc to have default kwargs of a=4 and b=2:
mydict = {a=4, b=2} @wraps_kwargs(mydict) def myfunc(**k): pass
The default_kwargs object needs to satisfy the MutableMapping interface definition. When the wrapped function is called the kwargs passed in are used to update the default_kwargs object. The default_kwargs object is then passed into the wrapped function i.e. wrapped(**default_kwargs).
Parameters: default_kwargs (mutable mapping) – kwargs to be fix into the wrapped function. Return type: decorated function.
- funconf.lazy_string_cast(model_kwargs={})[source]¶
Type cast string input values if they differ from the type of the default value found in model_kwargs.
The following list details how each type is handled:
- int, bool, float:
- If the input value string can not be cast into an int, bool, or float, the exception generated during the attempted conversion will be raised.
- list:
- The input value string will be split into a list shlex.split. If the default list value in model contains items, the first item is sampled an attempt to cast the entire list is made for that type.
- other:
- An attempt to convert other types will be made. If this fails, the input value will be passed through in its original string form.
This example demonstrates how lazy_string_cast() can be applied:
@lazy_string_cast() def main(a=4, b=[4, 2, 55]): pass
Or using lazy_string_cast() with wraps_kwargs() to define new keyword defaults:
config = dict(a=6, b=[4]) @lazy_string_cast(config) @wraps_kwargs() def main(a=4, b=[4, 2, 55]): pass
Parameters: model_kwargs (mutable mapping) – kwargs to model default type values and keys from. Return type: decorated function.
- class funconf.Config(filenames=[], strict=False)[source]¶
The Config class is the root container that represents configuration state set programmatically or read in from YAML config files.
The following lists the main features of this class:
- aggregates ConfigSection objects that are accessible through attributes.
- exposes a translation of the configuration into section_option:value through a standard implementation of the MutableMapping abstract type.
- when cast to a string it outputs its state in YAML.
- as a decorator it utilises the wraps_kwargs() to change the defaults of a variable kwargs function.
- __call__(func)[source]¶
The Config object can be used as a function decorator.
Applying this decorator to a function which takes variable kwargs will change its signature to a set of kwargs with default values defined using the values in this Config object. The input kwargs go through the lazy_string_cast() function and are passed into this objects update routine. The wrapped function is finally called with the updated values of this object.
For example:
myconfig = Config('my.conf') @myconfig def func(**k): pass
Parameters: func (variable kwargs function) – function to be wrapped. Return type: wrapped function with defined kwargs bound to this Config object.
- __getattribute__(y)[source]¶
Return a section where y is the section name. Else, return the value of a reserved word.
- __init__(filenames=[], strict=False)[source]¶
Construct a new Config object.
This is the root object for a function configuration set. It is the container for the configuration sections.
Parameters: - filenames (list of filepaths) – YAML configuration files.
- strict (False) – Raise ConfigAttributeError if a ConfigSection doesn’t exist
- load(stream)[source]¶
Parse the first YAML document from stream then load the section:option:value elements into this Config object.
Parameters: stream (stream object) – the configuration to be loaded using yaml.load.
- read(filenames)[source]¶
Read and parse a filename or a list of filenames.
Files that cannot be opened are silently ignored; this is designed so that you can specify a list of potential configuration file locations (e.g. current directory, user’s home directory, system wide directory), and all existing configuration files in the list will be read. A single filename may also be given.
Parameters: filenames (list of filepaths) – YAML configuration files. Return type: list of successfully read files.
- set(section, option, value)[source]¶
Set an option.
In the event of setting an option name or section name to a reserved word a ValueError will be raised. A complete set of reserved words for both section and option can be seen by:
print(dir(funconf.Config)) print(dir(funconf.ConfigOption))
Parameters: - section (str) – Name of the section to add the option into.
- option (str) – Name of the option.
- value – Value assigned to this option.
- class funconf.ConfigSection(section, options)[source]¶
The ConfigSection class is a mutable mapping object that represents the option:value items for a configuration section.
The following lists the main features of this class:
- exposes a configuration option:value through a standard implementation of the MutableMapping abstract type.
- when cast to a string it outputs its state in YAML.
- as a decorator it utilises the wraps_kwargs() to change the defaults of a variable kwargs function.
- __call__(func)[source]¶
The ConfigSection object can be used as a function decorator.
Applying this decorator to a function which takes variable kwargs will change its signature to a set of kwargs with default values defined using the values in this ConfigSection object. The input kwargs go through the lazy_string_cast() function and are passed into this objects update routine. The wrapped function is finally called with the updated values of this object.
For example:
myconfig = Config('my.conf') @myconfig.mysection def func(**k): pass
Parameters: func (variable kwargs function) – function to be wrapped. Return type: wrapped function with defined kwargs defaults bound to this ConfigSection object.
- __getattribute__(y)[source]¶
Return a option value where y is the option name. Else, return the value of a reserved word.
- __init__(section, options)[source]¶
Construct a new ConfigSection object.
This object represents a section which contains the mappings between the section’s options and their respective values.
Parameters: - section (str) – defines the name for this section.
- options (mutable mapping) – is the mapping containing an initialised set of option:values
- __len__()[source]¶
Return the number of options defined in this ConfigSection object
- dirty[source]¶
The dirty property is a convenience property which is set when a change has occurred to one of the options under this section. Once this property is read, it is reset to False.
This property is particularly useful if you’re software system has the ability to change the configuration state during runtime. It means that you no longer need to remember the state of the options, you just need to know that when the dirty property is set, there has been a change in the configuration for this section.
Return type: boolean value of dirty.