"""Utils to configure Bigchain. By calling `file_config`, the global configuration (stored in `bigchain.config`) will be updated with the values contained in the configuration file. Note that there is a precedence in reading configuration values: - [not yet] command line; - local config file; - environment vars; - default config file (contained in `bigchain.__init__`). """ import os import copy import json import logging import collections import bigchaindb logger = logging.getLogger(__name__) CONFIG_DEFAULT_PATH = os.environ.setdefault( 'BIGCHAINDB_CONFIG_PATH', os.path.join(os.path.expanduser('~'), '.bigchaindb'), ) # Thanks Alex <3 # http://stackoverflow.com/a/3233356/597097 def update(d, u): """Recursively update a mapping.""" for k, v in u.items(): if isinstance(v, collections.Mapping): r = update(d.get(k, {}), v) d[k] = r else: d[k] = u[k] return d def file_config(filename=None): """Read a configuration file and merge it with the default configuration. Args: filename (str): the JSON file with the configuration. Defaults to ``None``. If ``None``, the HOME of the current user and the string ``.bigchaindb`` will be used. Note: The function merges the values in ``filename`` with the **default configuration**, so any update made to ``bigchaindb.config`` will be lost. """ if not filename: filename = CONFIG_DEFAULT_PATH with open(filename) as f: newconfig = json.load(f) dict_config(newconfig) logger.info('Configuration loaded from `{}`'.format(filename)) def dict_config(newconfig): """Merge the provided configuration with the default one. Args: newconfig (dict): a dictionary with the configuration to load. Note: The function merges ``newconfig`` with the **default configuration**, so any update made to ``bigchaindb.config`` will be lost. """ bigchaindb.config = copy.deepcopy(bigchaindb._config) update(bigchaindb.config, newconfig) bigchaindb.config['CONFIGURED'] = True def write_config(newconfig, filename=None): """Write the provided configuration to a specific location. Args: newconfig (dict): a dictionary with the configuration to load. filename (str): the name of the file that will store the new configuration. Defaults to ``None``. If ``None``, the HOME of the current user and the string ``.bigchaindb`` will be used. """ if not filename: filename = CONFIG_DEFAULT_PATH with open(filename, 'w') as f: json.dump(newconfig, f) def autoconfigure(): """Run ``file_config`` if the module has not been initialized. """ if bigchaindb.config.get('CONFIGURED'): return try: file_config() except FileNotFoundError: logger.warning('Cannot find your config file. Run `bigchaindb configure` to create one')