Implement a better fix for escaped strings in referenced dictionaries
When merging reference dictionaries with escaped strings, these strings
would be double processed. The original fix simply did not wrap strings
in Value objects when creating the parameter objects during the merge
step for dictionaries in the ValueList.render method.
This change replaces that fix, which did not work in all cases, by
not parsing string during the creation of parameter objects in
ValueList.render, instead strings are simply wraped as ScalarItems.
This is valid as any strings will have already been wraped once and
rendered so can not be references.
diff --git a/reclass/datatypes/parameters.py b/reclass/datatypes/parameters.py
index cbee11f..6ad0d27 100644
--- a/reclass/datatypes/parameters.py
+++ b/reclass/datatypes/parameters.py
@@ -44,7 +44,7 @@
functionality and does not try to be a really mapping object.
'''
- def __init__(self, mapping, settings, uri, merge_initialise = True):
+ def __init__(self, mapping, settings, uri, parse_strings=True):
self._settings = settings
self._base = {}
self._uri = uri
@@ -54,14 +54,12 @@
self._resolve_errors = ResolveErrorList()
self._needs_all_envs = False
self._keep_overrides = False
+ self._parse_strings = parse_strings
if mapping is not None:
- if merge_initialise:
- # we initialise by merging
- self._keep_overrides = True
- self.merge(mapping)
- self._keep_overrides = False
- else:
- self._base = copy.deepcopy(mapping)
+ # we initialise by merging
+ self._keep_overrides = True
+ self.merge(mapping)
+ self._keep_overrides = False
#delimiter = property(lambda self: self._delimiter)
@@ -103,7 +101,7 @@
return value
else:
try:
- return Value(value, self._settings, self._uri)
+ return Value(value, self._settings, self._uri, parse_string=self._parse_strings)
except InterpolationError as e:
e.context = str(path)
raise
@@ -127,7 +125,7 @@
elif isinstance(new, ValueList):
values.extend(new)
else:
- values.append(Value(new, self._settings, self._uri))
+ values.append(Value(new, self._settings, self._uri, parse_string=self._parse_strings))
return values
@@ -154,7 +152,7 @@
for (key, newvalue) in iteritems(new):
if key.startswith(self._settings.dict_key_override_prefix) and not self._keep_overrides:
if not isinstance(newvalue, Value):
- newvalue = Value(newvalue, self._settings, self._uri)
+ newvalue = Value(newvalue, self._settings, self._uri, parse_string=self._parse_strings)
newvalue.overwrite = True
ret[key.lstrip(self._settings.dict_key_override_prefix)] = newvalue
else:
@@ -187,7 +185,7 @@
else:
return self._update_value(cur, new)
- def merge(self, other, wrap=True):
+ def merge(self, other):
"""Merge function (public edition).
Call _merge_recurse on self with either another Parameter object or a
@@ -203,15 +201,9 @@
self._unrendered = None
if isinstance(other, dict):
- if wrap:
- wrapped = self._wrap_dict(other, DictPath(self._settings.delimiter))
- else:
- wrapped = copy.deepcopy(other)
+ wrapped = self._wrap_dict(other, DictPath(self._settings.delimiter))
elif isinstance(other, self.__class__):
- if wrap:
- wrapped = self._wrap_dict(other._base, DictPath(self._settings.delimiter))
- else:
- wrapped = copy.deepcopy(other._base)
+ wrapped = self._wrap_dict(other._base, DictPath(self._settings.delimiter))
else:
raise TypeError('Cannot merge %s objects into %s' % (type(other),
self.__class__.__name__))
diff --git a/reclass/values/value.py b/reclass/values/value.py
index 7a855ad..1a5b450 100644
--- a/reclass/values/value.py
+++ b/reclass/values/value.py
@@ -14,16 +14,19 @@
_parser = Parser()
- def __init__(self, value, settings, uri):
+ def __init__(self, value, settings, uri, parse_string=True):
self._settings = settings
self._uri = uri
self._overwrite = False
if isinstance(value, str):
- try:
- self._item = self._parser.parse(value, self._settings)
- except InterpolationError as e:
- e.uri = self._uri
- raise
+ if parse_string:
+ try:
+ self._item = self._parser.parse(value, self._settings)
+ except InterpolationError as e:
+ e.uri = self._uri
+ raise
+ else:
+ self._item = ScaItem(value, self._settings)
elif isinstance(value, list):
self._item = ListItem(value, self._settings)
elif isinstance(value, dict):
diff --git a/reclass/values/valuelist.py b/reclass/values/valuelist.py
index 460dff0..bdfa01a 100644
--- a/reclass/values/valuelist.py
+++ b/reclass/values/valuelist.py
@@ -109,9 +109,9 @@
deepCopied = False
else:
if isinstance(output, dict) and isinstance(new, dict):
- p1 = Parameters(output, self._settings, None, merge_initialise = False)
- p2 = Parameters(new, self._settings, None, merge_initialise = False)
- p1.merge(p2, wrap=False)
+ p1 = Parameters(output, self._settings, None, parse_strings=False)
+ p2 = Parameters(new, self._settings, None, parse_strings=False)
+ p1.merge(p2)
output = p1.as_dict()
continue
elif isinstance(output, list) and isinstance(new, list):