| Index: third_party/logilab/common/vcgutils.py
 | 
| diff --git a/third_party/logilab/common/vcgutils.py b/third_party/logilab/common/vcgutils.py
 | 
| new file mode 100644
 | 
| index 0000000000000000000000000000000000000000..9cd2acda0cd732d61509cfd78b7db400a5e82273
 | 
| --- /dev/null
 | 
| +++ b/third_party/logilab/common/vcgutils.py
 | 
| @@ -0,0 +1,216 @@
 | 
| +# copyright 2003-2011 LOGILAB S.A. (Paris, FRANCE), all rights reserved.
 | 
| +# contact http://www.logilab.fr/ -- mailto:contact@logilab.fr
 | 
| +#
 | 
| +# This file is part of logilab-common.
 | 
| +#
 | 
| +# logilab-common is free software: you can redistribute it and/or modify it under
 | 
| +# the terms of the GNU Lesser General Public License as published by the Free
 | 
| +# Software Foundation, either version 2.1 of the License, or (at your option) any
 | 
| +# later version.
 | 
| +#
 | 
| +# logilab-common is distributed in the hope that it will be useful, but WITHOUT
 | 
| +# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
 | 
| +# FOR A PARTICULAR PURPOSE.  See the GNU Lesser General Public License for more
 | 
| +# details.
 | 
| +#
 | 
| +# You should have received a copy of the GNU Lesser General Public License along
 | 
| +# with logilab-common.  If not, see <http://www.gnu.org/licenses/>.
 | 
| +"""Functions to generate files readable with Georg Sander's vcg
 | 
| +(Visualization of Compiler Graphs).
 | 
| +
 | 
| +You can download vcg at http://rw4.cs.uni-sb.de/~sander/html/gshome.html
 | 
| +Note that vcg exists as a debian package.
 | 
| +
 | 
| +See vcg's documentation for explanation about the different values that
 | 
| +maybe used for the functions parameters.
 | 
| +
 | 
| +
 | 
| +
 | 
| +
 | 
| +"""
 | 
| +__docformat__ = "restructuredtext en"
 | 
| +
 | 
| +import string
 | 
| +
 | 
| +ATTRS_VAL = {
 | 
| +    'algos':       ('dfs', 'tree', 'minbackward',
 | 
| +                    'left_to_right', 'right_to_left',
 | 
| +                    'top_to_bottom', 'bottom_to_top',
 | 
| +                    'maxdepth', 'maxdepthslow', 'mindepth', 'mindepthslow',
 | 
| +                    'mindegree', 'minindegree', 'minoutdegree',
 | 
| +                    'maxdegree', 'maxindegree', 'maxoutdegree'),
 | 
| +    'booleans':    ('yes', 'no'),
 | 
| +    'colors':      ('black', 'white', 'blue', 'red', 'green', 'yellow',
 | 
| +                    'magenta', 'lightgrey',
 | 
| +                    'cyan', 'darkgrey', 'darkblue', 'darkred', 'darkgreen',
 | 
| +                    'darkyellow', 'darkmagenta', 'darkcyan', 'gold',
 | 
| +                    'lightblue', 'lightred', 'lightgreen', 'lightyellow',
 | 
| +                    'lightmagenta', 'lightcyan', 'lilac', 'turquoise',
 | 
| +                    'aquamarine', 'khaki', 'purple', 'yellowgreen', 'pink',
 | 
| +                    'orange', 'orchid'),
 | 
| +    'shapes':      ('box', 'ellipse', 'rhomb', 'triangle'),
 | 
| +    'textmodes':   ('center', 'left_justify', 'right_justify'),
 | 
| +    'arrowstyles': ('solid', 'line', 'none'),
 | 
| +    'linestyles':  ('continuous', 'dashed', 'dotted', 'invisible'),
 | 
| +    }
 | 
| +
 | 
| +# meaning of possible values:
 | 
| +#   O    -> string
 | 
| +#   1    -> int
 | 
| +#   list -> value in list
 | 
| +GRAPH_ATTRS = {
 | 
| +    'title':              0,
 | 
| +    'label':              0,
 | 
| +    'color':               ATTRS_VAL['colors'],
 | 
| +    'textcolor':           ATTRS_VAL['colors'],
 | 
| +    'bordercolor':         ATTRS_VAL['colors'],
 | 
| +    'width':               1,
 | 
| +    'height':              1,
 | 
| +    'borderwidth':         1,
 | 
| +    'textmode':            ATTRS_VAL['textmodes'],
 | 
| +    'shape':               ATTRS_VAL['shapes'],
 | 
| +    'shrink':              1,
 | 
| +    'stretch':             1,
 | 
| +    'orientation':         ATTRS_VAL['algos'],
 | 
| +    'vertical_order':      1,
 | 
| +    'horizontal_order':    1,
 | 
| +    'xspace':              1,
 | 
| +    'yspace':              1,
 | 
| +    'layoutalgorithm':    ATTRS_VAL['algos'],
 | 
| +    'late_edge_labels':   ATTRS_VAL['booleans'],
 | 
| +    'display_edge_labels': ATTRS_VAL['booleans'],
 | 
| +    'dirty_edge_labels':  ATTRS_VAL['booleans'],
 | 
| +    'finetuning':          ATTRS_VAL['booleans'],
 | 
| +    'manhattan_edges':     ATTRS_VAL['booleans'],
 | 
| +    'smanhattan_edges':    ATTRS_VAL['booleans'],
 | 
| +    'port_sharing':        ATTRS_VAL['booleans'],
 | 
| +    'edges':               ATTRS_VAL['booleans'],
 | 
| +    'nodes':               ATTRS_VAL['booleans'],
 | 
| +    'splines':             ATTRS_VAL['booleans'],
 | 
| +    }
 | 
