account for ancester and non existant paths
diff --git a/reclass/datatypes/exports.py b/reclass/datatypes/exports.py
index ae5b30b..91bc149 100644
--- a/reclass/datatypes/exports.py
+++ b/reclass/datatypes/exports.py
@@ -31,42 +31,44 @@
while len(self._unrendered) > 0:
path, v = self._unrendered.iteritems().next()
value = path.get_value(self._base)
- 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 rendered
- del self._unrendered[path]
- else:
+ if isinstance(value, (Value, ValueList)):
external._interpolate_references(path, value, None)
new = self._interpolate_render_from_external(external._base, path, value)
path.set_value(self._base, new)
del self._unrendered[path]
+ else:
+ # 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 rendered
+ del self._unrendered[path]
def interpolate_single_from_external(self, external, query):
paths = {}
for r in query.get_inv_references():
paths[r] = True
+
+ rendered = {}
while len(paths) > 0:
path, v = paths.iteritems().next()
- if path.exists_in(self._base) and path in self._unrendered:
- value = path.get_value(self._base)
- if not isinstance(value, (Value, ValueList)):
- del paths[path]
- del self._unrendered[path]
- else:
+ rendpath = path.deepest_match_in(self._base)
+ if rendpath in rendered:
+ del paths[path]
+ continue
+ if rendpath.exists_in(self._base) and rendpath in self._unrendered:
+ value = rendpath.get_value(self._base)
+ if isinstance(value, (Value, ValueList)):
try:
- external._interpolate_references(path, value, None)
- new = self._interpolate_render_from_external(external._base, path, value)
- path.set_value(self._base, new)
+ external._interpolate_references(rendpath, value, None)
+ new = self._interpolate_render_from_external(external._base, rendpath, value)
+ rendpath.set_value(self._base, new)
except ResolveError as e:
if query.ignore_failed_render():
- path.delete(self._base)
+ rendpath.delete(self._base)
else:
raise
- del paths[path]
- del self._unrendered[path]
- else:
- del paths[path]
+ rendered[rendpath] = True
+ paths.pop(rendpath, None)
+ self._unrendered.pop(rendpath, None)
def _interpolate_render_from_external(self, context, path, value):
try:
diff --git a/reclass/utils/dictpath.py b/reclass/utils/dictpath.py
index 1466a5e..eae57a1 100644
--- a/reclass/utils/dictpath.py
+++ b/reclass/utils/dictpath.py
@@ -117,7 +117,7 @@
def key_parts(self):
if self.has_ancestors():
- return self._parts[::len(self._parts)-1]
+ return self._parts[:-1]
else:
return []
@@ -134,6 +134,9 @@
del self._parts[0]
return self
+ def is_empty(self):
+ return len(self._parts) == 0
+
def delete(self, base):
del self._get_innermost_container(base)[self._get_key()]
@@ -154,3 +157,22 @@
else:
return False
return True
+
+ def deepest_match_in(self, container):
+ match = DictPath(self._delim)
+ item = container
+ for i in self._parts:
+ if isinstance(item, (dict, list)):
+ if i in item:
+ if isinstance(item, dict):
+ item = item[i]
+ elif isinstance(container, list):
+ item = item[int(i)]
+ match = match.new_subpath(i)
+ else:
+ return match
+ else:
+ if item == self._parts[-1]:
+ match = match.new_subpath(i)
+ return match
+ return match