"""
..
Copyright (c) 2014-2017, Magni developers.
All rights reserved.
See LICENSE.rst for further information.
Module providing a robust configger class.
Routine listings
----------------
Configger(object)
Provide functionality to access a set of configuration options.
Notes
-----
This module does not itself contain any configuration options and thus has no
access to any configuration options unlike the other config modules of `magni`.
"""
from __future__ import division
from itertools import chain
from magni.utils.validation import decorate_validation as _decorate_validation
from magni.utils.validation import validate_generic as _generic
from magni.utils.validation import validate_levels as _levels
from magni.utils.validation import validate_numeric as _numeric
[docs]class Configger(object):
"""
Provide functionality to access a set of configuration options.
The set of configuration options, their default values, and their
validation schemes are specified upon initialisation.
Parameters
----------
params : dict
The configuration options and their default values.
valids : dict
The validation schemes of the configuration options.
See Also
--------
magni.utils.validation : Validation.
Notes
-----
`valids` must contain the same keys as `params`. For each key in 'valids',
the first value is the validation function ('generic', 'levels', or
'numeric'), whereas the remaining values are passed to that validation
function.
Examples
--------
Instantiate Configger with the parameter 'key' with default value 'default'
which can only assume string values.
>>> import magni
>>> from magni.utils.config import Configger
>>> valid = magni.utils.validation.validate_generic(None, 'string')
>>> config = Configger({'key': 'default'}, {'key': valid})
The number of parameters can be retrieved as the length:
>>> len(config)
1
That parameter can be retrieved in a number of ways:
>>> config['key']
'default'
>>> for key, value in config.items():
... print('key: {!r}, value: {!r}'.format(key, value))
key: 'key', value: 'default'
>>> for key in config.keys():
... print('key: {!r}'.format(key))
key: 'key'
>>> for value in config.values():
... print('value: {!r}'.format(value))
value: 'default'
Likewise, the parameter can be changed in a number of ways:
>>> config['key'] = 'value'
>>> config['key']
'value'
>>> config.update({'key': 'value changed by dict'})
>>> config['key']
'value changed by dict'
>>> config.update(key='value changed by keyword')
>>> config['key']
'value changed by keyword'
Finally, the parameter can be reset to the default value at any point:
>>> config.reset()
>>> config['key']
'default'
"""
_funcs = {'generic': _generic, 'levels': _levels, 'numeric': _numeric}
def __init__(self, params, valids):
@_decorate_validation
def validate_input():
_generic('params', 'mapping')
_levels('valids', (
_generic(None, 'mapping', has_keys=tuple(params.keys())),
_generic(None, 'explicit collection')))
for key in valids.keys():
_generic(('valids', key, 0), 'string',
value_in=tuple(self._funcs.keys()))
validate_input()
self._default = params.copy()
self._params = params
self._valids = valids
[docs] def __getitem__(self, name):
"""
Get the value of a configuration parameter.
Parameters
----------
name : str
The name of the parameter.
Returns
-------
value : None
The value of the parameter.
"""
@_decorate_validation
def validate_input():
_generic('name', 'string', value_in=tuple(self._params.keys()))
validate_input()
return self._params[name]
[docs] def __len__(self):
"""
Get the number of configuration parameters.
Returns
-------
length : int
The number of parameters.
"""
return len(self._params)
[docs] def __setitem__(self, name, value):
"""
Set the value of a configuration parameter.
The value is validated according to the validation scheme of that
parameter.
Parameters
----------
name : str
The name of the parameter.
value : None
The new value of the parameter.
"""
@_decorate_validation
def validate_input():
_generic('name', 'string', value_in=tuple(self._params.keys()))
validation = self._valids[name]
self._funcs[validation[0]]('value', *validation[1:])
validate_input()
self._params[name] = value
[docs] def get(self, key=None):
"""
Deprecated method.
See Also
--------
Configger.__getitem__ : Replacing method.
Configger.items : Replacing method.
Configger.keys : Replacing method.
Configger.values : Replacing method.
"""
raise DeprecationWarning("'get' will be removed in version 1.3.0 - "
"use 'var[name]', 'items', 'keys', or "
"'values' instead.")
if key is None:
return dict(self.items())
else:
return self[key]
[docs] def items(self):
"""
Get the configuration parameters as key, value pairs.
Returns
-------
items : set-like
The list of parameters.
"""
for key in self.keys():
yield (key, self[key])
[docs] def keys(self):
"""
Get the configuration parameter keys.
Returns
-------
keys : set-like
The keys.
"""
return self._params.keys()
[docs] def reset(self):
"""
Reset the parameter values to the default values.
"""
self._params = self._default.copy()
[docs] def set(self, dictionary={}, **kwargs):
"""
Deprecated method.
See Also
--------
Configger.__setitem__ : Replacing function.
"""
raise DeprecationWarning("'set' will be removed in version 1.3.0 - "
"use 'var[name] = value' or 'update' "
"instead.")
self.update(dictionary, **kwargs)
[docs] def update(self, params={}, **kwargs):
"""
Update the value of one or more configuration parameters.
Each value is validated according to the validation scheme of that
parameter.
Parameters
----------
params : dict, optional
A dictionary containing the key and values to update. (the default
value is an empty dictionary)
kwargs : dict
Keyword arguments being the key and values to update.
"""
@_decorate_validation
def validate_input():
_generic('params', 'mapping', keys_in=tuple(self._params.keys()))
for name, var in (('params', params), ('kwargs', kwargs)):
for key in var.keys():
validation = self._valids[key]
self._funcs[validation[0]]((name, key), *validation[1:])
validate_input()
if params is not None:
for key, value in params.items():
self[key] = value
if len(kwargs) > 0:
for key, value in kwargs.items():
self[key] = value
[docs] def values(self):
"""
Get the configuration parameter values.
Returns
-------
values : set-like
The values.
"""
for key in self.keys():
yield self[key]