def push(self, nodes): ''' Push nodes into dependency map. If node already exists, update its dependency. Only nodes mentioned in the parameter will be updated. For a global dependency re-calculation, please use "refresh". @param nodes: Node collection, must be iterable. ''' # create nodes target_jar = {} for n in nodes: targets = self.fp(n) if (targets is None): if n in self.nodes: self.remove(n) continue target_jar[n] = targets self.nodes[n] = MapNode(n) # setup references for n in builtin.iterkeys(target_jar): # check target set targets = target_jar[n] targets_set = set([t for t in targets if t in self.nodes]) # remove not alive old references old_targets_set = set(self.nodes[n].targets) for n2 in (old_targets_set - targets_set): self.nodes[n2].parents.remove(n) self.nodes[n].targets.remove(n2) # add new references for n2 in (targets_set - old_targets_set): self.nodes[n2].parents.append(n) self.nodes[n].targets.append(n2)
def walk(self, proc, nodes=None): ''' Walk on the dependency map and process each node. Nodes are iterated according to dependency relations. Simple recursive implementation for the time being, but may be use better methods later. Exceptions must be well handled in proc! @param proc: A function object to process each node. @param nodes: Start walk from initial nodes. Must be a collection. If None, then all nodes will be selected. ''' memo = {} def loop(node, memo): for n in self.nodes[node].targets: if (n not in memo): memo[n] = True loop(n, memo) proc(n) if (nodes is None): nodes = builtin.iterkeys(self.nodes) else: nodes = [n for n in nodes if n in self.nodes] for n in nodes: if (n not in memo): memo[n] = True loop(n, memo) proc(n)
def refresh(self): ''' Re-calculate dependency relations of all nodes pushed. ''' self.push(builtin.iterkeys(self.nodes))