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 """
00088 creates a node item for this factory, adds it to the graph.
00089 Node name can vary from label but must always be same for the same node label
00090 """
00091 if nodename is None or nodename == '':
00092 raise ValueError('Empty Node name')
00093 if nodelabel is None:
00094 nodelabel = nodename
00095 node = pydot.Node(self.escape_name(nodename))
00096 node.set_shape(shape)
00097 node.set_label(self.escape_label(nodelabel))
00098 if url is not None:
00099 node.set_URL(self.escape_name(url))
00100 if color is not None:
00101 node.set_color(color)
00102 graph.add_node(node)
00103
00104 def add_subgraph_to_graph(self,
00105 graph,
00106 subgraphname,
00107 rank='same',
00108 simplify=True,
00109 rankdir='TB',
00110 ranksep=0.2,
00111 compound=True,
00112 color=None,
00113 shape='box',
00114 style='bold',
00115 subgraphlabel=None):
00116 """
00117 creates a cluster subgraph item for this factory, adds it to the graph.
00118 cluster name can vary from label but must always be same for the same node label.
00119 Most layouters require cluster names to start with cluster.
00120 """
00121 if subgraphname is None or subgraphname == '':
00122 raise ValueError('Empty subgraph name')
00123 g = pydot.Cluster(self.escape_name(subgraphname), rank=rank, rankdir=rankdir, simplify=simplify, color=color)
00124 if 'set_style' in g.__dict__:
00125 g.set_style(style)
00126 if 'set_shape' in g.__dict__:
00127 g.set_shape(shape)
00128 if LooseVersion(pydot.__version__) > LooseVersion('1.0.10'):
00129 g.set_compound(compound)
00130 g.set_ranksep(ranksep)
00131 subgraphlabel = subgraphname if subgraphlabel is None else subgraphlabel
00132 subgraphlabel = self.escape_label(subgraphlabel)
00133 if subgraphlabel:
00134 g.set_label(subgraphlabel)
00135 if 'set_color' in g.__dict__:
00136 if color is not None:
00137 g.set_color(color)
00138 graph.add_subgraph(g)
00139 return g
00140
00141 def add_edge_to_graph(self, graph, nodename1, nodename2, label=None, url=None, simplify=True, style=None, penwidth=1, color=None):
00142 if simplify and LooseVersion(pydot.__version__) < LooseVersion('1.0.10'):
00143 if graph.get_edge(self.escape_name(nodename1), self.escape_name(nodename2)) != []:
00144 return
00145 edge = pydot.Edge(self.escape_name(nodename1), self.escape_name(nodename2))
00146 if label is not None and label != '':
00147 edge.set_label(label)
00148 if url is not None:
00149 edge.set_URL(self.escape_name(url))
00150 if style is not None:
00151 edge.set_style(style)
00152 edge.obj_dict['attributes']['penwidth'] = str(penwidth)
00153 if color is not None:
00154 edge.obj_dict['attributes']['colorR'] = str(color[0])
00155 edge.obj_dict['attributes']['colorG'] = str(color[1])
00156 edge.obj_dict['attributes']['colorB'] = str(color[2])
00157 graph.add_edge(edge)
00158
00159 def create_dot(self, graph):
00160 dot = graph.create_dot()
00161
00162 return dot.replace("\\\n", "")