Merge pull request #19 from salt-formulas/andrew-fix-escapes

fix escaped strings in merged referenced dictionaries
diff --git a/reclass/datatypes/parameters.py b/reclass/datatypes/parameters.py
index e7199ab..ac15925 100644
--- a/reclass/datatypes/parameters.py
+++ b/reclass/datatypes/parameters.py
@@ -40,7 +40,7 @@
     functionality and does not try to be a really mapping object.
     '''
 
-    def __init__(self, mapping, settings, uri):
+    def __init__(self, mapping, settings, uri, merge_initialise = True):
         self._settings = settings
         self._base = {}
         self._uri = uri
@@ -51,10 +51,13 @@
         self._needs_all_envs = False
         self._keep_overrides = False
         if mapping is not None:
-            # we initialise by merging
-            self._keep_overrides = True
-            self.merge(mapping)
-            self._keep_overrides = False
+            if merge_initialise:
+                # we initialise by merging
+                self._keep_overrides = True
+                self.merge(mapping)
+                self._keep_overrides = False
+            else:
+                self._base = copy.deepcopy(mapping)
 
     #delimiter = property(lambda self: self._delimiter)
 
@@ -178,7 +181,7 @@
         else:
             return self._update_value(cur, new)
 
-    def merge(self, other):
+    def merge(self, other, wrap=True):
         """Merge function (public edition).
 
         Call _merge_recurse on self with either another Parameter object or a
@@ -194,9 +197,15 @@
 
         self._unrendered = None
         if isinstance(other, dict):
-            wrapped = self._wrap_dict(other, DictPath(self._settings.delimiter))
+            if wrap:
+                wrapped = self._wrap_dict(other, DictPath(self._settings.delimiter))
+            else:
+                wrapped = copy.deepcopy(other)
         elif isinstance(other, self.__class__):
-            wrapped = self._wrap_dict(other._base, DictPath(self._settings.delimiter))
+            if wrap:
+                wrapped = self._wrap_dict(other._base, DictPath(self._settings.delimiter))
+            else:
+                wrapped = copy.deepcopy(other._base)
         else:
             raise TypeError('Cannot merge %s objects into %s' % (type(other),
                             self.__class__.__name__))
diff --git a/reclass/datatypes/tests/test_parameters.py b/reclass/datatypes/tests/test_parameters.py
index 405f757..bb9ec35 100644
--- a/reclass/datatypes/tests/test_parameters.py
+++ b/reclass/datatypes/tests/test_parameters.py
@@ -572,5 +572,23 @@
         self.assertEqual(error.exception.message, "-> \n   Cannot resolve ${beta}, at alpha")
         self.assertEqual(std_err.text(), err1)
 
+    def test_escaped_string_in_ref_dict_1(self):
+        # test with escaped string in first dict to be merged
+        p1 = Parameters({'a': { 'one': '${a_ref}' }, 'b': { 'two': '\${not_a_ref}' }, 'c': '${b}', 'a_ref': 123}, SETTINGS, '')
+        p2 = Parameters({'c': '${a}'}, SETTINGS, '')
+        r = { 'a': { 'one': 123 }, 'b': { 'two': '${not_a_ref}' }, 'c': { 'one': 123, 'two': '${not_a_ref}' }, 'a_ref': 123}
+        p1.merge(p2)
+        p1.interpolate()
+        self.assertEqual(p1.as_dict(), r)
+
+    def test_escaped_string_in_ref_dict_2(self):
+        # test with escaped string in second dict to be merged
+        p1 = Parameters({'a': { 'one': '${a_ref}' }, 'b': { 'two': '\${not_a_ref}' }, 'c': '${a}', 'a_ref': 123}, SETTINGS, '')
+        p2 = Parameters({'c': '${b}'}, SETTINGS, '')
+        r = { 'a': { 'one': 123 }, 'b': { 'two': '${not_a_ref}' }, 'c': { 'one': 123, 'two': '${not_a_ref}' }, 'a_ref': 123}
+        p1.merge(p2)
+        p1.interpolate()
+        self.assertEqual(p1.as_dict(), r)
+
 if __name__ == '__main__':
     unittest.main()
diff --git a/reclass/values/valuelist.py b/reclass/values/valuelist.py
index 6201564..46d8ec7 100644
--- a/reclass/values/valuelist.py
+++ b/reclass/values/valuelist.py
@@ -107,9 +107,9 @@
                 deepCopied = False
             else:
                 if isinstance(output, dict) and isinstance(new, dict):
-                    p1 = Parameters(output, self._settings, None)
-                    p2 = Parameters(new, self._settings, None)
-                    p1.merge(p2)
+                    p1 = Parameters(output, self._settings, None, merge_initialise = False)
+                    p2 = Parameters(new, self._settings, None, merge_initialise = False)
+                    p1.merge(p2, wrap=False)
                     output = p1.as_dict()
                     continue
                 elif isinstance(output, list) and isinstance(new, list):