1 # Copyright (c) 2010 The Chromium OS Authors. All rights reserved.
2 # Use of this source code is governed by a BSD-style license that can be
3 # found in the LICENSE file.
5 """Helper functions for building graphs with dot."""
7 from __future__ import print_function
9 from chromite.lib import cros_build_lib
10 from chromite.lib import osutils
13 class Subgraph(object):
14 """A subgraph in dot. Contains nodes, arcs, and other subgraphs."""
16 _valid_ranks = set(['source', 'sink', 'same', 'min', 'max', None])
18 def __init__(self, rank=None):
25 def AddNode(self, node_id, name=None, color=None, href=None):
26 """Adds a node to the subgraph."""
32 tags['fontcolor'] = color
35 self._nodes.append({'id': node_id, 'tags': tags})
37 def AddSubgraph(self, subgraph):
38 """Adds a subgraph to the subgraph."""
39 self._subgraphs.append(subgraph)
41 def AddNewSubgraph(self, rank=None):
42 """Adds a new subgraph to the subgraph. The new subgraph is returned."""
43 subgraph = Subgraph(rank)
44 self.AddSubgraph(subgraph)
47 def AddArc(self, node_from, node_to):
48 """Adds an arc between two nodes."""
49 self._arcs.add((node_from, node_to))
52 """Generates the code for all the nodes."""
54 for node in self._nodes:
55 tags = ['%s="%s"' % (k, v) for (k, v) in node['tags'].iteritems()]
56 lines.append('"%s" [%s];' % (node['id'], ', '.join(tags)))
59 def _GenSubgraphs(self):
60 """Generates the code for all the subgraphs contained in this subgraph."""
62 for subgraph in self._subgraphs:
63 lines += subgraph.Gen()
67 """Generates the code for all the arcs."""
69 for node_from, node_to in self._arcs:
70 lines.append('"%s" -> "%s";' % (node_from, node_to))
74 """Generates the code for the inner contents of the subgraph."""
77 lines.append('rank=%s;' % self._rank)
78 lines += self._GenSubgraphs()
79 lines += self._GenNodes()
80 lines += self._GenArcs()
84 """Generates the code for the subgraph."""
85 return ['subgraph {'] + self._GenInner() + ['}']
88 class Graph(Subgraph):
89 """A top-level graph in dot. It's basically a subgraph with a name."""
91 def __init__(self, name):
92 Subgraph.__init__(self)
96 """Generates the code for the graph."""
97 return ['digraph "%s" {' % self._name,
98 'graph [name="%s"];' % self._name] + self._GenInner() + ['}']
101 def GenerateImage(lines, filename, out_format='svg', save_dot_filename=None):
102 """Generates the image by calling dot on the input lines."""
103 data = '\n'.join(lines)
104 cros_build_lib.RunCommand(['dot', '-T%s' % out_format, '-o', filename],
107 if save_dot_filename:
108 osutils.WriteFile(save_dot_filename, data)