pydotfactory.py
Go to the documentation of this file.
1 # Software License Agreement (BSD License)
2 #
3 # Copyright (c) 2008, Willow Garage, Inc.
4 # All rights reserved.
5 #
6 # Redistribution and use in source and binary forms, with or without
7 # modification, are permitted provided that the following conditions
8 # are met:
9 #
10 # * Redistributions of source code must retain the above copyright
11 # notice, this list of conditions and the following disclaimer.
12 # * Redistributions in binary form must reproduce the above
13 # copyright notice, this list of conditions and the following
14 # disclaimer in the documentation and/or other materials provided
15 # with the distribution.
16 # * Neither the name of Willow Garage, Inc. nor the names of its
17 # contributors may be used to endorse or promote products derived
18 # from this software without specific prior written permission.
19 #
20 # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
21 # "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
22 # LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
23 # FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
24 # COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
25 # INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
26 # BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
27 # LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
28 # CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
29 # LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
30 # ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
31 # POSSIBILITY OF SUCH DAMAGE.
32 
33 from distutils.version import LooseVersion
34 try:
35  from urllib.request import quote
36 except ImportError:
37  from urllib import quote
38 
39 import os
40 
41 import pydot
42 
43 
44 # Reference implementation for a dotcode factory
45 class PydotFactory():
46 
47  def __init__(self):
48  pass
49 
50  def escape_label(self, name):
51  if name in ['graph', 'subgraph', 'node', 'edge']:
52  ret = '%s_' % name
53  else:
54  ret = name
55  return ret
56 
57  def escape_name(self, name):
58  ret = quote(name.strip())
59  ret = ret.replace('/', '__')
60  ret = ret.replace('%', '_')
61  ret = ret.replace('-', '_')
62  return self.escape_label(ret)
63 
64  def get_graph(
65  self, graph_type='digraph', rank='same', simplify=True,
66  rankdir='TB', ranksep=0.2, compound=True):
67  # Lucid version of pydot bugs with certain settings, not sure which
68  # version exactly fixes those
69  if LooseVersion(pydot.__version__) > LooseVersion('1.0.10'):
70  graph = pydot.Dot('graphname',
71  graph_type=graph_type,
72  rank=rank,
73  rankdir=rankdir,
74  simplify=simplify
75  )
76  graph.set_ranksep(ranksep)
77  graph.set_compound(compound)
78  else:
79  graph = pydot.Dot('graphname',
80  graph_type=graph_type,
81  rank=rank,
82  rankdir=rankdir)
83  return graph
84 
85  def add_node_to_graph(self,
86  graph,
87  nodename,
88  nodelabel=None,
89  shape='box',
90  color=None,
91  url=None,
92  tooltip=None):
93  """
94  Create a node item for this factory, adds it to the graph.
95 
96  Node name can vary from label but must always be same for the same node label
97  """
98  if nodename is None or nodename == '':
99  raise ValueError('Empty Node name')
100  if nodelabel is None:
101  nodelabel = nodename
102  node = pydot.Node(self.escape_name(nodename))
103  node.set_shape(shape)
104  node.set_label(self.escape_label(nodelabel))
105  if tooltip is not None:
106  node.set_tooltip(tooltip)
107  elif url is not None:
108  node.set_tooltip(url)
109  if url is not None:
110  node.set_URL(self.escape_name(url))
111  if color is not None:
112  node.set_color(color)
113  graph.add_node(node)
114 
115  def add_subgraph_to_graph(self,
116  graph,
117  subgraphname,
118  rank='same',
119  simplify=True,
120  rankdir='TB',
121  ranksep=0.2,
122  compound=True,
123  color=None,
124  shape='box',
125  style='bold',
126  subgraphlabel=None):
127  """
128  Create a cluster subgraph item for this factory, adds it to the graph.
129 
130  cluster name can vary from label but must always be same for the same node label.
131  Most layouters require cluster names to start with cluster.
132  """
133  if subgraphname is None or subgraphname == '':
134  raise ValueError('Empty subgraph name')
135  g = pydot.Cluster(self.escape_name(subgraphname),
136  rank=rank, rankdir=rankdir, simplify=simplify)
137  if 'set_style' in g.__dict__:
138  g.set_style(style)
139  if 'set_shape' in g.__dict__:
140  g.set_shape(shape)
141  if LooseVersion(pydot.__version__) > LooseVersion('1.0.10'):
142  g.set_compound(compound)
143  g.set_ranksep(ranksep)
144  subgraphlabel = subgraphname if subgraphlabel is None else subgraphlabel
145  subgraphlabel = self.escape_label(subgraphlabel)
146  if subgraphlabel:
147  g.set_label(subgraphlabel)
148  if 'set_color' in g.__dict__:
149  if color is not None:
150  g.set_color(color)
151  graph.add_subgraph(g)
152  return g
153 
154  def add_edge_to_graph(
155  self, graph, nodename1, nodename2, label=None, url=None,
156  simplify=True, style=None, penwidth=1, color=None):
157  if simplify and LooseVersion(pydot.__version__) < LooseVersion('1.0.10'):
158  if graph.get_edge(self.escape_name(nodename1), self.escape_name(nodename2)) != []:
159  return
160  edge = pydot.Edge(self.escape_name(nodename1), self.escape_name(nodename2))
161  if label is not None and label != '':
162  edge.set_label(label)
163  if url is not None:
164  edge.set_URL(self.escape_name(url))
165  if style is not None:
166  edge.set_style(style)
167  edge.obj_dict['attributes']['penwidth'] = str(penwidth)
168  if color is not None:
169  edge.obj_dict['attributes']['colorR'] = str(color[0])
170  edge.obj_dict['attributes']['colorG'] = str(color[1])
171  edge.obj_dict['attributes']['colorB'] = str(color[2])
172  graph.add_edge(edge)
173 
174  def create_dot(self, graph):
175  dot = graph.create_dot()
176  if type(dot) != str:
177  dot = dot.decode()
178  # sadly pydot generates line wraps cutting between numbers
179  return dot.replace('\\%s' % os.linesep, '').replace('\\\n', '')
def get_graph(self, graph_type='digraph', rank='same', simplify=True, rankdir='TB', ranksep=0.2, compound=True)
Definition: pydotfactory.py:66
def add_node_to_graph(self, graph, nodename, nodelabel=None, shape='box', color=None, url=None, tooltip=None)
Definition: pydotfactory.py:92
def add_subgraph_to_graph(self, graph, subgraphname, rank='same', simplify=True, rankdir='TB', ranksep=0.2, compound=True, color=None, shape='box', style='bold', subgraphlabel=None)
def add_edge_to_graph(self, graph, nodename1, nodename2, label=None, url=None, simplify=True, style=None, penwidth=1, color=None)


qt_dotgraph
Author(s): Thibault Kruse, Dirk Thomas
autogenerated on Fri Jun 24 2022 02:42:36