00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033 from distutils.version import LooseVersion
00034 import urllib
00035
00036
00037 import pyparsing
00038 pyparsing._noncomma = "".join([c for c in pyparsing.printables if c != ","])
00039 import pydot
00040
00041
00042
00043 class PydotFactory():
00044
00045 def __init__(self):
00046 pass
00047
00048 def escape_label(self, name):
00049 if name in ['graph', 'subgraph', 'node', 'edge']:
00050 ret = "%s_" % name
00051 else:
00052 ret = name
00053 return ret
00054
00055 def escape_name(self, name):
00056 ret = urllib.quote(name.strip())
00057 ret = ret.replace('/', '_')
00058 ret = ret.replace('%', '_')
00059 ret = ret.replace('-', '_')
00060 return self.escape_label(ret)
00061
00062 def get_graph(self, graph_type='digraph', rank='same', simplify=True, rankdir='TB', ranksep=0.2, compound=True):
00063
00064 if LooseVersion(pydot.__version__) > LooseVersion('1.0.10'):
00065 graph = pydot.Dot('graphname',
00066 graph_type=graph_type,
00067 rank=rank,
00068 rankdir=rankdir,
00069 simplify=simplify
00070 )
00071 graph.set_ranksep(ranksep)
00072 graph.set_compound(compound)
00073 else:
00074 graph = pydot.Dot('graphname',
00075 graph_type=graph_type,
00076 rank=rank,
00077 rankdir=rankdir)
00078 return graph
00079
00080 def add_node_to_graph(self,
00081 graph,
00082 nodename,
00083 nodelabel=None,
00084 shape='box',
00085 color=None,
00086 url=None,
00087 tooltip=None):
00088 """
00089 creates a node item for this factory, adds it to the graph.
00090 Node name can vary from label but must always be same for the same node label
00091 """
00092 if nodename is None or nodename == '':
00093 raise ValueError('Empty Node name')
00094 if nodelabel is None:
00095 nodelabel = nodename
00096 node = pydot.Node(self.escape_name(nodename))
00097 node.set_shape(shape)
00098 node.set_label(self.escape_label(nodelabel))
00099 if tooltip is not None:
00100 node.set_tooltip(tooltip)
00101 elif url is not None:
00102 node.set_tooltip(url)
00103 if url is not None:
00104 node.set_URL(self.escape_name(url))
00105 if color is not None:
00106 node.set_color(color)
00107 graph.add_node(node)
00108
00109 def add_subgraph_to_graph(self,
00110 graph,
00111 subgraphname,
00112 rank='same',
00113 simplify=True,
00114 rankdir='TB',
00115 ranksep=0.2,
00116 compound=True,
00117 color=None,
00118 shape='box',
00119 style='bold',
00120 subgraphlabel=None):
00121 """
00122 creates a cluster subgraph item for this factory, adds it to the graph.
00123 cluster name can vary from label but must always be same for the same node label.
00124 Most layouters require cluster names to start with cluster.
00125 """
00126 if subgraphname is None or subgraphname == '':
00127 raise ValueError('Empty subgraph name')
00128 g = pydot.Cluster(self.escape_name(subgraphname), rank=rank, rankdir=rankdir, simplify=simplify, color=color)
00129 if 'set_style' in g.__dict__:
00130 g.set_style(style)
00131 if 'set_shape' in g.__dict__:
00132 g.set_shape(shape)
00133 if LooseVersion(pydot.__version__) > LooseVersion('1.0.10'):
00134 g.set_compound(compound)
00135 g.set_ranksep(ranksep)
00136 subgraphlabel = subgraphname if subgraphlabel is None else subgraphlabel
00137 subgraphlabel = self.escape_label(subgraphlabel)
00138 if subgraphlabel:
00139 g.set_label(subgraphlabel)
00140 if 'set_color' in g.__dict__:
00141 if color is not None:
00142 g.set_color(color)
00143 graph.add_subgraph(g)
00144 return g
00145
00146 def add_edge_to_graph(self, graph, nodename1, nodename2, label=None, url=None, simplify=True, style=None, penwidth=1, color=None):
00147 if simplify and LooseVersion(pydot.__version__) < LooseVersion('1.0.10'):
00148 if graph.get_edge(self.escape_name(nodename1), self.escape_name(nodename2)) != []:
00149 return
00150 edge = pydot.Edge(self.escape_name(nodename1), self.escape_name(nodename2))
00151 if label is not None and label != '':
00152 edge.set_label(label)
00153 if url is not None:
00154 edge.set_URL(self.escape_name(url))
00155 if style is not None:
00156 edge.set_style(style)
00157 edge.obj_dict['attributes']['penwidth'] = str(penwidth)
00158 if color is not None:
00159 edge.obj_dict['attributes']['colorR'] = str(color[0])
00160 edge.obj_dict['attributes']['colorG'] = str(color[1])
00161 edge.obj_dict['attributes']['colorB'] = str(color[2])
00162 graph.add_edge(edge)
00163
00164 def create_dot(self, graph):
00165 dot = graph.create_dot()
00166
00167 return dot.replace("\\\n", "")