diff --git a/netjsonconfig/utils.py b/netjsonconfig/utils.py index 430eff645..987703d56 100644 --- a/netjsonconfig/utils.py +++ b/netjsonconfig/utils.py @@ -1,6 +1,9 @@ +import re from collections import OrderedDict from copy import deepcopy +import six + def merge_config(template, config): """ @@ -34,6 +37,32 @@ 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 diff --git a/tests/test_utils.py b/tests/test_utils.py index b57caec63..d0183f229 100644 --- a/tests/test_utils.py +++ b/tests/test_utils.py @@ -1,6 +1,6 @@ import unittest -from netjsonconfig.utils import merge_config +from netjsonconfig.utils import evaluate_vars, merge_config class TestUtils(unittest.TestCase): @@ -109,3 +109,27 @@ def test_merge_list_of_dicts_unchanged(self): {"c": "original"} ] }) + + def test_evaluate_vars(self): + self.assertEqual(evaluate_vars('{{ tz }}', {'tz': 'UTC'}), 'UTC') + self.assertEqual(evaluate_vars('tz: {{ tz }}', {'tz': 'UTC'}), 'tz: UTC') + + def test_evaluate_vars_missing(self): + self.assertEqual(evaluate_vars('{{ tz }}'), '{{ tz }}') + self.assertEqual(evaluate_vars('tz: {{ tz }}'), 'tz: {{ tz }}') + + def test_evaluate_vars_dict(self): + val = evaluate_vars({'timezone': '{{ tz }}'}, {'tz': 'UTC'}) + self.assertEqual(val, {'timezone': 'UTC'}) + + def test_evaluate_vars_nested_dict(self): + val = evaluate_vars({'general': {'timezone': '{{ tz }}'}}, {'tz': 'UTC'}) + self.assertEqual(val, {'general': {'timezone': 'UTC'}}) + + def test_evaluate_vars_list(self): + val = evaluate_vars(['{{ a }}', '{{ b }}'], {'a': '1', 'b': '2'}) + self.assertEqual(val, ['1', '2']) + + def test_evaluate_vars_list_in_dict(self): + val = evaluate_vars({'l': ['{{ a }}', '{{ b }}']}, {'a': '1', 'b': '2'}) + self.assertEqual(val, {'l': ['1', '2']})