1
#!/usr/bin/env python2.4
2
from subprocess import Popen, PIPE
3
from urllib import urlencode
4
from xml.sax.saxutils import escape
12
class NoDot(Exception):
14
Exception.__init__(self, "Can't find dot!")
16
class NoRsvg(Exception):
18
Exception.__init__(self, "Can't find rsvg!")
21
def __init__(self, name, color=None, label=None, rev_id=None,
29
self.cluster = cluster
31
def get_committer(self):
32
if self.committer is not None:
33
if '@' in self.committer:
35
return mail_map[self.committer]
39
elif self.rev_id is not None:
41
first_segment = '-'.join(self.rev_id.split('-')[:-2])\
45
if '@' in first_segment:
47
return mail_map[first_segment]
53
committer = self.get_committer()
54
if committer is not None:
55
label = "%s\\n%s" % (self.name, committer)
61
if self.color is not None:
62
attributes.append('fillcolor="%s"' % self.color)
63
style.append('filled')
64
style.extend(self.node_style)
66
attributes.append('style="%s"' % ",".join(style))
67
label = self.get_label()
69
attributes.append('label="%s"' % label)
70
attributes.append('shape="box"')
71
if len(attributes) > 0:
72
return '%s[%s]' % (self.name, " ".join(attributes))
77
def dot_output(relations):
82
def rel_appropriate(start, end, cluster):
84
return start.cluster is None or end.cluster is None
86
return start.cluster==cluster and end.cluster==cluster
88
for (start, end) in relations:
89
if start.cluster is not None:
90
clusters.add(start.cluster)
91
if end.cluster is not None:
92
clusters.add(end.cluster)
93
clusters = list(clusters)
95
for index, cluster in enumerate(clusters):
96
if cluster is not None:
97
yield "subgraph cluster_%s\n" % index
99
yield ' label="%s"\n' % cluster
100
for (start, end) in relations:
101
if start.name not in defined and start.cluster == cluster:
102
defined.add(start.name)
103
my_def = start.define()
104
if my_def is not None:
105
yield " %s;\n" % my_def
106
if end.name not in defined and end.cluster == cluster:
107
defined.add(end.name)
108
my_def = end.define()
109
if my_def is not None:
110
yield " %s;\n" % my_def
111
if rel_appropriate(start, end, cluster):
112
yield " %s->%s;\n" % (start.name, end.name)
113
if cluster is not None:
117
def invoke_dot_aa(input, out_file, file_type='png'):
119
Produce antialiased Dot output, invoking rsvg on an intermediate file.
120
rsvg only supports png, jpeg and .ico files."""
121
tempdir = tempfile.mkdtemp()
123
temp_file = os.path.join(tempdir, 'temp.svg')
124
invoke_dot(input, temp_file, 'svg')
125
cmdline = ['rsvg', temp_file, out_file]
127
rsvg_proc = Popen(cmdline)
129
if e.errno == errno.ENOENT:
131
status = rsvg_proc.wait()
133
shutil.rmtree(tempdir)
136
def invoke_dot(input, out_file=None, file_type='svg', antialias=None):
137
cmdline = ['dot', '-T%s' % file_type]
138
if out_file is not None:
139
cmdline.extend(('-o', out_file))
141
dot_proc = Popen(cmdline, stdin=PIPE)
143
if e.errno == errno.ENOENT:
148
dot_proc.stdin.write(line)
149
dot_proc.stdin.close()
150
return dot_proc.wait()