Esempio n. 1
0
    def _interpolate_references(self, path, value, inventory):
        all_refs = False
        while not all_refs:
            for ref in value.get_references():
                path_from_ref = DictPath(self._delimiter, ref)

                if path_from_ref in self._unrendered:
                    if self._unrendered[path_from_ref] is False:
                        # every call to _interpolate_inner replaces the value of
                        # self._unrendered[path] with False
                        # Therefore, if we encounter False instead of True,
                        # it means that we have already processed it and are now
                        # faced with a cyclical reference.
                        raise InfiniteRecursionError(path, ref)
                    else:
                        self._interpolate_inner(path_from_ref, inventory)
                else:
                    # ensure ancestor keys are already dereferenced
                    ancestor = DictPath(self._delimiter)
                    for k in path_from_ref.key_parts():
                        ancestor = ancestor.new_subpath(k)
                        if ancestor in self._unrendered:
                            self._interpolate_inner(ancestor, inventory)
            if value.allRefs():
                all_refs = True
            else:
                # not all references in the value could be calculated previously so
                # try recalculating references with current context and recursively
                # call _interpolate_inner if the number of references has increased
                # Otherwise raise an error
                old = len(value.get_references())
                value.assembleRefs(self._base)
                if old == len(value.get_references()):
                    raise InterpolationError('Bad reference count, path:' +
                                             repr(path))
Esempio n. 2
0
    def _interpolate_inner(self, path, refvalue):
        self._occurrences[path] = True  # mark as seen
        for ref in refvalue.get_references():
            path_from_ref = DictPath(self.delimiter, ref)
            try:
                refvalue_inner = self._occurrences[path_from_ref]

                # If there is no reference, then this will throw a KeyError,
                # look further down where this is caught and execution passed
                # to the next iteration of the loop
                #
                # If we get here, then the ref references another parameter,
                # requiring us to recurse, dereferencing first those refs that
                # are most used and are thus at the leaves of the dependency
                # tree.

                if refvalue_inner is True:
                    # every call to _interpolate_inner replaces the value of
                    # the saved occurrences of a reference with True.
                    # Therefore, if we encounter True instead of a refvalue,
                    # it means that we have already processed it and are now
                    # faced with a cyclical reference.
                    raise InfiniteRecursionError(path, ref)
                self._interpolate_inner(path_from_ref, refvalue_inner)

            except KeyError as e:
                # not actually an error, but we are done resolving all
                # dependencies of the current ref, so move on
                continue

        try:
            new = refvalue.render(self._base)
            path.set_value(self._base, new)

            # finally, remove the reference from the occurrences cache
            del self._occurrences[path]
        except UndefinedVariableError as e:
            raise UndefinedVariableError(e.var, path)