def nodes_to_graph(self, root_node): graph = pydot.Graph() graph.set_type('digraph') self.append_subtree_to_graph(graph, root_node) return graph
def test_graph_simplify(self): # Fail example: pydot 1.0.2. GH pydot/pydot#92 OP patch 1. g = pydot.Graph() g.add_edge(pydot.Edge('a', 'b')) g.add_edge(pydot.Edge('a', 'b')) g.add_edge(pydot.Edge('b', 'a')) g.add_edge(pydot.Edge('b', 'a')) test_combinations = [ ('graph', False, 'graph G { a -- b; a -- b; b -- a; b -- a; }'), ('graph', True, 'graph G { a -- b; }'), ('digraph', False, 'digraph G { a -> b; a -> b; b -> a; b -> a; }'), ('digraph', True, 'digraph G { a -> b; b -> a; }') ] expected_concat = observed_concat = '' for (graph_type, simplify, expected) in test_combinations: expected_concat += 'graph_type %s, simplify %s: %s\n' % ( graph_type, simplify, expected) g.set_type(graph_type) g.set_simplify(simplify) try: observed = ' '.join(g.to_string().split()) except (NameError, TypeError) as e: observed = '%s: %s' % (type(e).__name__, e) observed_concat += 'graph_type %s, simplify %s: %s\n' % ( graph_type, simplify, observed) self.maxDiff = None self.assertMultiLineEqual(expected_concat, observed_concat)
def push_top_graph_stmt(str, loc, toks): attrs = {} g = None for element in toks: if isinstance(element, ParseResults) or \ isinstance(element, tuple) or \ isinstance(element, list): element = element[0] if element == 'strict': attrs['strict'] = True elif element in ['graph', 'digraph']: attrs['graph_type'] = element elif type(element) == type(''): attrs['graph_name'] = element elif isinstance(element, pydot.Graph): g = pydot.Graph(**attrs) g.__dict__.update(element.__dict__) for e in g.get_edge_list(): e.parent_graph = g for e in g.get_node_list(): e.parent_graph = g for e in g.get_subgraph_list(): e.set_graph_parent(g) elif isinstance(element, P_AttrList): attrs.update(element.attrs) else: raise ValueError, "Unknown element statement: %r " % element if g is not None: g.__dict__.update(attrs) return g
def markup_edges(graph=pydot.Graph(), mapping={}, verbose=False): edges = graph.get_edges() if verbose: print("DEBUG: function", __name__, ", mapping:", mapping) for e in edges: attr = e.get_attributes() previous_label = attr['label'] if attr['label'] in mapping.keys(): e.set('label', mapping[attr['label']]) elif attr['label'].split(" ")[0] + " any" in mapping.keys(): e.set('label', mapping[attr['label'].split(" ")[0] + " any"]) elif len( attr['label'].split(" ") ) >= 2 and "any " + attr['label'].split(" ")[1] in mapping.keys(): e.set('label', mapping["any " + attr['label'].split(" ")[1]]) elif "any any" in mapping.keys(): e.set('label', mapping["any any"]) else: print("Error in markup") sys.exit(1) if verbose: print("Edge remap:", e.get_source(), e.get_destination, previous_label, e.get_attributes()['label']) return graph
def Deca2Dot(decaGraph, force=True, mode='dot'): wx.GetApp().log('[PyDot][dbg] build %s graph' % mode) G = pydot.Graph() G.set('layout', mode) G.set('overlap', False) for s in decaGraph.values(): tag = getattr(s, 'Tag', '') if s.Tag == 'object': node = pydot.Node(str(s.ID)) if not force: node.set('pos', "%f,%f" % (s.xpos,s.ypos)) node.set('width', float(s.width) / 72) node.set('height', float(s.height) / 72) lb = getattr(s, 'label', str(s.ID)) if lb.strip() != '': if lb.find(':') > -1: lb = '"%s"' % lb node.set('label', lb) G.add_node(node) if s.Tag == 'link': st = str(s.start) fn = str(s.finish) lnk = pydot.Edge(st, fn) if s.direct: lnk.set('dir', 'forward') if hasattr(s, 'label') and s.label != '': lnk.set('label', s.label) G.add_edge(lnk) return G.to_string()
def generate_inheritance_graph(current_entity): i = current_entity g = pydot.Graph('dot_inheritance', graph_type='graph') di = { 'rankdir': 'BT', 'ranksep': 0.2 } for kv in di.items(): g.set(*kv) previous = None while i: n = pydot.Node(i) di = { 'color':'black', 'fillcolor':'grey43', 'fontcolor':'white', 'fontsize': '10', 'height':'0.2', 'shape':'rectangle', 'style':'filled', 'width':'3', } for kv in di.items(): n.set(*kv) g.add_node(n) if previous: g.add_edge(pydot.Edge(previous, n)) previous = n i = entity_supertype.get(i) return g.to_string()
def test_edge_equality_basics_3_same_points_not_not_equal(self): # Fail example: pydot 1.4.1 on Python 2. g = pydot.Graph() e1 = pydot.Edge('a', 'b') e2 = pydot.Edge('a', 'b') g.add_edge(e1) g.add_edge(e2) self.assertFalse(e1 != e2)
def _init_dot_graph(cls) -> pydot.Graph: graph = pydot.Graph(graph_type="digraph", simplify=False) graph.set("bgcolor", "#eeeeee") graph.set("clusterrank", "local") graph.set("labelloc", "bottom") graph.set("labelloc", "bottom") graph.set("labeljust", "right") return graph
def _init_dot_graph(cls) -> pydot.Graph: graph = pydot.Graph(graph_type="digraph", simplify=False) graph.set_bgcolor("#eeeeee") graph.set_clusterrank("local") graph.set_labelloc("bottom") graph.set_labelloc("bottom") graph.set_labeljust("right") return graph
def test_graph_pickling(self): g = pydot.Graph() s = pydot.Subgraph("foo") g.add_subgraph(s) g.add_edge(pydot.Edge("A", "B")) g.add_edge(pydot.Edge("A", "C")) g.add_edge(pydot.Edge(("D", "E"))) g.add_node(pydot.Node("node!")) pickle.dumps(g)
def __init__(self, fname, mc): self.dot_graph = pydot.Graph(graph_name="MC", graph_type="digraph", simplify=True, rankdir="LR") self.node_cache = {} self.node_count = 0 self.current_transition = None self.fname = fname self.mc = mc
def test_graph_pickling(self): g = pydot.Graph() s = pydot.Subgraph("foo") g.add_subgraph(s) g.add_edge(pydot.Edge('A', 'B')) g.add_edge(pydot.Edge('A', 'C')) g.add_edge(pydot.Edge(('D', 'E'))) g.add_node(pydot.Node('node!')) pickle.dumps(g)
def test_subgraphs(self): g = pydot.Graph() s = pydot.Subgraph("foo") self.assertEqual(g.get_subgraphs(), []) self.assertEqual(g.get_subgraph_list(), []) g.add_subgraph(s) self.assertEqual(g.get_subgraphs()[0].get_name(), s.get_name()) self.assertEqual(g.get_subgraph_list()[0].get_name(), s.get_name())
def generate_graph_from_dbml(dbml: pydbml.PyDBML) -> pydot.Graph: graph = pydot.Graph() graph.set_node_defaults(fontname="Bitstream Vera Sans", fontsize=8, shape="none") graph.set_edge_defaults(fontname="Bitstream Vera Sans", fontsize=8, labeldistance=2, color="grey") graph.set_graph_defaults(rankdir='LR') enums = [] for enum in dbml.enums: enum: pydbml.classes.Enum = enum graph.add_node(pydot.Node( enum.name, label=generate_table_label(f"<I>Enum</I><BR></BR>{enum.name}", enum.items) )) enums.append(enum.name.strip()) debug(f"{enums=}") debug("Tables:", list(dbml.table_dict.keys())) for table_name, table_contents in dbml.table_dict.items(): node, edges = generate_table_nodes(table_name, table_contents, enums) graph.add_node(node) for edge in edges: graph.add_edge(edge) for reference in dbml.refs: reference: pydbml.classes.Reference = reference orig = reference.col1.name dest = reference.col2.name label_len = (len(dest) + len(orig)) if reference.table1.name == reference.table2.name: debug("Origin and destination are identical", reference.table1.name) for i in range(label_len // 8): graph.add_edge(pydot.Edge(reference.table1.name, reference.table2.name, style="invis")) # graph. graph.add_edge(pydot.Edge( reference.table1.name, reference.table2.name, headlabel=dest, taillabel=orig, xlabel=" " * label_len*2, minlen=int(math.sqrt(1+label_len/2)) # xlabel=f"{reference.col1.name} {reference.type} {reference.col2.name}" )) # graph.set_simplify(True) graph.set_type("digraph") return graph
def test_graph_pickling(self): import pickle g = pydot.Graph() s = pydot.Subgraph("foo") g.add_subgraph(s) g.add_edge(pydot.Edge('A', 'B')) g.add_edge(pydot.Edge('A', 'C')) g.add_edge(pydot.Edge(('D', 'E'))) g.add_node(pydot.Node('node!')) self.assertEqual(type(pickle.dumps(g)), bytes)
def test_graph_simplify(self): # Fail example: pydot 1.0.2. GH pydot/pydot#92 OP patch 1. g = pydot.Graph() g.add_edge(pydot.Edge("a", "b")) g.add_edge(pydot.Edge("a", "b")) g.add_edge(pydot.Edge("b", "a")) g.add_edge(pydot.Edge("b", "a")) test_combinations = [ ( "graph", False, "graph G { a -- b; a -- b; b -- a; b -- a; }", ), ( "graph", True, "graph G { a -- b; }", ), ( "digraph", False, "digraph G { a -> b; a -> b; b -> a; b -> a; }", ), ( "digraph", True, "digraph G { a -> b; b -> a; }", ), ] expected_concat = observed_concat = "" for (graph_type, simplify, expected) in test_combinations: expected_concat += "graph_type %s, simplify %s: %s\n" % ( graph_type, simplify, expected, ) g.set_type(graph_type) g.set_simplify(simplify) try: observed = " ".join(g.to_string().split()) except (NameError, TypeError) as e: observed = "%s: %s" % (type(e).__name__, e) observed_concat += "graph_type %s, simplify %s: %s\n" % ( graph_type, simplify, observed, ) self.maxDiff = None self.assertMultiLineEqual(expected_concat, observed_concat)
def __init__(self, name, description=None): """ """ # TODO: proper pickling # TODO: restore graph from mappings if description: self.description = description else: self.description = 'This mapping describes the AER connectivity\ between addresses.' self.name = "\"" + 'AER connectivity' + "\"" self.mapping = [] self.graph = pydot.Graph(self.name)
def cfg_dot(cfg,g=None): if g == None: g=pydot.Graph (name = "Tree") index = 0 allnames = [] for ccfg in cfg.functions: functionname = "%s" % ccfg.function_element.element.smallprint() subg = pydot.Subgraph("cluster_%d%d"%(id(ccfg), index), label="%s"% functionname,color="black") subg = cfg_dot(ccfg,subg) index = index + 1 cfg_dot_generate_nodes(ccfg,subg,allnames) allnames =allnames + map ( lambda x: x.get_name() , subg.get_node_list()) g.add_subgraph(subg) cfg_dot_generate_nodes(cfg,g,allnames) cfg_dot_generate_edges(cfg,g) return g
def make_graph(graphname, nodes, edges, size, fontsize, length, weight, color, penwidth, edge_exists): """ Construct a pydot graph inputs ------ graphname - Title of graph :: str nodes - iterable of nodes :: [node] edges - iterable of edges :: [(node, node)] size - size of node function :: node -> float fontsize - fontsize of node fn :: node -> int length - length (in inches) between two nodes :: node, node -> float weight - importance that this length is kept :: node, node -> float color - color of an edge (can include alpha) :: node, node -> str #000000FF penwidth - pen width with which to draw an edge :: node, node -> int edge_exists - does an edge exist? :: node, node -> bool """ # Make Graph import pydot G = pydot.Graph(graphname, graph_type='graph') # Nodes for node in nodes: dot_node = pydot.Node(node, width=size(node), height=size(node), fontsize=fontsize(node)) G.add_node(dot_node) # Edges for a, b in edges: if a < b: continue if edge_exists(a, b): edge = pydot.Edge(a, b, len=length(a, b), weight=weight(a, b), color=color(a, b), penwidth=penwidth(a, b)) G.add_edge(edge) return G
def build_graph(node, graph=None, context=None, tree=False): top = pydot.Node(id(node), label=node.name) if not graph: graph = pydot.Graph(graph_type='digraph') graph.add_node(top) context = Counter() context[node.name] += 1 # Increment the name of the top node cluster = pydot.Cluster(str(id(node.children)), label=' ') graph.add_subgraph(cluster) for child in node.children: nd, _ = build_graph(child, graph, context, tree=tree) # Ensure the graph is a tree by adding numbers to the # labels of nodes. if tree: if context[nd.name] == 0: # a name = nd.name else: # a1, a2, a3 name = nd.name + str(context[nd.name]) #name = nd.name + "_" + str(context[nd.name]) context[nd.name] += 1 # Allow cycles or "level-jumping" graphs else: name = nd.name nd = pydot.Node(id(nd), label=name) cluster.add_node(nd) graph.add_node(nd) graph.add_edge(pydot.Edge(top, nd)) return node, graph
def generate_uses_simplediagram(self): """Genera el grafico de uses del main_file.""" self.grafico = pydot.Dot(grap_name = "Diagrama de uses", graph_type = "digraph", dpi = 300 ) main_node = ModuleNode(name = self.main_name, filename = self.main_file_name, shape = "Mrecord") self.nodes.append(main_node) self.grafico.add_node(main_node) self.__create_usesnodetree(main_node, self.dependencies) print( self.dependencies) self.G=pydot.Graph(margin=5.) self.legend=pydot.Subgraph(graph_name='Legend', shape = 'Mrecord', rank='sink', label='Legend') self.grafico.add_subgraph(self.legend) self.grafico.write_svg('graphs\\uses_simplediagram.svg')#.format(time.strftime("%d%m%y%H%M"))) self.grafico.write_jpg('graphs\\uses_simplediagram.jpg'.format(time.strftime("%d%m%y%H%M"))) self.grafico.write_pdf('graphs\\uses_simplediagram.pdf'.format(time.strftime("%d%m%y%H%M"))) self.grafico.write_dot('graphs\\uses_simplediagram.dot'.format(time.strftime("%d%m%y%H%M")))
def build_graph(courses): g = pydot.Graph('courses', graph_type='digraph') def get_node_name(course): return 'node_%d' % course['serialnum'] for title, course in courses.iteritems(): names = [] for has_code in course['major_codes']: major_code = has_code['major']['code'] course_number = has_code['code'] names.append('%s %s' % (major_code, course_number)) codes = '/'.join(names) #codes = [has_code['major']['code'] + ' ' + has_code['code'] for has_code in course['major_codes']].join('/') g.add_node(pydot.Node( get_node_name(course), label='%s: %s' % (codes, course['title']), tooltip=course['prereq_text'] )) for prereq in course['prereqs']: g.add_edge(pydot.Edge(get_node_name(course), get_node_name(prereq))) return g
def convert_to_graph(actors=None): """ :param actors: List of actors or None. In case this is None or empty the graph will be generated from all loaded actors :return: A pydot.Graph instance representing the actor dependency graph """ if not pydot: raise Exception( "Please install pydot before you use the snactor graph support") g = pydot.Graph() channels = {} names = set() if actors: iterable = ((actor.definition, None) for actor in actors) else: iterable = get_registered_actors().values() for definition, _ in iterable: names.add(definition.name) for chan in definition.inputs: get_chan(channels, chan)['consumers'].append(definition.name) for chan in definition.outputs: get_chan(channels, chan)['producers'].append(definition.name) edges = {} map(g.add_node, (pydot.Node(a, label=a) for a in names)) for name, channel in channels.items(): for consumer in channel['consumers']: for producer in channel['producers']: edges.setdefault((consumer, producer), []).append(name) g.add_edge(pydot.Edge(producer, consumer, label=name)) return g
def _singletrace2dot(trace,is_beautified=False): """translate a single trace into a corresponding dot-graph; wheras the parsing assumes a correct trace given as trace ::= state ( input state )* """ # if not is_beautified: # lines = [line for line in trace if not (line.startswith("***") or # line.startswith("WARNING") or line == "\n" # or line.startswith("-- specification") or line.startswith("-- as demonstrated") # or line.startswith("Trace Description: ") or line.startswith("Trace Type: "))] # map(lambda x: x.lstrip(" "), lines) # else: # lines = trace # strip the headers of each trace. global digraph lines = [] for line in trace: #print(line) if( not (line.startswith("***") or line.startswith("WARNING") or line == "\n" or line.startswith("-- specification") or line.startswith("-- as demonstrated") or line.startswith("Trace Description: ") or line.startswith("Trace Type: "))): lines.append(line.lstrip(" ")) #print (lines) #slice list at "->" index=0 states=[] for item in lines: if item.startswith("->"): last=index index=lines.index(item) states.append(lines[last:index]) # the first state is empty states.append(lines[index:len(lines)]) print (states) lines=False #free space! graph = pydot.Graph() loop=False #flag to finally add an additional dotted edge for loop assert states[1][0].startswith("-> State:") #starting with state! digraph = 'Digraph G{\n' digraph += 'rankdir=LR\n' stateVariablesDict = OrderedDict() counter = 0 for item in states[1:]: #first item is header name= item[0].lstrip("-> ").rstrip(" <-\n") if (name.startswith("State")): state=name.lstrip("State: ") node=pydot.Node(state) props=name+'\\n' #to reach pydotfile: need double '\' digraph = digraph + 'S' + str(counter) + '[shape=box,label=\"' + name + '\\n' counter = counter + 1 #print (name) for i in (item[1:]): #props+=i.rstrip('\n') #props+="\\n" isNewValue = False s = str(i).rstrip('\n') variable = s[:s.rfind('=')].strip() value = s[s.rfind('=')+1:].strip() if(variable not in stateVariablesDict): isNewValue = False else: (val, newValInd) = stateVariablesDict[variable] if(str(val) != str(value)): isNewValue = True stateVariablesDict[variable] = (value, isNewValue) #stateVariablesList = [[k, v] for k, v in stateVariablesDict.items()] for var, (val, newValInd) in stateVariablesDict.items(): if(newValInd == True): props += '*' + str(var) + ' = ' + str(val) + '\\n' digraph = digraph + '*' + str(var) + ' = ' + str(val) + '\\n' else: props += str(var) + ' = ' + str(val) + '\\n' digraph = digraph + str(var) + ' = ' + str(val) + '\\n' node.set_label('"'+props+'"') digraph = digraph + '\"]\n' graph.add_node(node) for var, (val, newValInd) in stateVariablesDict.items(): stateVariablesDict[var] = (val, False) elif name.startswith("Input"): assert state #already visited state trans=name.lstrip("Input: ") edge=pydot.Edge(state,trans) hasLoop = [it for it in item[1:] if it.startswith("-- Loop starts here")] #TODO: check trace-syntax, if this can happen only in the last line of a transition # then list-compreh. can be avoided if hasLoop: loop=state #remember state at which loop starts item.remove(hasLoop[0]) props="" for i in (item[1:]): props+=i.rstrip('\n') props+="\\n" edge.set_label(props) graph.add_edge(edge) else: assert False #only states and transitions! if loop: edge=pydot.Edge(state,loop) edge.set_style("dotted,bold") edge.set_label(" LOOP") graph.add_edge(edge) for i in range(1, counter): digraph = digraph + 'S' + str(i-1) + ' -> ' + 'S' + str(i) + '\n' digraph = digraph + '\n}\n' return graph
def torTree2dot(self, allAtoms, index=1, selStr=None, labelEdges=True, edgeLabelStyle='node numbers', size="8,6", verbose=False): """return (dot format) graph specification""" if not self.rootNode: return offset = allAtoms[0].number - 1 self.labelEdges = labelEdges assert edgeLabelStyle in ['node numbers', 'node bond'] self.edgeLabelStyle = edgeLabelStyle gname = '"' + allAtoms[0].top.name + '"' found_pydot = 1 try: import pydot except: found_pydot = 0 if found_pydot: dg = pydot.Graph(graph_name=gname, type='digraph', label=gname, size=size) rootID = str(index) if verbose: print("1: set rootID to ", rootID) # change atList = self.rootNode.atomList[:] # start with c25,c27,c26,n1 # remove c27,c26, n1 because they're in rotatable bond to c25 for c in self.rootNode.children: next = c.bond[1] - offset if next in atList: # remove atoms connected by rotatable bonds atList.remove(next) if verbose: print("removed ", next, " from root") if verbose: print("atList =", atList) # sub_ats = AtomSet() # for ind in atList: # sub_ats.append(allAtoms[ind-1]) sub_ats = allAtoms.get(lambda x: x.number - (1 + offset) in atList) if verbose: print("sub_ats=", sub_ats.full_name()) # sub_ats=allAtoms.get(lambda x: x.number-1 in self.rootNode.atomList) rootLbl = '"' for at in sub_ats: rootLbl += "%s," % at.name # remove last ',' rootLbl = rootLbl[:-1] + '"' # rootLbl = sub_ats.full_name() # cpos = rootLbl.rfind(':') # rootLbl = '"' + rootLbl[cpos+1:] + '"' if found_pydot: rootNd = pydot.Node(rootID, label=rootLbl, shape="trapezium", style="bold") dg.add_node(rootNd) else: if verbose: print("1: added node %s, label=%s" % (rootID, rootLbl)) print("would add pydot.Node(%s, label =%s)" % (rootID, rootLbl)) dg = None next_index = index + 1 for c in self.rootNode.children: if verbose: print( c.bond, "call self.__torTree2dot(c,%d, %s, %d,dg,[])" % (next_index, rootID, len(allAtoms))) next_index = self.__torTree2dot(c, next_index, rootID, allAtoms, dg, [], verbose) dotstr = "no pydot" if found_pydot: dotstr = dg.to_string() return dotstr
def gen_dot(program_tree): p = copy.deepcopy(program_tree) g=pydot.Graph (name = "Tree") nodelist=[] walker(p,function=tree_dumper,arg=(g,nodelist)) return g.to_string()
print("Please wait...") if just_projects: nice_names = [name.title() for name in sorted(just_projects)] graph_name = '%s Universe' % (" and ".join(nice_names)) else: graph_name = 'OpenStack Universe' graph_kwargs = { 'rankdir': 'LR', 'nodesep': '0.25', 'overlap': 'false', 'ranksep': '0.5', 'splines': 'true', 'ordering': 'in', 'graph_name': graph_name, } graph = pydot.Graph(**graph_kwargs) for project_name in project_names: print(" Inserting nodes for '%s'" % project_name) node = graph_nodes[project_name] graph.add_node(node) deliverables = projects[project_name].get('deliverables', []) deliverable_names = sorted(six.iterkeys(deliverables)) for deliverable_name in deliverable_names: print(" Inserting node for '%s'" % deliverable_name) node_path = "%s/%s" % (project_name, deliverable_name) deliverable_node = graph_nodes[node_path] graph.add_node(deliverable_node) print(" Inserting edge for '%s' -> '%s'" % (project_name, deliverable_name)) graph.add_edge(pydot.Edge(node, deliverable_node, style='dotted')) end = time.time()
import pydot g=pydot.Graph("mygraph") g.add_node(pydot.Node("haha")) print(g.to_string()) print('='*20) g = pydot.Dot() g.set_type('digraph') node = pydot.Node('legend') node.set("shape", 'box') g.add_node(node) node.set('label','mine') print(g.to_string())
def _reset_graphs(self): self.graph_directed = pydot.Graph('testgraph', graph_type='digraph')
def emit_repo_as_xdot(repo, options): '''Emits xdot for the given repo on stdout.''' global graph # TODO: globals are bad mmmmkay global vertices vertices = {} graph = pydot.Graph(verbose=True) graph.set_bgcolor('#00000000') # transparent background objstore = repo.object_store seen = set() # walk everything in the object store. (this means orphaned nodes will show.) for sha in objstore: if not options.blobs and objstore[sha].type_name in ('blob', 'tree'): continue walk_node(objstore, seen, sha, options) for ref in repo.refs.keys(): if ref == 'HEAD': continue # TODO: let this loop handle symbolic refs too branch_node = add_branch_node(ref) graph.add_edge( pydot.Edge(branch_node, repo.refs[ref], **edge_opts(style='dotted'))) # do HEAD as a special case ref = 'HEAD' nopts = node_opts(label=ref, shape='diamond', style='filled', fillcolor='#ff3333', fontcolor='white', tooltip='Symbolic Ref: HEAD') head_node = pydot.Node(ref, **nopts) graph.add_node(head_node) symref = repo.refs.read_ref(ref) if symref.startswith('ref: '): symref = symref[5:] points_to = add_branch_node(symref) graph.add_node(points_to) graph.add_edge( pydot.Edge(head_node, add_branch_node(symref), **edge_opts(style='dotted'))) # index if options.index: try: head_tree = repo['HEAD'].tree except KeyError: head_tree = None index = repo.open_index() try: changes = list(index.changes_from_tree(objstore, head_tree)) except TypeError: # the official dulwich repo throws a TypeError changes_from_tree is # called against an empty tree (None) if head_tree is not None: raise changes = [] if changes: index_node = pydot.Node('index', shape='invtriangle', style='filled', fillcolor='#33ff33', fontname=DEFAULT_FONTNAME, fontsize=DEFAULT_FONTSIZE) graph.add_node(index_node) for (oldpath, newpath), (oldmode, newmode), (oldsha, newsha) in changes: graph.add_edge( pydot.Edge(index_node, vert_for_sha(objstore, newsha), label=q(' ' + newpath), fontname=DEFAULT_FONTNAME, fontsize=DEFAULT_FONTSIZE)) # invoke dot -Txdot to turn out DOT file into an xdot file, which canviz is expecting subprocess.Popen(['dot', '-Txdot'], stdin=subprocess.PIPE).communicate(graph.to_string())