Source code for mlpy.tools.configuration

"""
.. module:: mlpy.auxiliary.configuration
   :platform: Unix, Windows
   :synopsis: Manages configurations read in JSON format.

.. moduleauthor:: Astrid Jackson <ajackson@eecs.ucf.edu>
"""
from __future__ import division, print_function, absolute_import

from ..auxiliary.io import load_from_file
from ..auxiliary.misc import listify


def _decode_list(data):
    rv = []
    for item in data:
        if isinstance(item, unicode):
            item = item.encode('utf-8')
        elif isinstance(item, list):
            item = _decode_list(item)
        elif isinstance(item, dict):
            item = _decode_dict(item)
        rv.append(item)
    return rv


def _decode_dict(data):
    rv = {}
    for key, value in data.iteritems():
        if isinstance(key, unicode):
            key = key.encode('utf-8')
        if isinstance(value, unicode):
            value = value.encode('utf-8')
        elif isinstance(value, list):
            value = _decode_list(value)
        elif isinstance(value, dict):
            value = _decode_dict(value)
        rv[key] = value
    return rv


[docs]class ConfigMgr(object): """The configuration manager. The configuration manager provides access to configuration files (usually in `JSON <http://json.org/>`_ format) for client applications. Parameters ---------- filename : str The name of the configuration file. import_modules : str or list[str] Modules required by the configuration file that must be imported first. eval_key : bool Whether to evaluate the key. If this is `True`, the key will be evaluated as a statement by a call to :func:`eval()`. Raises ------ TypeError If the configuration file is not read in a dictionary Examples -------- Assuming there exists a file ``events_map.json`` containing the following configuration: :: { "keyboard": { "down": { "pygame.K_ESCAPE": "QUIT", "pygame.K_SPACE": [-1.0], "pygame.K_LEFT" : [-0.004], "pygame.K_RIGHT": [0.004] } } } The keys can be mapped to the `PyGame <http://www.pygame.org/>`_ keyboard constants, when the file is loaded by the configuration manager as follows: >>> cfg = ConfigMgr("events_map.json", "pygame", eval_key=True) This allows to retrieve the values for the keys in the configuration file by using the `PyGame <http://www.pygame.org/>`_ keyboard constants, which are returned in the `key` attribute of the `PyGame <http://www.pygame.org/>`_ event: >>> import pygame >>> for event in pygame.event.get(): >>> print cfg.get("keyboard.down." + str(event.key)) """ def __init__(self, filename, import_modules=None, eval_key=None): self._config = load_from_file(filename, import_modules) if not isinstance(self._config, dict): raise TypeError("The configuration file must be of type `dict`.") eval_key = eval_key if eval_key is not None else False if eval_key: self._eval_key(self._config, import_modules)
[docs] def get(self, key): """Return the value for the given key. Parameters ---------- key : str The key for the configuration. Concatenate keys by dots (`.`) to access keys at deeper levels in the configuration. Raises ------ KeyError If the key does not exist in the configuration """ key_list = key.split(".") config = self._config for k in key_list: if k in config: # noinspection PyTypeChecker config = config[k] else: raise KeyError(k) return config
[docs] def has_config(self, key): """Checks if the given key exists in the configuration. Parameters ---------- key : str The key for the configuration. Concatenate keys by dots (``.``) to access keys at deeper levels in the configuration. Returns ------- bool : Whether the key exists or not. """ key_list = key.split(".") config = self._config for k in key_list: if k in config: # noinspection PyTypeChecker config = config[k] else: return False return True
def _eval_key(self, d, import_modules): """Evaluate the key by calling eval(). Parameters ---------- d : dict The configuration dictionary. import_modules : str or list[str] The modules that must be imported first. """ def items(): import importlib for m in listify(import_modules): vars()[m] = importlib.import_module(m) for key, value in d.items(): try: d[eval("str(" + key + ")")] = d.pop(key) except NameError: d[key] = value if isinstance(value, dict): self._eval_key(value, import_modules) items()