1
#!/usr/bin/env python2.4
2
from subprocess import Popen, PIPE
3
from urllib import urlencode
4
from xml.sax.saxutils import escape
11
RSVG_OUTPUT_TYPES = ('png', 'jpg')
12
DOT_OUTPUT_TYPES = ('svg', 'svgz', 'gif', 'jpg', 'ps', 'fig', 'mif', 'png')
14
class NoDot(Exception):
16
Exception.__init__(self, "Can't find dot!")
18
class NoRsvg(Exception):
20
Exception.__init__(self, "Can't find rsvg!")
23
def __init__(self, name, color=None, label=None, rev_id=None,
24
cluster=None, node_style=None):
30
if node_style is None:
32
self.cluster = cluster
34
def get_committer(self):
35
if self.committer is not None:
36
if '@' in self.committer:
38
return mail_map[self.committer]
42
elif self.rev_id is not None:
44
first_segment = '-'.join(self.rev_id.split('-')[:-2])\
48
if '@' in first_segment:
50
return mail_map[first_segment]
56
committer = self.get_committer()
57
if committer is not None:
58
label = "%s\\n%s" % (self.name, committer)
64
if self.color is not None:
65
attributes.append('fillcolor="%s"' % self.color)
66
style.append('filled')
67
style.extend(self.node_style)
69
attributes.append('style="%s"' % ",".join(style))
72
attributes.append('label="%s"' % label)
73
attributes.append('shape="box"')
74
if len(attributes) > 0:
75
return '%s[%s]' % (self.name, " ".join(attributes))
80
def dot_output(relations):
85
def rel_appropriate(start, end, cluster):
87
return (start.cluster is None and end.cluster is None) or \
88
start.cluster != end.cluster
90
return start.cluster==cluster and end.cluster==cluster
92
for (start, end) in relations:
93
if start.cluster is not None:
94
clusters.add(start.cluster)
95
if end.cluster is not None:
96
clusters.add(end.cluster)
97
clusters = list(clusters)
99
for index, cluster in enumerate(clusters):
100
if cluster is not None:
101
yield "subgraph cluster_%s\n" % index
103
yield ' label="%s"\n' % cluster
104
for (start, end) in relations:
105
if start.name not in defined and start.cluster == cluster:
106
defined.add(start.name)
107
my_def = start.define()
108
if my_def is not None:
109
yield " %s;\n" % my_def
110
if end.name not in defined and end.cluster == cluster:
111
defined.add(end.name)
112
my_def = end.define()
113
if my_def is not None:
114
yield " %s;\n" % my_def
115
if rel_appropriate(start, end, cluster):
116
yield " %s->%s;\n" % (start.name, end.name)
117
if cluster is not None:
121
def invoke_dot_aa(input, out_file, file_type='png'):
123
Produce antialiased Dot output, invoking rsvg on an intermediate file.
124
rsvg only supports png, jpeg and .ico files."""
125
tempdir = tempfile.mkdtemp()
127
temp_file = os.path.join(tempdir, 'temp.svg')
128
invoke_dot(input, temp_file, 'svg')
129
cmdline = ['rsvg', temp_file, out_file]
131
rsvg_proc = Popen(cmdline)
133
if e.errno == errno.ENOENT:
135
status = rsvg_proc.wait()
137
shutil.rmtree(tempdir)
140
def invoke_dot(input, out_file=None, file_type='svg', antialias=None):
141
cmdline = ['dot', '-T%s' % file_type]
142
if out_file is not None:
143
cmdline.extend(('-o', out_file))
145
dot_proc = Popen(cmdline, stdin=PIPE)
147
if e.errno == errno.ENOENT:
152
dot_proc.stdin.write(line)
153
dot_proc.stdin.close()
154
return dot_proc.wait()