clean up handling of references to lists and dicts
diff --git a/reclass/datatypes/parameters.py b/reclass/datatypes/parameters.py
index 4b93b31..ece5b1c 100644
--- a/reclass/datatypes/parameters.py
+++ b/reclass/datatypes/parameters.py
@@ -263,6 +263,12 @@
self._interpolate_inner(path, path.get_value(self._base), options)
def _interpolate_inner(self, path, value, options):
+ if not isinstance(value, (Value, ValueList)):
+ # references to lists and dicts are only deepcopied when merged
+ # together so it's possible a value with references in a referenced
+ # list or dict has already been visited by _interpolate_inner
+ del self._unrendered[path]
+ return
self._unrendered[path] = False # mark as seen
for ref in value.get_references():
path_from_ref = DictPath(self.delimiter, ref)
@@ -285,12 +291,9 @@
new = value.render(self._base, options)
if isinstance(new, dict):
self._render_simple_dict(new, path, options)
- path.set_value(self._base, copy.deepcopy(new))
elif isinstance(new, list):
self._render_simple_list(new, path, options)
- path.set_value(self._base, copy.deepcopy(new))
- else:
- path.set_value(self._base, new)
+ path.set_value(self._base, new)
# remove the reference from the unrendered list
del self._unrendered[path]
diff --git a/reclass/datatypes/tests/test_parameters.py b/reclass/datatypes/tests/test_parameters.py
index 3e2bd86..77c45e3 100644
--- a/reclass/datatypes/tests/test_parameters.py
+++ b/reclass/datatypes/tests/test_parameters.py
@@ -339,5 +339,6 @@
p1.merge(p2)
p1.interpolate()
self.assertEqual(p1.as_dict(), r)
+
if __name__ == '__main__':
unittest.main()
diff --git a/reclass/utils/dictitem.py b/reclass/utils/dictitem.py
index 8185d23..fca9982 100644
--- a/reclass/utils/dictitem.py
+++ b/reclass/utils/dictitem.py
@@ -6,8 +6,8 @@
class DictItem(object):
- def __init__(self, items):
- self._items = items
+ def __init__(self, item):
+ self._dict = item
self._refs = []
self._allRefs = False
self.assembleRefs()
@@ -15,7 +15,7 @@
def assembleRefs(self, context={}):
self._refs = []
self._allRefs = True
- self._assembleRefs_recurse_dict(self._items)
+ self._assembleRefs_recurse_dict(self._dict)
def _assembleRefs_recurse_dict(self, items):
for key, item in items.iteritems():
@@ -29,7 +29,7 @@
self._allRefs = False
def contents(self):
- return self._items
+ return self._dict
def allRefs(self):
return self._allRefs
@@ -51,10 +51,7 @@
raise TypeError('Cannot merge %s over %s' % (repr(self), repr(item)))
def render(self, context):
- value = {}
- for key, item in self._items.iteritems():
- value[key] = item
- return value
+ return self._dict
def __repr__(self):
- return 'DictItem(%r)' % self._items
+ return 'DictItem(%r)' % self._dict
diff --git a/reclass/utils/listitem.py b/reclass/utils/listitem.py
index f79212e..291d16a 100644
--- a/reclass/utils/listitem.py
+++ b/reclass/utils/listitem.py
@@ -8,8 +8,8 @@
class ListItem(object):
- def __init__(self, items):
- self._items = items
+ def __init__(self, item):
+ self._list = item
self._refs = []
self._allRefs = False
self.assembleRefs()
@@ -17,7 +17,7 @@
def assembleRefs(self, context={}):
self._refs = []
self._allRefs = True
- for item in self._items:
+ for item in self._list:
if item.has_references():
for ref in item.get_references():
self._refs.append(ref)
@@ -25,7 +25,7 @@
self._allRefs = False
def contents(self):
- return self._items
+ return self._list
def allRefs(self):
return self._allRefs
@@ -37,23 +37,20 @@
return self._refs
def render(self, context):
- value = []
- for item in self._items:
- value.append(item)
- return value
+ return self._list
def merge_over(self, item, options):
if isinstance(item, ListItem):
- for i in self._items:
- item._items.append(i)
+ for i in self._list:
+ item._list.append(i)
return item
elif isinstance(item, scaitem.ScaItem):
if options.allow_list_over_scalar:
- self._items.insert(0, item.contents())
+ self._list.insert(0, item.contents())
return self
else:
raise TypeError('allow list over scalar = False: cannot merge %s onto %s' % (repr(self), repr(item)))
raise TypeError('Cannot merge %s over %s' % (repr(self), repr(item)))
def __repr__(self):
- return 'ListItem(%r)' % (self._items)
+ return 'ListItem(%r)' % (self._list)