From e9d63bb6844471d77bd5fb0e69e81410f3fba0e8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jo=C3=A3o=20Magalh=C3=A3es?= Date: Fri, 15 Jan 2021 13:07:50 +0000 Subject: [PATCH] fix: merge_dict issue with override = False and recursive = True The replacement of the values was not being correctly performed --- src/appier/test/util.py | 13 +++++++++++++ src/appier/util.py | 25 +++++++++++++++++++++++++ 2 files changed, 38 insertions(+) diff --git a/src/appier/test/util.py b/src/appier/test/util.py index 7db3d52e..e43bd931 100644 --- a/src/appier/test/util.py +++ b/src/appier/test/util.py @@ -995,6 +995,19 @@ def test_dict_merge(self): ) )) + result = appier.dict_merge(first, second, override = False, recursive = True) + self.assertEqual(id(result) in (id(first), (id(second))), False) + self.assertEqual(result["a"], dict( + a = "hello", + b = "world", + c = "other", + d = "other", + m = dict( + a = "hello", + b = "world" + ) + )) + def test_verify(self): result = appier.verify(1 == 1) self.assertEqual(result, None) diff --git a/src/appier/util.py b/src/appier/util.py index c38043f9..3d76353b 100644 --- a/src/appier/util.py +++ b/src/appier/util.py @@ -1740,6 +1740,30 @@ def to_tokens_m(tokens): return tokens_m def dict_merge(first, second, override = True, recursive = False): + """ + Merges two dictionaries, optionally using a deep (recursive) + strategy to achieve the merge. + + The default "way" of the merge is from the second to the first + and overriding the values of the first dictionary. + + :type first: Dictionary + :param first: The target dictionary of the merge operation and + that will have its contents overriden if requested. + :type second: Dictionary + :param second: The base dictionary of the merge that will be + "copied" into the first one. + :type override: bool + :param override: If the contents of the first dictionary should + be overriden (overwritten) in case of "collision". + :type recursive: bool + :param recursive: If the merge operation should be performed using + a deep and recursive approach for dictionary types. + :rtype: Dictionary + :return: The resulting dictionary (new instance) from the merge + operation of the second dictionary into the first. + """ + # in case no override exists then the order of the items is # exchanged so that the first overrides the second values # and not the exact opposite @@ -1769,6 +1793,7 @@ def dict_merge(first, second, override = True, recursive = False): # it's of any other type (no smart merge possible) other = second[key] if isinstance(value, dict) and isinstance(other, dict): + if not override: value, other = other, value final[key] = dict_merge( value, other,