Source code for netjsonconfig.utils

import re
from collections import OrderedDict
from copy import deepcopy

import six


[docs]def merge_config(template, config): """ Merges ``config`` on top of ``template``. Conflicting keys are handled in the following way: * simple values (eg: ``str``, ``int``, ``float``, ecc) in ``config`` will overwrite the ones in ``template`` * values of type ``list`` in both ``config`` and ``template`` will be summed in order to create a list which contains elements of both * values of type ``dict`` will be merged recursively :param template: template ``dict`` :param config: config ``dict`` :returns: merged ``dict`` """ result = template.copy() for key, value in config.items(): if isinstance(value, dict): node = result.get(key, {}) result[key] = merge_config(node, value) elif isinstance(value, list) and isinstance(result.get(key), list): result[key] = deepcopy(result[key]) + deepcopy(value) else: result[key] = value return result
def sorted_dict(dictionary): return OrderedDict(sorted(dictionary.items())) var_pattern = re.compile(r'\{\{\s(\w*)\s\}\}') def evaluate_vars(data, context={}): """ Evaluates variables in ``data`` :param data: data structure containing variables, may be ``str``, ``dict`` or ``list`` :param context: ``dict`` containing variables :returns: modified data structure """ if isinstance(data, (dict, list)): if isinstance(data, dict): loop_items = data.items() elif isinstance(data, list): loop_items = enumerate(data) for key, value in loop_items: data[key] = evaluate_vars(value, context) elif isinstance(data, six.string_types): for var in var_pattern.findall(data): if var in context: data = data.replace('{{ %s }}' % var, context[var]) return data class _TabsMixin(object): # pragma: nocover """ mixin that adds _tabs method to test classes """ def _tabs(self, string): """ replace 4 spaces with 1 tab """ return string.replace(' ', '\t')