| +NODE_ATTRS = {
 | 
| +    'title':              0,
 | 
| +    'label':              0,
 | 
| +    'color':               ATTRS_VAL['colors'],
 | 
| +    'textcolor':           ATTRS_VAL['colors'],
 | 
| +    'bordercolor':         ATTRS_VAL['colors'],
 | 
| +    'width':               1,
 | 
| +    'height':              1,
 | 
| +    'borderwidth':         1,
 | 
| +    'textmode':            ATTRS_VAL['textmodes'],
 | 
| +    'shape':               ATTRS_VAL['shapes'],
 | 
| +    'shrink':              1,
 | 
| +    'stretch':             1,
 | 
| +    'vertical_order':      1,
 | 
| +    'horizontal_order':    1,
 | 
| +    }
 | 
| +EDGE_ATTRS = {
 | 
| +    'sourcename':         0,
 | 
| +    'targetname':         0,
 | 
| +    'label':              0,
 | 
| +    'linestyle':          ATTRS_VAL['linestyles'],
 | 
| +    'class':              1,
 | 
| +    'thickness':          0,
 | 
| +    'color':               ATTRS_VAL['colors'],
 | 
| +    'textcolor':           ATTRS_VAL['colors'],
 | 
| +    'arrowcolor':          ATTRS_VAL['colors'],
 | 
| +    'backarrowcolor':      ATTRS_VAL['colors'],
 | 
| +    'arrowsize':           1,
 | 
| +    'backarrowsize':       1,
 | 
| +    'arrowstyle':          ATTRS_VAL['arrowstyles'],
 | 
| +    'backarrowstyle':      ATTRS_VAL['arrowstyles'],
 | 
| +    'textmode':            ATTRS_VAL['textmodes'],
 | 
| +    'priority':            1,
 | 
| +    'anchor':              1,
 | 
| +    'horizontal_order':    1,
 | 
| +    }
 | 
| +
 | 
| +
 | 
| +# Misc utilities ###############################################################
 | 
| +
 | 
| +def latin_to_vcg(st):
 | 
| +    """Convert latin characters using vcg escape sequence.
 | 
| +    """
 | 
| +    for char in st:
 | 
| +        if char not in string.ascii_letters:
 | 
| +            try:
 | 
| +                num = ord(char)
 | 
| +                if num >= 192:
 | 
| +                    st = st.replace(char, r'\fi%d'%ord(char))
 | 
| +            except:
 | 
| +                pass
 | 
| +    return st
 | 
| +
 | 
| +
 | 
| +class VCGPrinter:
 | 
| +    """A vcg graph writer.
 | 
| +    """
 | 
| +
 | 
| +    def __init__(self, output_stream):
 | 
| +        self._stream = output_stream
 | 
| +        self._indent = ''
 | 
| +
 | 
| +    def open_graph(self, **args):
 | 
| +        """open a vcg graph
 | 
| +        """
 | 
| +        self._stream.write('%sgraph:{\n'%self._indent)
 | 
| +        self._inc_indent()
 | 
| +        self._write_attributes(GRAPH_ATTRS, **args)
 | 
| +
 | 
| +    def close_graph(self):
 | 
| +        """close a vcg graph
 | 
| +        """
 | 
| +        self._dec_indent()
 | 
| +        self._stream.write('%s}\n'%self._indent)
 | 
| +
 | 
| +
 | 
| +    def node(self, title, **args):
 | 
| +        """draw a node
 | 
| +        """
 | 
| +        self._stream.write('%snode: {title:"%s"' % (self._indent, title))
 | 
| +        self._write_attributes(NODE_ATTRS, **args)
 | 
| +        self._stream.write('}\n')
 | 
| +
 | 
| +
 | 
| +    def edge(self, from_node, to_node, edge_type='', **args):
 | 
| +        """draw an edge from a node to another.
 | 
| +        """
 | 
| +        self._stream.write(
 | 
| +            '%s%sedge: {sourcename:"%s" targetname:"%s"' % (
 | 
| +            self._indent, edge_type, from_node, to_node))
 | 
| +        self._write_attributes(EDGE_ATTRS, **args)
 | 
| +        self._stream.write('}\n')
 | 
| +
 | 
| +
 | 
| +    # private ##################################################################
 | 
| +
 | 
| +    def _write_attributes(self, attributes_dict, **args):
 | 
| +        """write graph, node or edge attributes
 | 
| +        """
 | 
| +        for key, value in args.items():
 | 
| +            try:
 | 
| +                _type =  attributes_dict[key]
 | 
| +            except KeyError:
 | 
| +                raise Exception('''no such attribute %s
 | 
| +possible attributes are %s''' % (key, attributes_dict.keys()))
 | 
| +
 | 
| +            if not _type:
 | 
| +                self._stream.write('%s%s:"%s"\n' % (self._indent, key, value))
 | 
| +            elif _type == 1:
 | 
| +                self._stream.write('%s%s:%s\n' % (self._indent, key,
 | 
| +                                                  int(value)))
 | 
| +            elif value in _type:
 | 
| +                self._stream.write('%s%s:%s\n' % (self._indent, key, value))
 | 
| +            else:
 | 
| +                raise Exception('''value %s isn\'t correct for attribute %s
 | 
| +correct values are %s''' % (value, key, _type))
 | 
| +
 | 
| +    def _inc_indent(self):
 | 
| +        """increment indentation
 | 
| +        """
 | 
| +        self._indent = '  %s' % self._indent
 | 
| +
 | 
| +    def _dec_indent(self):
 | 
| +        """decrement indentation
 | 
| +        """
 | 
| +        self._indent = self._indent[:-2]
 | 
| 
 |