/usr/share/pyshared/mastertickets/graphviz.py is in trac-mastertickets 3.0.2+20111224-2.
This file is owned by root:root, with mode 0o644.
The actual contents of the file can be viewed below.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 | # -*- coding: utf-8 -*-
# Created by Noah Kantrowitz on 2007-12-21.
# Copyright (c) 2007 Noah Kantrowitz. All rights reserved.
import os
import subprocess
import tempfile
import time
import itertools
try:
set = set
except NameError:
from sets import Set as set
def _format_options(base_string, options):
return u'%s [%s]'%(base_string, u', '.join([u'%s="%s"'%x for x in options.iteritems()]))
class Edge(dict):
"""Model for an edge in a dot graph."""
def __init__(self, source, dest, **kwargs):
self.source = source
self.dest = dest
dict.__init__(self, **kwargs)
def __str__(self):
ret = u'%s -> %s'%(self.source.name, self.dest.name)
if self:
ret = _format_options(ret, self)
return ret
def __hash__(self):
return hash(id(self))
class Node(dict):
"""Model for a node in a dot graph."""
def __init__(self, name, **kwargs):
self.name = unicode(name)
self.edges = []
dict.__init__(self, **kwargs)
def __str__(self):
ret = self.name
if self:
ret = _format_options(ret, self)
return ret
def __gt__(self, other):
"""Allow node1 > node2 to add an edge."""
edge = Edge(self, other)
self.edges.append(edge)
other.edges.append(edge)
return edge
def __lt__(self, other):
edge = Edge(other, self)
self.edges.append(edge)
other.edges.append(edge)
return edge
def __hash__(self):
return hash(id(self))
class Graph(object):
"""A model object for a graphviz digraph."""
def __init__(self, name=u'graph'):
super(Graph,self).__init__()
self.name = name
self.nodes = []
self._node_map = {}
self.attributes={}
self.edges = []
def add(self, obj):
if isinstance(obj, Node):
self.nodes.append(obj)
self._node_map[obj.name] = obj
elif isinstance(obj, Edge):
self.edges.append(obj)
def __getitem__(self, key):
key = unicode(key)
if key not in self._node_map:
new_node = Node(key)
self._node_map[key] = new_node
self.nodes.append(new_node)
return self._node_map[key]
def __delitem__(self, key):
key = unicode(key)
node = self._node_map.pop(key)
self.nodes.remove(node)
def __str__(self):
edges = []
nodes = []
memo = set()
def process(lst):
for obj in lst:
if obj in memo:
continue
memo.add(obj)
if isinstance(obj, Node):
nodes.append(obj)
process(obj.edges)
elif isinstance(obj, Edge):
edges.append(obj)
if isinstance(obj.source, Node):
process((obj.source,))
if isinstance(obj.dest, Node):
process((obj.dest,))
process(self.nodes)
process(self.edges)
lines = [u'digraph "%s" {'%self.name]
for att,value in self.attributes.iteritems():
lines.append(u'\t%s="%s";' % (att,value))
for obj in itertools.chain(nodes, edges):
lines.append(u'\t%s;'%obj)
lines.append(u'}')
return u'\n'.join(lines)
def render(self, dot_path='dot', format='png'):
"""Render a dot graph."""
proc = subprocess.Popen([dot_path, '-T%s'%format], stdin=subprocess.PIPE, stdout=subprocess.PIPE)
out, _ = proc.communicate(unicode(self).encode('utf8'))
return out
if __name__ == '__main__':
g = Graph()
root = Node('me')
root > Node('them')
root < Node(u'Üs')
g.add(root)
print g.render()
|