def read_graph_from_string(txt): """Read a graph from a string, either in dot format, or our own compressed format. Returns: `pygraph.digraph`: Graph object. """ if not txt.startswith('{'): return read_dot(txt) # standard dot format def conv(value): if isinstance(value, basestring): return '"' + value + '"' else: return value # our compacted format doc = literal_eval(txt) g = digraph() for attrs, values in doc.get("nodes", []): attrs = [(k, conv(v)) for k, v in attrs] for value in values: if isinstance(value, basestring): node_name = value attrs_ = attrs else: node_name, label = value attrs_ = attrs + [("label", conv(label))] g.add_node(node_name, attrs=attrs_) for attrs, values in doc.get("edges", []): attrs_ = [(k, conv(v)) for k, v in attrs] for value in values: if len(value) == 3: edge = value[:2] label = value[-1] else: edge = value label = '' g.add_edge(edge, label=label, attrs=attrs_) return g
def prune_graph(graph_str, package_name): """Prune a package graph so it only contains nodes accessible from the given package. Args: graph_str (str): Dot-language graph string. package_name (str): Name of package of interest. Returns: Pruned graph, as a string. """ # find nodes of interest g = read_dot(graph_str) nodes = set() for node, attrs in g.node_attr.iteritems(): attr = [x for x in attrs if x[0] == "label"] if attr: label = attr[0][1] try: req_str = _request_from_label(label) request = PackageRequest(req_str) except PackageRequestError: continue if request.name == package_name: nodes.add(node) if not nodes: raise ValueError("The package %r does not appear in the graph." % package_name) # find nodes upstream from these nodes g_rev = g.reverse() accessible_nodes = set() access = accessibility(g_rev) for node in nodes: nodes_ = access.get(node, []) accessible_nodes |= set(nodes_) # remove inaccessible nodes inaccessible_nodes = set(g.nodes()) - accessible_nodes for node in inaccessible_nodes: g.del_node(node) return write_dot(g)