Package logilab :: Package common :: Module vcgutils

[frames] | no frames]

# Source Code for Module logilab.common.vcgutils

      1  # copyright 2003-2011 LOGILAB S.A. (Paris, FRANCE), all rights reserved.
      2  # contact http://www.logilab.fr/ -- mailto:contact@logilab.fr
      3  #
      4  # This file is part of logilab-common.
      5  #
      6  # logilab-common is free software: you can redistribute it and/or modify it under
      7  # the terms of the GNU Lesser General Public License as published by the Free
      8  # Software Foundation, either version 2.1 of the License, or (at your option) any
      9  # later version.
     10  #
     11  # logilab-common is distributed in the hope that it will be useful, but WITHOUT
     12  # ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
     13  # FOR A PARTICULAR PURPOSE.  See the GNU Lesser General Public License for more
     14  # details.
     15  #
     16  # You should have received a copy of the GNU Lesser General Public License along
     17  # with logilab-common.  If not, see <http://www.gnu.org/licenses/>.
     18  """Functions to generate files readable with Georg Sander's vcg
     19  (Visualization of Compiler Graphs).
     20
     21  You can download vcg at http://rw4.cs.uni-sb.de/~sander/html/gshome.html
     22  Note that vcg exists as a debian package.
     23
     24  See vcg's documentation for explanation about the different values that
     25  maybe used for the functions parameters.
     26
     27
     28
     29
     30  """
     31  __docformat__ = "restructuredtext en"
     32
     33  import string
     34
     35  ATTRS_VAL = {
     36      'algos':       ('dfs', 'tree', 'minbackward',
     37                      'left_to_right', 'right_to_left',
     38                      'top_to_bottom', 'bottom_to_top',
     39                      'maxdepth', 'maxdepthslow', 'mindepth', 'mindepthslow',
     40                      'mindegree', 'minindegree', 'minoutdegree',
     41                      'maxdegree', 'maxindegree', 'maxoutdegree'),
     42      'booleans':    ('yes', 'no'),
     43      'colors':      ('black', 'white', 'blue', 'red', 'green', 'yellow',
     44                      'magenta', 'lightgrey',
     45                      'cyan', 'darkgrey', 'darkblue', 'darkred', 'darkgreen',
     46                      'darkyellow', 'darkmagenta', 'darkcyan', 'gold',
     47                      'lightblue', 'lightred', 'lightgreen', 'lightyellow',
     48                      'lightmagenta', 'lightcyan', 'lilac', 'turquoise',
     49                      'aquamarine', 'khaki', 'purple', 'yellowgreen', 'pink',
     50                      'orange', 'orchid'),
     51      'shapes':      ('box', 'ellipse', 'rhomb', 'triangle'),
     52      'textmodes':   ('center', 'left_justify', 'right_justify'),
     53      'arrowstyles': ('solid', 'line', 'none'),
     54      'linestyles':  ('continuous', 'dashed', 'dotted', 'invisible'),
     55      }
     56
     57  # meaning of possible values:
     58  #   O    -> string
     59  #   1    -> int
     60  #   list -> value in list
     61  GRAPH_ATTRS = {
     62      'title':              0,
     63      'label':              0,
     64      'color':               ATTRS_VAL['colors'],
     65      'textcolor':           ATTRS_VAL['colors'],
     66      'bordercolor':         ATTRS_VAL['colors'],
     67      'width':               1,
     68      'height':              1,
     69      'borderwidth':         1,
     70      'textmode':            ATTRS_VAL['textmodes'],
     71      'shape':               ATTRS_VAL['shapes'],
     72      'shrink':              1,
     73      'stretch':             1,
     74      'orientation':         ATTRS_VAL['algos'],
     75      'vertical_order':      1,
     76      'horizontal_order':    1,
     77      'xspace':              1,
     78      'yspace':              1,
     79      'layoutalgorithm':    ATTRS_VAL['algos'],
     80      'late_edge_labels':   ATTRS_VAL['booleans'],
     81      'display_edge_labels': ATTRS_VAL['booleans'],
     82      'dirty_edge_labels':  ATTRS_VAL['booleans'],
     83      'finetuning':          ATTRS_VAL['booleans'],
     84      'manhattan_edges':     ATTRS_VAL['booleans'],
     85      'smanhattan_edges':    ATTRS_VAL['booleans'],
     86      'port_sharing':        ATTRS_VAL['booleans'],
     87      'edges':               ATTRS_VAL['booleans'],
     88      'nodes':               ATTRS_VAL['booleans'],
     89      'splines':             ATTRS_VAL['booleans'],
     90      }
     91  NODE_ATTRS = {
     92      'title':              0,
     93      'label':              0,
     94      'color':               ATTRS_VAL['colors'],
     95      'textcolor':           ATTRS_VAL['colors'],
     96      'bordercolor':         ATTRS_VAL['colors'],
     97      'width':               1,
     98      'height':              1,
     99      'borderwidth':         1,
    100      'textmode':            ATTRS_VAL['textmodes'],
    101      'shape':               ATTRS_VAL['shapes'],
    102      'shrink':              1,
    103      'stretch':             1,
    104      'vertical_order':      1,
    105      'horizontal_order':    1,
    106      }
    107  EDGE_ATTRS = {
    108      'sourcename':         0,
    109      'targetname':         0,
    110      'label':              0,
    111      'linestyle':          ATTRS_VAL['linestyles'],
    112      'class':              1,
    113      'thickness':          0,
    114      'color':               ATTRS_VAL['colors'],
    115      'textcolor':           ATTRS_VAL['colors'],
    116      'arrowcolor':          ATTRS_VAL['colors'],
    117      'backarrowcolor':      ATTRS_VAL['colors'],
    118      'arrowsize':           1,
    119      'backarrowsize':       1,
    120      'arrowstyle':          ATTRS_VAL['arrowstyles'],
    121      'backarrowstyle':      ATTRS_VAL['arrowstyles'],
    122      'textmode':            ATTRS_VAL['textmodes'],
    123      'priority':            1,
    124      'anchor':              1,
    125      'horizontal_order':    1,
    126      }
    127
    128
    129  # Misc utilities ###############################################################
    130
    131 -def latin_to_vcg(st):
    132      """Convert latin characters using vcg escape sequence.
    133      """
    134      for char in st:
    135          if char not in string.ascii_letters:
    136              try:
    137                  num = ord(char)
    138                  if num >= 192:
    139                      st = st.replace(char, r'\fi%d'%ord(char))
    140              except:
    141                  pass
    142      return st
    143
    144
    145 -class VCGPrinter:
    146      """A vcg graph writer.
    147      """
    148
    149 -    def __init__(self, output_stream):
    150          self._stream = output_stream
    151          self._indent = ''
    152
    153 -    def open_graph(self, **args):
    154          """open a vcg graph
    155          """
    156          self._stream.write('%sgraph:{\n'%self._indent)
    157          self._inc_indent()
    158          self._write_attributes(GRAPH_ATTRS, **args)
    159
    160 -    def close_graph(self):
    161          """close a vcg graph
    162          """
    163          self._dec_indent()
    164          self._stream.write('%s}\n'%self._indent)
    165
    166
    167 -    def node(self, title, **args):
    168          """draw a node
    169          """
    170          self._stream.write('%snode: {title:"%s"' % (self._indent, title))
    171          self._write_attributes(NODE_ATTRS, **args)
    172          self._stream.write('}\n')
    173
    174
    175 -    def edge(self, from_node, to_node, edge_type='', **args):
    176          """draw an edge from a node to another.
    177          """
    178          self._stream.write(
    179              '%s%sedge: {sourcename:"%s" targetname:"%s"' % (
    180              self._indent, edge_type, from_node, to_node))
    181          self._write_attributes(EDGE_ATTRS, **args)
    182          self._stream.write('}\n')
    183
    184
    185      # private ##################################################################
    186
    187 -    def _write_attributes(self, attributes_dict, **args):
    188          """write graph, node or edge attributes
    189          """
    190          for key, value in args.items():
    191              try:
    192                  _type =  attributes_dict[key]
    193              except KeyError:
    194                  raise Exception('''no such attribute %s
    195  possible attributes are %s''' % (key, attributes_dict.keys()))
    196
    197              if not _type:
    198                  self._stream.write('%s%s:"%s"\n' % (self._indent, key, value))
    199              elif _type == 1:
    200                  self._stream.write('%s%s:%s\n' % (self._indent, key,
    201                                                    int(value)))
    202              elif value in _type:
    203                  self._stream.write('%s%s:%s\n' % (self._indent, key, value))
    204              else:
    205                  raise Exception('''value %s isn\'t correct for attribute %s
    206  correct values are %s''' % (value, key, _type))
    207
    208 -    def _inc_indent(self):
    209          """increment indentation
    210          """
    211          self._indent = '  %s' % self._indent
    212
    213 -    def _dec_indent(self):
    214          """decrement indentation
    215          """
    216          self._indent = self._indent[:-2]
    217