From 696adcf1d92cfa188c51ef76a9f1ad85d95a1c8d Mon Sep 17 00:00:00 2001 From: Sergey Kraynev Date: Tue, 14 Feb 2017 14:13:06 +0000 Subject: [PATCH] Add ability for recursive merge dicts for AttrDict This patch adds ability to merge nested dicts if they are passed as a paramater for "_merge" method of AttrDict class. Also corresponding tests are added. Change-Id: I7d18f69d4dc076c178552ae886af6df2932abc27 --- fuel_ccp/config/_yaml.py | 4 ++- fuel_ccp/tests/test_config.py | 55 +++++++++++++++++++++++++++++++++++ 2 files changed, 58 insertions(+), 1 deletion(-) diff --git a/fuel_ccp/config/_yaml.py b/fuel_ccp/config/_yaml.py index a1879104..b7eff311 100644 --- a/fuel_ccp/config/_yaml.py +++ b/fuel_ccp/config/_yaml.py @@ -65,7 +65,9 @@ class AttrDict(object): value._merge(other_value) else: if isinstance(other_value, dict): - other_value = AttrDict(other_value) + val = AttrDict() + val._merge(other_value) + other_value = val self._dict[key] = other_value def _json(self, **kwargs): diff --git a/fuel_ccp/tests/test_config.py b/fuel_ccp/tests/test_config.py index dfdf23a4..68ac5d16 100644 --- a/fuel_ccp/tests/test_config.py +++ b/fuel_ccp/tests/test_config.py @@ -1,5 +1,6 @@ import io import jsonschema +import testscenarios from fuel_ccp import config from fuel_ccp.config import _yaml @@ -26,3 +27,57 @@ class TestConfigSchema(base.TestCase): _yaml.dump(conf, stream) new_conf = _yaml.load(stream.getvalue()) config.validate_config(new_conf) + + +class TestAttrDict(testscenarios.WithScenarios, base.TestCase): + scenarios = ( + ('empty_dict', + {'init_dict': {}, + 'value': {}, + 'res': _yaml.AttrDict()}), + ('one_value_dict', + {'init_dict': {}, + 'value': {'foo': True}, + 'res': _yaml.AttrDict({'foo': True})}), + ('nested_dict', + {'init_dict': {}, + 'value': {'bar': {'foo': True}}, + 'res': _yaml.AttrDict({'bar': _yaml.AttrDict({'foo': True})})}), + ('nested_nested_dict', + {'init_dict': {}, + 'value': {'baz': {'bar': {'foo': True}}}, + 'res': _yaml.AttrDict({'baz': _yaml.AttrDict({'bar': + _yaml.AttrDict({'foo': True})})})}), + ('merge_class', + {'init_dict': {}, + 'value': _yaml.AttrDict({'foo': 'bar'}), + 'res': _yaml.AttrDict({'foo': 'bar'})}), + ('merge_class_same_val', + {'init_dict': {'foo': True}, + 'value': _yaml.AttrDict({'foo': 'bar'}), + 'res': _yaml.AttrDict({'foo': 'bar'})}), + ('merge_dict_same_val', + {'init_dict': {'foo': True}, + 'value': {'foo': 'bar'}, + 'res': _yaml.AttrDict({'foo': 'bar'})}), + ('merge_nested_multi', + {'init_dict': {}, + 'value': {'baz': {'bar': {'foo': True}}, 'boom': {'cat': 'no'}, + 'end': 'yes'}, + 'res': _yaml.AttrDict({'baz': {'bar': {'foo': True}}, + 'boom': {'cat': 'no'}, 'end': 'yes'})}), + ('merge_dict_diff_val', + {'init_dict': {'baz': True}, + 'value': {'foo': 'bar'}, + 'res': _yaml.AttrDict({'baz': True, 'foo': 'bar'})}), + ('merge_dict_mixed_val', + {'init_dict': {'baz': True, 'foo': False}, + 'value': {'foo': 'bar', 'cat': 'dog'}, + 'res': _yaml.AttrDict({'baz': True, 'cat': 'dog', + 'foo': 'bar'})}), + ) + + def test_merge(self): + cls = _yaml.AttrDict(self.init_dict) + cls._merge(self.value) + self.assertEqual(self.res, cls)