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 import pydot
00034 import urllib
00035 from distutils.version import LooseVersion
00036
00037
00038
00039 class PydotFactory():
00040
00041 def __init__(self):
00042 pass
00043
00044 def escape_label(self, name):
00045 if name in ['graph', 'subgraph', 'node', 'edge']:
00046 ret = "%s_" % name
00047 else:
00048 ret = name
00049 return ret
00050
00051 def escape_name(self, name):
00052 ret = urllib.quote(name.strip())
00053 ret = ret.replace('/', '_')
00054 ret = ret.replace('%', '_')
00055 ret = ret.replace('-', '_')
00056 return self.escape_label(ret)
00057
00058 def get_graph(self, graph_type='digraph', rank='same', simplify=True, rankdir='TB', ranksep=0.2, compound=True):
00059
00060 if LooseVersion(pydot.__version__) > LooseVersion('1.0.10'):
00061 graph = pydot.Dot('graphname',
00062 graph_type=graph_type,
00063 rank=rank,
00064 rankdir=rankdir,
00065 simplify=simplify
00066 )
00067 graph.set_ranksep(ranksep)
00068 graph.set_compound(compound)
00069 else:
00070 graph = pydot.Dot('graphname',
00071 graph_type=graph_type,
00072 rank=rank,
00073 rankdir=rankdir)
00074 return graph
00075
00076 def add_node_to_graph(self,
00077 graph,
00078 nodename,
00079 nodelabel=None,
00080 shape='box',
00081 color=None,
00082 url=None):
00083 """
00084 creates a node item for this factory, adds it to the graph.
00085 Node name can vary from label but must always be same for the same node label
00086 """
00087 if nodename is None or nodename == '':
00088 raise ValueError('Empty Node label')
00089 if nodelabel is None:
00090 nodelabel = nodename
00091 node = pydot.Node(self.escape_name(nodelabel))
00092 node.set_shape(shape)
00093 node.set_label(self.escape_label(nodelabel))
00094 if url is not None:
00095 node.set_URL(self.escape_name(url))
00096 if color is not None:
00097 node.set_color(color)
00098 graph.add_node(node)
00099
00100 def add_subgraph_to_graph(self,
00101 graph,
00102 subgraphlabel,
00103 rank='same',
00104 simplify=True,
00105 rankdir='TB',
00106 ranksep=0.2,
00107 compound=True,
00108 color=None,
00109 shape='box',
00110 style='bold'):
00111 """
00112 creates a cluster subgraph item for this factory, adds it to the graph.
00113 cluster name can vary from label but must always be same for the same node label.
00114 Most layouters require cluster names to start with cluster.
00115 """
00116 if subgraphlabel is None or subgraphlabel == '':
00117 raise ValueError('Empty subgraph label')
00118 g = pydot.Cluster(self.escape_name(subgraphlabel), rank=rank, rankdir=rankdir, simplify=simplify)
00119 if 'set_style' in g.__dict__:
00120 g.set_style(style)
00121 if 'set_shape' in g.__dict__:
00122 g.set_shape(shape)
00123 if LooseVersion(pydot.__version__) > LooseVersion('1.0.10'):
00124 g.set_compound(compound)
00125 g.set_ranksep(ranksep)
00126 g.set_label(subgraphlabel)
00127 if 'set_color' in g.__dict__:
00128 if color is not None:
00129 g.set_color(color)
00130 graph.add_subgraph(g)
00131 return g
00132
00133 def add_edge_to_graph(self, graph, nodename1, nodename2, label=None, url=None, simplify=True, style=None):
00134 if simplify and LooseVersion(pydot.__version__) < LooseVersion('1.0.10'):
00135 if graph.get_edge(self.escape_name(nodename1), self.escape_name(nodename2)) != []:
00136 return
00137 edge = pydot.Edge(self.escape_name(nodename1), self.escape_name(nodename2))
00138 if label is not None and label != '':
00139 edge.set_label(label)
00140 if url is not None:
00141 edge.set_URL(self.escape_name(url))
00142 if style is not None:
00143 edge.set_style(style)
00144 graph.add_edge(edge)
00145
00146 def create_dot(self, graph):
00147 dot = graph.create_dot()
00148
00149 return dot.replace("\\\n", "")