|
rdobuilder |
3e5fd2 |
From 050e291cbf63fd190f1ec14d65d1154a23ce8756 Mon Sep 17 00:00:00 2001
|
|
rdobuilder |
3e5fd2 |
From: Sandro Tosi <morph@debian.org>
|
|
rdobuilder |
3e5fd2 |
Date: Sun, 10 Jan 2016 00:25:45 +0000
|
|
rdobuilder |
3e5fd2 |
Subject: support python3
|
|
rdobuilder |
3e5fd2 |
|
|
rdobuilder |
3e5fd2 |
Origin: https://github.com/nlhepler/pydot/tree/adf18a858a63b321b7e4ffd964a24d73add1bf4f
|
|
rdobuilder |
3e5fd2 |
Bug-Debian: https://bugs.debian.org/cgi-bin/bugreport.cgi?bug=739858
|
|
rdobuilder |
3e5fd2 |
Reviewed-by: Sandro Tosi <morph@debian.org>
|
|
rdobuilder |
3e5fd2 |
Last-Update: 2016-01-10
|
|
rdobuilder |
3e5fd2 |
|
|
rdobuilder |
3e5fd2 |
---
|
|
rdobuilder |
3e5fd2 |
dot_parser.py | 429 ++++++++--------
|
|
rdobuilder |
3e5fd2 |
pydot.py | 1553 +++++++++++++++++++++++++++------------------------------
|
|
rdobuilder |
3e5fd2 |
setup.py | 6 +-
|
|
rdobuilder |
3e5fd2 |
3 files changed, 954 insertions(+), 1034 deletions(-)
|
|
rdobuilder |
3e5fd2 |
|
|
rdobuilder |
3e5fd2 |
diff --git a/dot_parser.py b/dot_parser.py
|
|
rdobuilder |
3e5fd2 |
index dedd61a..4cdd482 100644
|
|
rdobuilder |
3e5fd2 |
--- a/dot_parser.py
|
|
rdobuilder |
3e5fd2 |
+++ b/dot_parser.py
|
|
rdobuilder |
3e5fd2 |
@@ -1,4 +1,3 @@
|
|
rdobuilder |
3e5fd2 |
-# -*- coding: Latin-1 -*-
|
|
rdobuilder |
3e5fd2 |
"""Graphviz's dot language parser.
|
|
rdobuilder |
3e5fd2 |
|
|
rdobuilder |
3e5fd2 |
The dotparser parses graphviz files in dot and dot files and transforms them
|
|
rdobuilder |
3e5fd2 |
@@ -10,236 +9,215 @@ Author: Michael Krause <michael@krause-software.de>
|
|
rdobuilder |
3e5fd2 |
Fixes by: Ero Carrera <ero@dkbza.org>
|
|
rdobuilder |
3e5fd2 |
"""
|
|
rdobuilder |
3e5fd2 |
|
|
rdobuilder |
3e5fd2 |
+from __future__ import division, print_function
|
|
rdobuilder |
3e5fd2 |
+
|
|
rdobuilder |
3e5fd2 |
__author__ = ['Michael Krause', 'Ero Carrera']
|
|
rdobuilder |
3e5fd2 |
__license__ = 'MIT'
|
|
rdobuilder |
3e5fd2 |
|
|
rdobuilder |
3e5fd2 |
-
|
|
rdobuilder |
3e5fd2 |
import sys
|
|
rdobuilder |
3e5fd2 |
-import glob
|
|
rdobuilder |
3e5fd2 |
import pydot
|
|
rdobuilder |
3e5fd2 |
-import re
|
|
rdobuilder |
3e5fd2 |
import codecs
|
|
rdobuilder |
3e5fd2 |
|
|
rdobuilder |
3e5fd2 |
from pyparsing import __version__ as pyparsing_version
|
|
rdobuilder |
3e5fd2 |
|
|
rdobuilder |
3e5fd2 |
-from pyparsing import ( nestedExpr, Literal, CaselessLiteral, Word, Upcase, OneOrMore, ZeroOrMore,
|
|
rdobuilder |
3e5fd2 |
- Forward, NotAny, delimitedList, oneOf, Group, Optional, Combine, alphas, nums,
|
|
rdobuilder |
3e5fd2 |
- restOfLine, cStyleComment, nums, alphanums, printables, empty, quotedString,
|
|
rdobuilder |
3e5fd2 |
- ParseException, ParseResults, CharsNotIn, _noncomma, dblQuotedString, QuotedString, ParserElement )
|
|
rdobuilder |
3e5fd2 |
+from pyparsing import (
|
|
rdobuilder |
3e5fd2 |
+ nestedExpr, Literal, CaselessLiteral, Word, OneOrMore,
|
|
rdobuilder |
3e5fd2 |
+ Forward, Group, Optional, Combine, nums, restOfLine,
|
|
rdobuilder |
3e5fd2 |
+ cStyleComment, alphanums, printables, ParseException,
|
|
rdobuilder |
3e5fd2 |
+ ParseResults, CharsNotIn, QuotedString
|
|
rdobuilder |
3e5fd2 |
+ )
|
|
rdobuilder |
3e5fd2 |
+
|
|
rdobuilder |
3e5fd2 |
+
|
|
rdobuilder |
3e5fd2 |
+PY3 = not sys.version_info < (3, 0, 0)
|
|
rdobuilder |
3e5fd2 |
+
|
|
rdobuilder |
3e5fd2 |
+if PY3:
|
|
rdobuilder |
3e5fd2 |
+ basestring = str
|
|
rdobuilder |
3e5fd2 |
|
|
rdobuilder |
3e5fd2 |
|
|
rdobuilder |
3e5fd2 |
class P_AttrList:
|
|
rdobuilder |
3e5fd2 |
|
|
rdobuilder |
3e5fd2 |
def __init__(self, toks):
|
|
rdobuilder |
3e5fd2 |
-
|
|
rdobuilder |
3e5fd2 |
self.attrs = {}
|
|
rdobuilder |
3e5fd2 |
i = 0
|
|
rdobuilder |
3e5fd2 |
-
|
|
rdobuilder |
3e5fd2 |
+
|
|
rdobuilder |
3e5fd2 |
while i < len(toks):
|
|
rdobuilder |
3e5fd2 |
attrname = toks[i]
|
|
rdobuilder |
3e5fd2 |
- if i+2 < len(toks) and toks[i+1] == '=':
|
|
rdobuilder |
3e5fd2 |
- attrvalue = toks[i+2]
|
|
rdobuilder |
3e5fd2 |
+ if i + 2 < len(toks) and toks[i + 1] == '=':
|
|
rdobuilder |
3e5fd2 |
+ attrvalue = toks[i + 2]
|
|
rdobuilder |
3e5fd2 |
i += 3
|
|
rdobuilder |
3e5fd2 |
else:
|
|
rdobuilder |
3e5fd2 |
attrvalue = None
|
|
rdobuilder |
3e5fd2 |
i += 1
|
|
rdobuilder |
3e5fd2 |
-
|
|
rdobuilder |
3e5fd2 |
+
|
|
rdobuilder |
3e5fd2 |
self.attrs[attrname] = attrvalue
|
|
rdobuilder |
3e5fd2 |
-
|
|
rdobuilder |
3e5fd2 |
-
|
|
rdobuilder |
3e5fd2 |
- def __repr__(self):
|
|
rdobuilder |
3e5fd2 |
|
|
rdobuilder |
3e5fd2 |
+ def __repr__(self):
|
|
rdobuilder |
3e5fd2 |
return "%s(%r)" % (self.__class__.__name__, self.attrs)
|
|
rdobuilder |
3e5fd2 |
|
|
rdobuilder |
3e5fd2 |
|
|
rdobuilder |
3e5fd2 |
-
|
|
rdobuilder |
3e5fd2 |
class DefaultStatement(P_AttrList):
|
|
rdobuilder |
3e5fd2 |
|
|
rdobuilder |
3e5fd2 |
def __init__(self, default_type, attrs):
|
|
rdobuilder |
3e5fd2 |
-
|
|
rdobuilder |
3e5fd2 |
self.default_type = default_type
|
|
rdobuilder |
3e5fd2 |
self.attrs = attrs
|
|
rdobuilder |
3e5fd2 |
|
|
rdobuilder |
3e5fd2 |
def __repr__(self):
|
|
rdobuilder |
3e5fd2 |
-
|
|
rdobuilder |
3e5fd2 |
- return "%s(%s, %r)" % (self.__class__.__name__,
|
|
rdobuilder |
3e5fd2 |
- self.default_type, self.attrs)
|
|
rdobuilder |
3e5fd2 |
+ return "%s(%s, %r)" % (
|
|
rdobuilder |
3e5fd2 |
+ self.__class__.__name__,
|
|
rdobuilder |
3e5fd2 |
+ self.default_type, self.attrs
|
|
rdobuilder |
3e5fd2 |
+ )
|
|
rdobuilder |
3e5fd2 |
|
|
rdobuilder |
3e5fd2 |
|
|
rdobuilder |
3e5fd2 |
top_graphs = list()
|
|
rdobuilder |
3e5fd2 |
|
|
rdobuilder |
3e5fd2 |
-def push_top_graph_stmt(str, loc, toks):
|
|
rdobuilder |
3e5fd2 |
|
|
rdobuilder |
3e5fd2 |
+def push_top_graph_stmt(str, loc, toks):
|
|
rdobuilder |
3e5fd2 |
attrs = {}
|
|
rdobuilder |
3e5fd2 |
g = None
|
|
rdobuilder |
3e5fd2 |
-
|
|
rdobuilder |
3e5fd2 |
+
|
|
rdobuilder |
3e5fd2 |
for element in toks:
|
|
rdobuilder |
3e5fd2 |
-
|
|
rdobuilder |
3e5fd2 |
- if( isinstance(element, (ParseResults, tuple, list)) and
|
|
rdobuilder |
3e5fd2 |
- len(element) == 1 and isinstance(element[0], basestring) ):
|
|
rdobuilder |
3e5fd2 |
-
|
|
rdobuilder |
3e5fd2 |
+ if (isinstance(element, (ParseResults, tuple, list)) and
|
|
rdobuilder |
3e5fd2 |
+ len(element) == 1 and isinstance(element[0], basestring)):
|
|
rdobuilder |
3e5fd2 |
element = element[0]
|
|
rdobuilder |
3e5fd2 |
-
|
|
rdobuilder |
3e5fd2 |
+
|
|
rdobuilder |
3e5fd2 |
if element == 'strict':
|
|
rdobuilder |
3e5fd2 |
attrs['strict'] = True
|
|
rdobuilder |
3e5fd2 |
-
|
|
rdobuilder |
3e5fd2 |
- elif element in ['graph', 'digraph']:
|
|
rdobuilder |
3e5fd2 |
|
|
rdobuilder |
3e5fd2 |
+ elif element in ['graph', 'digraph']:
|
|
rdobuilder |
3e5fd2 |
attrs = {}
|
|
rdobuilder |
3e5fd2 |
-
|
|
rdobuilder |
3e5fd2 |
+
|
|
rdobuilder |
3e5fd2 |
g = pydot.Dot(graph_type=element, **attrs)
|
|
rdobuilder |
3e5fd2 |
attrs['type'] = element
|
|
rdobuilder |
3e5fd2 |
-
|
|
rdobuilder |
3e5fd2 |
- top_graphs.append( g )
|
|
rdobuilder |
3e5fd2 |
-
|
|
rdobuilder |
3e5fd2 |
- elif isinstance( element, basestring):
|
|
rdobuilder |
3e5fd2 |
- g.set_name( element )
|
|
rdobuilder |
3e5fd2 |
-
|
|
rdobuilder |
3e5fd2 |
+
|
|
rdobuilder |
3e5fd2 |
+ top_graphs.append(g)
|
|
rdobuilder |
3e5fd2 |
+
|
|
rdobuilder |
3e5fd2 |
+ elif isinstance(element, basestring):
|
|
rdobuilder |
3e5fd2 |
+ g.set_name(element)
|
|
rdobuilder |
3e5fd2 |
+
|
|
rdobuilder |
3e5fd2 |
elif isinstance(element, pydot.Subgraph):
|
|
rdobuilder |
3e5fd2 |
-
|
|
rdobuilder |
3e5fd2 |
- g.obj_dict['attributes'].update( element.obj_dict['attributes'] )
|
|
rdobuilder |
3e5fd2 |
- g.obj_dict['edges'].update( element.obj_dict['edges'] )
|
|
rdobuilder |
3e5fd2 |
- g.obj_dict['nodes'].update( element.obj_dict['nodes'] )
|
|
rdobuilder |
3e5fd2 |
- g.obj_dict['subgraphs'].update( element.obj_dict['subgraphs'] )
|
|
rdobuilder |
3e5fd2 |
-
|
|
rdobuilder |
3e5fd2 |
+ g.obj_dict['attributes'].update(element.obj_dict['attributes'])
|
|
rdobuilder |
3e5fd2 |
+ g.obj_dict['edges'].update(element.obj_dict['edges'])
|
|
rdobuilder |
3e5fd2 |
+ g.obj_dict['nodes'].update(element.obj_dict['nodes'])
|
|
rdobuilder |
3e5fd2 |
+ g.obj_dict['subgraphs'].update(element.obj_dict['subgraphs'])
|
|
rdobuilder |
3e5fd2 |
g.set_parent_graph(g)
|
|
rdobuilder |
3e5fd2 |
-
|
|
rdobuilder |
3e5fd2 |
+
|
|
rdobuilder |
3e5fd2 |
elif isinstance(element, P_AttrList):
|
|
rdobuilder |
3e5fd2 |
attrs.update(element.attrs)
|
|
rdobuilder |
3e5fd2 |
|
|
rdobuilder |
3e5fd2 |
elif isinstance(element, (ParseResults, list)):
|
|
rdobuilder |
3e5fd2 |
add_elements(g, element)
|
|
rdobuilder |
3e5fd2 |
-
|
|
rdobuilder |
3e5fd2 |
+
|
|
rdobuilder |
3e5fd2 |
else:
|
|
rdobuilder |
3e5fd2 |
- raise ValueError, "Unknown element statement: %r " % element
|
|
rdobuilder |
3e5fd2 |
-
|
|
rdobuilder |
3e5fd2 |
-
|
|
rdobuilder |
3e5fd2 |
+ raise ValueError("Unknown element statement: %r " % element)
|
|
rdobuilder |
3e5fd2 |
+
|
|
rdobuilder |
3e5fd2 |
for g in top_graphs:
|
|
rdobuilder |
3e5fd2 |
update_parent_graph_hierarchy(g)
|
|
rdobuilder |
3e5fd2 |
-
|
|
rdobuilder |
3e5fd2 |
- if len( top_graphs ) == 1:
|
|
rdobuilder |
3e5fd2 |
+
|
|
rdobuilder |
3e5fd2 |
+ if len(top_graphs) == 1:
|
|
rdobuilder |
3e5fd2 |
return top_graphs[0]
|
|
rdobuilder |
3e5fd2 |
-
|
|
rdobuilder |
3e5fd2 |
+
|
|
rdobuilder |
3e5fd2 |
return top_graphs
|
|
rdobuilder |
3e5fd2 |
|
|
rdobuilder |
3e5fd2 |
|
|
rdobuilder |
3e5fd2 |
def update_parent_graph_hierarchy(g, parent_graph=None, level=0):
|
|
rdobuilder |
3e5fd2 |
-
|
|
rdobuilder |
3e5fd2 |
-
|
|
rdobuilder |
3e5fd2 |
if parent_graph is None:
|
|
rdobuilder |
3e5fd2 |
parent_graph = g
|
|
rdobuilder |
3e5fd2 |
-
|
|
rdobuilder |
3e5fd2 |
- for key_name in ('edges',):
|
|
rdobuilder |
3e5fd2 |
|
|
rdobuilder |
3e5fd2 |
+ for key_name in ('edges',):
|
|
rdobuilder |
3e5fd2 |
if isinstance(g, pydot.frozendict):
|
|
rdobuilder |
3e5fd2 |
item_dict = g
|
|
rdobuilder |
3e5fd2 |
else:
|
|
rdobuilder |
3e5fd2 |
item_dict = g.obj_dict
|
|
rdobuilder |
3e5fd2 |
-
|
|
rdobuilder |
3e5fd2 |
- if not item_dict.has_key( key_name ):
|
|
rdobuilder |
3e5fd2 |
+
|
|
rdobuilder |
3e5fd2 |
+ if key_name not in item_dict:
|
|
rdobuilder |
3e5fd2 |
continue
|
|
rdobuilder |
3e5fd2 |
|
|
rdobuilder |
3e5fd2 |
for key, objs in item_dict[key_name].items():
|
|
rdobuilder |
3e5fd2 |
for obj in objs:
|
|
rdobuilder |
3e5fd2 |
- if 'parent_graph' in obj and obj['parent_graph'].get_parent_graph()==g:
|
|
rdobuilder |
3e5fd2 |
+ if 'parent_graph' in obj and obj['parent_graph'].get_parent_graph() == g:
|
|
rdobuilder |
3e5fd2 |
if obj['parent_graph'] is g:
|
|
rdobuilder |
3e5fd2 |
pass
|
|
rdobuilder |
3e5fd2 |
else:
|
|
rdobuilder |
3e5fd2 |
obj['parent_graph'].set_parent_graph(parent_graph)
|
|
rdobuilder |
3e5fd2 |
|
|
rdobuilder |
3e5fd2 |
if key_name == 'edges' and len(key) == 2:
|
|
rdobuilder |
3e5fd2 |
- for idx, vertex in enumerate( obj['points'] ):
|
|
rdobuilder |
3e5fd2 |
- if isinstance( vertex, (pydot.Graph, pydot.Subgraph, pydot.Cluster)):
|
|
rdobuilder |
3e5fd2 |
+ for idx, vertex in enumerate(obj['points']):
|
|
rdobuilder |
3e5fd2 |
+ if isinstance(vertex, (pydot.Graph, pydot.Subgraph, pydot.Cluster)):
|
|
rdobuilder |
3e5fd2 |
vertex.set_parent_graph(parent_graph)
|
|
rdobuilder |
3e5fd2 |
- if isinstance( vertex, pydot.frozendict):
|
|
rdobuilder |
3e5fd2 |
+ if isinstance(vertex, pydot.frozendict):
|
|
rdobuilder |
3e5fd2 |
if vertex['parent_graph'] is g:
|
|
rdobuilder |
3e5fd2 |
pass
|
|
rdobuilder |
3e5fd2 |
else:
|
|
rdobuilder |
3e5fd2 |
vertex['parent_graph'].set_parent_graph(parent_graph)
|
|
rdobuilder |
3e5fd2 |
|
|
rdobuilder |
3e5fd2 |
|
|
rdobuilder |
3e5fd2 |
-
|
|
rdobuilder |
3e5fd2 |
def add_defaults(element, defaults):
|
|
rdobuilder |
3e5fd2 |
-
|
|
rdobuilder |
3e5fd2 |
d = element.__dict__
|
|
rdobuilder |
3e5fd2 |
for key, value in defaults.items():
|
|
rdobuilder |
3e5fd2 |
if not d.get(key):
|
|
rdobuilder |
3e5fd2 |
d[key] = value
|
|
rdobuilder |
3e5fd2 |
|
|
rdobuilder |
3e5fd2 |
|
|
rdobuilder |
3e5fd2 |
-
|
|
rdobuilder |
3e5fd2 |
def add_elements(g, toks, defaults_graph=None, defaults_node=None, defaults_edge=None):
|
|
rdobuilder |
3e5fd2 |
-
|
|
rdobuilder |
3e5fd2 |
if defaults_graph is None:
|
|
rdobuilder |
3e5fd2 |
defaults_graph = {}
|
|
rdobuilder |
3e5fd2 |
if defaults_node is None:
|
|
rdobuilder |
3e5fd2 |
defaults_node = {}
|
|
rdobuilder |
3e5fd2 |
if defaults_edge is None:
|
|
rdobuilder |
3e5fd2 |
defaults_edge = {}
|
|
rdobuilder |
3e5fd2 |
-
|
|
rdobuilder |
3e5fd2 |
+
|
|
rdobuilder |
3e5fd2 |
for elm_idx, element in enumerate(toks):
|
|
rdobuilder |
3e5fd2 |
-
|
|
rdobuilder |
3e5fd2 |
if isinstance(element, (pydot.Subgraph, pydot.Cluster)):
|
|
rdobuilder |
3e5fd2 |
-
|
|
rdobuilder |
3e5fd2 |
add_defaults(element, defaults_graph)
|
|
rdobuilder |
3e5fd2 |
g.add_subgraph(element)
|
|
rdobuilder |
3e5fd2 |
-
|
|
rdobuilder |
3e5fd2 |
+
|
|
rdobuilder |
3e5fd2 |
elif isinstance(element, pydot.Node):
|
|
rdobuilder |
3e5fd2 |
-
|
|
rdobuilder |
3e5fd2 |
add_defaults(element, defaults_node)
|
|
rdobuilder |
3e5fd2 |
g.add_node(element)
|
|
rdobuilder |
3e5fd2 |
-
|
|
rdobuilder |
3e5fd2 |
+
|
|
rdobuilder |
3e5fd2 |
elif isinstance(element, pydot.Edge):
|
|
rdobuilder |
3e5fd2 |
-
|
|
rdobuilder |
3e5fd2 |
add_defaults(element, defaults_edge)
|
|
rdobuilder |
3e5fd2 |
g.add_edge(element)
|
|
rdobuilder |
3e5fd2 |
-
|
|
rdobuilder |
3e5fd2 |
+
|
|
rdobuilder |
3e5fd2 |
elif isinstance(element, ParseResults):
|
|
rdobuilder |
3e5fd2 |
-
|
|
rdobuilder |
3e5fd2 |
for e in element:
|
|
rdobuilder |
3e5fd2 |
add_elements(g, [e], defaults_graph, defaults_node, defaults_edge)
|
|
rdobuilder |
3e5fd2 |
-
|
|
rdobuilder |
3e5fd2 |
+
|
|
rdobuilder |
3e5fd2 |
elif isinstance(element, DefaultStatement):
|
|
rdobuilder |
3e5fd2 |
-
|
|
rdobuilder |
3e5fd2 |
if element.default_type == 'graph':
|
|
rdobuilder |
3e5fd2 |
-
|
|
rdobuilder |
3e5fd2 |
default_graph_attrs = pydot.Node('graph', **element.attrs)
|
|
rdobuilder |
3e5fd2 |
g.add_node(default_graph_attrs)
|
|
rdobuilder |
3e5fd2 |
|
|
rdobuilder |
3e5fd2 |
elif element.default_type == 'node':
|
|
rdobuilder |
3e5fd2 |
-
|
|
rdobuilder |
3e5fd2 |
default_node_attrs = pydot.Node('node', **element.attrs)
|
|
rdobuilder |
3e5fd2 |
g.add_node(default_node_attrs)
|
|
rdobuilder |
3e5fd2 |
|
|
rdobuilder |
3e5fd2 |
elif element.default_type == 'edge':
|
|
rdobuilder |
3e5fd2 |
-
|
|
rdobuilder |
3e5fd2 |
default_edge_attrs = pydot.Node('edge', **element.attrs)
|
|
rdobuilder |
3e5fd2 |
g.add_node(default_edge_attrs)
|
|
rdobuilder |
3e5fd2 |
defaults_edge.update(element.attrs)
|
|
rdobuilder |
3e5fd2 |
|
|
rdobuilder |
3e5fd2 |
else:
|
|
rdobuilder |
3e5fd2 |
- raise ValueError, "Unknown DefaultStatement: %s " % element.default_type
|
|
rdobuilder |
3e5fd2 |
-
|
|
rdobuilder |
3e5fd2 |
+ raise ValueError("Unknown DefaultStatement: %s " % element.default_type)
|
|
rdobuilder |
3e5fd2 |
+
|
|
rdobuilder |
3e5fd2 |
elif isinstance(element, P_AttrList):
|
|
rdobuilder |
3e5fd2 |
-
|
|
rdobuilder |
3e5fd2 |
g.obj_dict['attributes'].update(element.attrs)
|
|
rdobuilder |
3e5fd2 |
|
|
rdobuilder |
3e5fd2 |
else:
|
|
rdobuilder |
3e5fd2 |
- raise ValueError, "Unknown element statement: %r" % element
|
|
rdobuilder |
3e5fd2 |
+ raise ValueError("Unknown element statement: %r" % element)
|
|
rdobuilder |
3e5fd2 |
|
|
rdobuilder |
3e5fd2 |
|
|
rdobuilder |
3e5fd2 |
-def push_graph_stmt(str, loc, toks):
|
|
rdobuilder |
3e5fd2 |
-
|
|
rdobuilder |
3e5fd2 |
+def push_graph_stmt(str, loc, toks):
|
|
rdobuilder |
3e5fd2 |
g = pydot.Subgraph('')
|
|
rdobuilder |
3e5fd2 |
add_elements(g, toks)
|
|
rdobuilder |
3e5fd2 |
return g
|
|
rdobuilder |
3e5fd2 |
|
|
rdobuilder |
3e5fd2 |
|
|
rdobuilder |
3e5fd2 |
def push_subgraph_stmt(str, loc, toks):
|
|
rdobuilder |
3e5fd2 |
-
|
|
rdobuilder |
3e5fd2 |
g = pydot.Subgraph('')
|
|
rdobuilder |
3e5fd2 |
+
|
|
rdobuilder |
3e5fd2 |
for e in toks:
|
|
rdobuilder |
3e5fd2 |
- if len(e)==3:
|
|
rdobuilder |
3e5fd2 |
+ if len(e) == 3:
|
|
rdobuilder |
3e5fd2 |
e[2].set_name(e[1])
|
|
rdobuilder |
3e5fd2 |
if e[0] == 'subgraph':
|
|
rdobuilder |
3e5fd2 |
e[2].obj_dict['show_keyword'] = True
|
|
rdobuilder |
3e5fd2 |
@@ -253,11 +231,9 @@ def push_subgraph_stmt(str, loc, toks):
|
|
rdobuilder |
3e5fd2 |
|
|
rdobuilder |
3e5fd2 |
|
|
rdobuilder |
3e5fd2 |
def push_default_stmt(str, loc, toks):
|
|
rdobuilder |
3e5fd2 |
-
|
|
rdobuilder |
3e5fd2 |
# The pydot class instances should be marked as
|
|
rdobuilder |
3e5fd2 |
# default statements to be inherited by actual
|
|
rdobuilder |
3e5fd2 |
# graphs, nodes and edges.
|
|
rdobuilder |
3e5fd2 |
- #
|
|
rdobuilder |
3e5fd2 |
default_type = toks[0][0]
|
|
rdobuilder |
3e5fd2 |
if len(toks) > 1:
|
|
rdobuilder |
3e5fd2 |
attrs = toks[1].attrs
|
|
rdobuilder |
3e5fd2 |
@@ -267,90 +243,80 @@ def push_default_stmt(str, loc, toks):
|
|
rdobuilder |
3e5fd2 |
if default_type in ['graph', 'node', 'edge']:
|
|
rdobuilder |
3e5fd2 |
return DefaultStatement(default_type, attrs)
|
|
rdobuilder |
3e5fd2 |
else:
|
|
rdobuilder |
3e5fd2 |
- raise ValueError, "Unknown default statement: %r " % toks
|
|
rdobuilder |
3e5fd2 |
+ raise ValueError("Unknown default statement: %r " % toks)
|
|
rdobuilder |
3e5fd2 |
|
|
rdobuilder |
3e5fd2 |
|
|
rdobuilder |
3e5fd2 |
def push_attr_list(str, loc, toks):
|
|
rdobuilder |
3e5fd2 |
-
|
|
rdobuilder |
3e5fd2 |
p = P_AttrList(toks)
|
|
rdobuilder |
3e5fd2 |
return p
|
|
rdobuilder |
3e5fd2 |
|
|
rdobuilder |
3e5fd2 |
|
|
rdobuilder |
3e5fd2 |
def get_port(node):
|
|
rdobuilder |
3e5fd2 |
-
|
|
rdobuilder |
3e5fd2 |
- if len(node)>1:
|
|
rdobuilder |
3e5fd2 |
+ if len(node) > 1:
|
|
rdobuilder |
3e5fd2 |
if isinstance(node[1], ParseResults):
|
|
rdobuilder |
3e5fd2 |
- if len(node[1][0])==2:
|
|
rdobuilder |
3e5fd2 |
- if node[1][0][0]==':':
|
|
rdobuilder |
3e5fd2 |
+ if len(node[1][0]) == 2:
|
|
rdobuilder |
3e5fd2 |
+ if node[1][0][0] == ':':
|
|
rdobuilder |
3e5fd2 |
return node[1][0][1]
|
|
rdobuilder |
3e5fd2 |
-
|
|
rdobuilder |
3e5fd2 |
return None
|
|
rdobuilder |
3e5fd2 |
|
|
rdobuilder |
3e5fd2 |
-
|
|
rdobuilder |
3e5fd2 |
-def do_node_ports(node):
|
|
rdobuilder |
3e5fd2 |
|
|
rdobuilder |
3e5fd2 |
+def do_node_ports(node):
|
|
rdobuilder |
3e5fd2 |
node_port = ''
|
|
rdobuilder |
3e5fd2 |
+
|
|
rdobuilder |
3e5fd2 |
if len(node) > 1:
|
|
rdobuilder |
3e5fd2 |
- node_port = ''.join( [str(a)+str(b) for a,b in node[1] ] )
|
|
rdobuilder |
3e5fd2 |
+ node_port = ''.join([str(a) + str(b) for a, b in node[1]])
|
|
rdobuilder |
3e5fd2 |
|
|
rdobuilder |
3e5fd2 |
return node_port
|
|
rdobuilder |
3e5fd2 |
|
|
rdobuilder |
3e5fd2 |
-
|
|
rdobuilder |
3e5fd2 |
+
|
|
rdobuilder |
3e5fd2 |
def push_edge_stmt(str, loc, toks):
|
|
rdobuilder |
3e5fd2 |
-
|
|
rdobuilder |
3e5fd2 |
tok_attrs = [a for a in toks if isinstance(a, P_AttrList)]
|
|
rdobuilder |
3e5fd2 |
attrs = {}
|
|
rdobuilder |
3e5fd2 |
+
|
|
rdobuilder |
3e5fd2 |
for a in tok_attrs:
|
|
rdobuilder |
3e5fd2 |
attrs.update(a.attrs)
|
|
rdobuilder |
3e5fd2 |
|
|
rdobuilder |
3e5fd2 |
e = []
|
|
rdobuilder |
3e5fd2 |
|
|
rdobuilder |
3e5fd2 |
if isinstance(toks[0][0], pydot.Graph):
|
|
rdobuilder |
3e5fd2 |
-
|
|
rdobuilder |
3e5fd2 |
n_prev = pydot.frozendict(toks[0][0].obj_dict)
|
|
rdobuilder |
3e5fd2 |
- else:
|
|
rdobuilder |
3e5fd2 |
- n_prev = toks[0][0] + do_node_ports( toks[0] )
|
|
rdobuilder |
3e5fd2 |
+ else:
|
|
rdobuilder |
3e5fd2 |
+ n_prev = toks[0][0] + do_node_ports(toks[0])
|
|
rdobuilder |
3e5fd2 |
|
|
rdobuilder |
3e5fd2 |
if isinstance(toks[2][0], ParseResults):
|
|
rdobuilder |
3e5fd2 |
-
|
|
rdobuilder |
3e5fd2 |
- n_next_list = [[n.get_name(),] for n in toks[2][0] ]
|
|
rdobuilder |
3e5fd2 |
+ n_next_list = [[n.get_name()] for n in toks[2][0]]
|
|
rdobuilder |
3e5fd2 |
for n_next in [n for n in n_next_list]:
|
|
rdobuilder |
3e5fd2 |
n_next_port = do_node_ports(n_next)
|
|
rdobuilder |
3e5fd2 |
- e.append(pydot.Edge(n_prev, n_next[0]+n_next_port, **attrs))
|
|
rdobuilder |
3e5fd2 |
+ e.append(pydot.Edge(n_prev, n_next[0] + n_next_port, **attrs))
|
|
rdobuilder |
3e5fd2 |
|
|
rdobuilder |
3e5fd2 |
elif isinstance(toks[2][0], pydot.Graph):
|
|
rdobuilder |
3e5fd2 |
-
|
|
rdobuilder |
3e5fd2 |
e.append(pydot.Edge(n_prev, pydot.frozendict(toks[2][0].obj_dict), **attrs))
|
|
rdobuilder |
3e5fd2 |
|
|
rdobuilder |
3e5fd2 |
elif isinstance(toks[2][0], pydot.Node):
|
|
rdobuilder |
3e5fd2 |
-
|
|
rdobuilder |
3e5fd2 |
node = toks[2][0]
|
|
rdobuilder |
3e5fd2 |
-
|
|
rdobuilder |
3e5fd2 |
+
|
|
rdobuilder |
3e5fd2 |
if node.get_port() is not None:
|
|
rdobuilder |
3e5fd2 |
name_port = node.get_name() + ":" + node.get_port()
|
|
rdobuilder |
3e5fd2 |
else:
|
|
rdobuilder |
3e5fd2 |
name_port = node.get_name()
|
|
rdobuilder |
3e5fd2 |
-
|
|
rdobuilder |
3e5fd2 |
+
|
|
rdobuilder |
3e5fd2 |
e.append(pydot.Edge(n_prev, name_port, **attrs))
|
|
rdobuilder |
3e5fd2 |
|
|
rdobuilder |
3e5fd2 |
elif isinstance(toks[2][0], type('')):
|
|
rdobuilder |
3e5fd2 |
-
|
|
rdobuilder |
3e5fd2 |
for n_next in [n for n in tuple(toks)[2::2]]:
|
|
rdobuilder |
3e5fd2 |
-
|
|
rdobuilder |
3e5fd2 |
if isinstance(n_next, P_AttrList) or not isinstance(n_next[0], type('')):
|
|
rdobuilder |
3e5fd2 |
continue
|
|
rdobuilder |
3e5fd2 |
|
|
rdobuilder |
3e5fd2 |
- n_next_port = do_node_ports( n_next )
|
|
rdobuilder |
3e5fd2 |
- e.append(pydot.Edge(n_prev, n_next[0]+n_next_port, **attrs))
|
|
rdobuilder |
3e5fd2 |
-
|
|
rdobuilder |
3e5fd2 |
- n_prev = n_next[0]+n_next_port
|
|
rdobuilder |
3e5fd2 |
-
|
|
rdobuilder |
3e5fd2 |
+ n_next_port = do_node_ports(n_next)
|
|
rdobuilder |
3e5fd2 |
+ e.append(pydot.Edge(n_prev, n_next[0] + n_next_port, **attrs))
|
|
rdobuilder |
3e5fd2 |
+
|
|
rdobuilder |
3e5fd2 |
+ n_prev = n_next[0] + n_next_port
|
|
rdobuilder |
3e5fd2 |
+
|
|
rdobuilder |
3e5fd2 |
else:
|
|
rdobuilder |
3e5fd2 |
# UNEXPECTED EDGE TYPE
|
|
rdobuilder |
3e5fd2 |
pass
|
|
rdobuilder |
3e5fd2 |
-
|
|
rdobuilder |
3e5fd2 |
- return e
|
|
rdobuilder |
3e5fd2 |
|
|
rdobuilder |
3e5fd2 |
+ return e
|
|
rdobuilder |
3e5fd2 |
|
|
rdobuilder |
3e5fd2 |
|
|
rdobuilder |
3e5fd2 |
def push_node_stmt(s, loc, toks):
|
|
rdobuilder |
3e5fd2 |
@@ -359,30 +325,25 @@ def push_node_stmt(s, loc, toks):
|
|
rdobuilder |
3e5fd2 |
attrs = toks[1].attrs
|
|
rdobuilder |
3e5fd2 |
else:
|
|
rdobuilder |
3e5fd2 |
attrs = {}
|
|
rdobuilder |
3e5fd2 |
-
|
|
rdobuilder |
3e5fd2 |
+
|
|
rdobuilder |
3e5fd2 |
node_name = toks[0]
|
|
rdobuilder |
3e5fd2 |
if isinstance(node_name, list) or isinstance(node_name, tuple):
|
|
rdobuilder |
3e5fd2 |
- if len(node_name)>0:
|
|
rdobuilder |
3e5fd2 |
+ if len(node_name) > 0:
|
|
rdobuilder |
3e5fd2 |
node_name = node_name[0]
|
|
rdobuilder |
3e5fd2 |
-
|
|
rdobuilder |
3e5fd2 |
+
|
|
rdobuilder |
3e5fd2 |
n = pydot.Node(str(node_name), **attrs)
|
|
rdobuilder |
3e5fd2 |
return n
|
|
rdobuilder |
3e5fd2 |
|
|
rdobuilder |
3e5fd2 |
|
|
rdobuilder |
3e5fd2 |
-
|
|
rdobuilder |
3e5fd2 |
-
|
|
rdobuilder |
3e5fd2 |
-
|
|
rdobuilder |
3e5fd2 |
-
|
|
rdobuilder |
3e5fd2 |
graphparser = None
|
|
rdobuilder |
3e5fd2 |
|
|
rdobuilder |
3e5fd2 |
-def graph_definition():
|
|
rdobuilder |
3e5fd2 |
|
|
rdobuilder |
3e5fd2 |
+def graph_definition():
|
|
rdobuilder |
3e5fd2 |
global graphparser
|
|
rdobuilder |
3e5fd2 |
-
|
|
rdobuilder |
3e5fd2 |
+
|
|
rdobuilder |
3e5fd2 |
if not graphparser:
|
|
rdobuilder |
3e5fd2 |
-
|
|
rdobuilder |
3e5fd2 |
# punctuation
|
|
rdobuilder |
3e5fd2 |
- colon = Literal(":")
|
|
rdobuilder |
3e5fd2 |
+ colon = Literal(":")
|
|
rdobuilder |
3e5fd2 |
lbrace = Literal("{")
|
|
rdobuilder |
3e5fd2 |
rbrace = Literal("}")
|
|
rdobuilder |
3e5fd2 |
lbrack = Literal("[")
|
|
rdobuilder |
3e5fd2 |
@@ -390,142 +351,170 @@ def graph_definition():
|
|
rdobuilder |
3e5fd2 |
lparen = Literal("(")
|
|
rdobuilder |
3e5fd2 |
rparen = Literal(")")
|
|
rdobuilder |
3e5fd2 |
equals = Literal("=")
|
|
rdobuilder |
3e5fd2 |
- comma = Literal(",")
|
|
rdobuilder |
3e5fd2 |
- dot = Literal(".")
|
|
rdobuilder |
3e5fd2 |
- slash = Literal("/")
|
|
rdobuilder |
3e5fd2 |
- bslash = Literal("\\")
|
|
rdobuilder |
3e5fd2 |
- star = Literal("*")
|
|
rdobuilder |
3e5fd2 |
- semi = Literal(";")
|
|
rdobuilder |
3e5fd2 |
- at = Literal("@")
|
|
rdobuilder |
3e5fd2 |
- minus = Literal("-")
|
|
rdobuilder |
3e5fd2 |
-
|
|
rdobuilder |
3e5fd2 |
+ comma = Literal(",")
|
|
rdobuilder |
3e5fd2 |
+ # dot = Literal(".")
|
|
rdobuilder |
3e5fd2 |
+ # slash = Literal("/")
|
|
rdobuilder |
3e5fd2 |
+ # bslash = Literal("\\")
|
|
rdobuilder |
3e5fd2 |
+ # star = Literal("*")
|
|
rdobuilder |
3e5fd2 |
+ semi = Literal(";")
|
|
rdobuilder |
3e5fd2 |
+ at = Literal("@")
|
|
rdobuilder |
3e5fd2 |
+ minus = Literal("-")
|
|
rdobuilder |
3e5fd2 |
+
|
|
rdobuilder |
3e5fd2 |
# keywords
|
|
rdobuilder |
3e5fd2 |
- strict_ = CaselessLiteral("strict")
|
|
rdobuilder |
3e5fd2 |
- graph_ = CaselessLiteral("graph")
|
|
rdobuilder |
3e5fd2 |
- digraph_ = CaselessLiteral("digraph")
|
|
rdobuilder |
3e5fd2 |
- subgraph_ = CaselessLiteral("subgraph")
|
|
rdobuilder |
3e5fd2 |
- node_ = CaselessLiteral("node")
|
|
rdobuilder |
3e5fd2 |
- edge_ = CaselessLiteral("edge")
|
|
rdobuilder |
3e5fd2 |
-
|
|
rdobuilder |
3e5fd2 |
-
|
|
rdobuilder |
3e5fd2 |
+ strict_ = CaselessLiteral("strict")
|
|
rdobuilder |
3e5fd2 |
+ graph_ = CaselessLiteral("graph")
|
|
rdobuilder |
3e5fd2 |
+ digraph_ = CaselessLiteral("digraph")
|
|
rdobuilder |
3e5fd2 |
+ subgraph_ = CaselessLiteral("subgraph")
|
|
rdobuilder |
3e5fd2 |
+ node_ = CaselessLiteral("node")
|
|
rdobuilder |
3e5fd2 |
+ edge_ = CaselessLiteral("edge")
|
|
rdobuilder |
3e5fd2 |
+
|
|
rdobuilder |
3e5fd2 |
# token definitions
|
|
rdobuilder |
3e5fd2 |
-
|
|
rdobuilder |
3e5fd2 |
- identifier = Word(alphanums + "_." ).setName("identifier")
|
|
rdobuilder |
3e5fd2 |
-
|
|
rdobuilder |
3e5fd2 |
- double_quoted_string = QuotedString('"', multiline=True, unquoteResults=False) # dblQuotedString
|
|
rdobuilder |
3e5fd2 |
+ identifier = Word(alphanums + "_.").setName("identifier")
|
|
rdobuilder |
3e5fd2 |
+
|
|
rdobuilder |
3e5fd2 |
+ # dblQuotedString
|
|
rdobuilder |
3e5fd2 |
+ double_quoted_string = QuotedString('"', multiline=True, unquoteResults=False)
|
|
rdobuilder |
3e5fd2 |
|
|
rdobuilder |
3e5fd2 |
- alphastring_ = OneOrMore(CharsNotIn(_noncomma + ' '))
|
|
rdobuilder |
3e5fd2 |
+ noncomma_ = "".join([c for c in printables if c != ","])
|
|
rdobuilder |
3e5fd2 |
+ alphastring_ = OneOrMore(CharsNotIn(noncomma_ + ' '))
|
|
rdobuilder |
3e5fd2 |
|
|
rdobuilder |
3e5fd2 |
def parse_html(s, loc, toks):
|
|
rdobuilder |
3e5fd2 |
return '<%s>' % ''.join(toks[0])
|
|
rdobuilder |
3e5fd2 |
-
|
|
rdobuilder |
3e5fd2 |
-
|
|
rdobuilder |
3e5fd2 |
+
|
|
rdobuilder |
3e5fd2 |
opener = '<'
|
|
rdobuilder |
3e5fd2 |
closer = '>'
|
|
rdobuilder |
3e5fd2 |
- html_text = nestedExpr( opener, closer,
|
|
rdobuilder |
3e5fd2 |
- ( CharsNotIn( opener + closer ) )
|
|
rdobuilder |
3e5fd2 |
- ).setParseAction(parse_html).leaveWhitespace()
|
|
rdobuilder |
3e5fd2 |
-
|
|
rdobuilder |
3e5fd2 |
- ID = ( identifier | html_text |
|
|
rdobuilder |
3e5fd2 |
- double_quoted_string | #.setParseAction(strip_quotes) |
|
|
rdobuilder |
3e5fd2 |
- alphastring_ ).setName("ID")
|
|
rdobuilder |
3e5fd2 |
-
|
|
rdobuilder |
3e5fd2 |
-
|
|
rdobuilder |
3e5fd2 |
- float_number = Combine(Optional(minus) +
|
|
rdobuilder |
3e5fd2 |
- OneOrMore(Word(nums + "."))).setName("float_number")
|
|
rdobuilder |
3e5fd2 |
-
|
|
rdobuilder |
3e5fd2 |
- righthand_id = (float_number | ID ).setName("righthand_id")
|
|
rdobuilder |
3e5fd2 |
+ html_text = nestedExpr(
|
|
rdobuilder |
3e5fd2 |
+ opener, closer,
|
|
rdobuilder |
3e5fd2 |
+ (CharsNotIn(opener + closer))
|
|
rdobuilder |
3e5fd2 |
+ ).setParseAction(parse_html).leaveWhitespace()
|
|
rdobuilder |
3e5fd2 |
+
|
|
rdobuilder |
3e5fd2 |
+ ID = (
|
|
rdobuilder |
3e5fd2 |
+ identifier | html_text |
|
|
rdobuilder |
3e5fd2 |
+ double_quoted_string | # .setParseAction(strip_quotes) |
|
|
rdobuilder |
3e5fd2 |
+ alphastring_
|
|
rdobuilder |
3e5fd2 |
+ ).setName("ID")
|
|
rdobuilder |
3e5fd2 |
+
|
|
rdobuilder |
3e5fd2 |
+ float_number = Combine(
|
|
rdobuilder |
3e5fd2 |
+ Optional(minus) +
|
|
rdobuilder |
3e5fd2 |
+ OneOrMore(Word(nums + "."))
|
|
rdobuilder |
3e5fd2 |
+ ).setName("float_number")
|
|
rdobuilder |
3e5fd2 |
+
|
|
rdobuilder |
3e5fd2 |
+ righthand_id = (float_number | ID).setName("righthand_id")
|
|
rdobuilder |
3e5fd2 |
|
|
rdobuilder |
3e5fd2 |
port_angle = (at + ID).setName("port_angle")
|
|
rdobuilder |
3e5fd2 |
-
|
|
rdobuilder |
3e5fd2 |
- port_location = (OneOrMore(Group(colon + ID)) |
|
|
rdobuilder |
3e5fd2 |
- Group(colon + lparen + ID + comma + ID + rparen)).setName("port_location")
|
|
rdobuilder |
3e5fd2 |
-
|
|
rdobuilder |
3e5fd2 |
- port = (Group(port_location + Optional(port_angle)) |
|
|
rdobuilder |
3e5fd2 |
- Group(port_angle + Optional(port_location))).setName("port")
|
|
rdobuilder |
3e5fd2 |
-
|
|
rdobuilder |
3e5fd2 |
+
|
|
rdobuilder |
3e5fd2 |
+ port_location = (
|
|
rdobuilder |
3e5fd2 |
+ OneOrMore(Group(colon + ID)) |
|
|
rdobuilder |
3e5fd2 |
+ Group(colon + lparen + ID + comma + ID + rparen)
|
|
rdobuilder |
3e5fd2 |
+ ).setName("port_location")
|
|
rdobuilder |
3e5fd2 |
+
|
|
rdobuilder |
3e5fd2 |
+ port = (
|
|
rdobuilder |
3e5fd2 |
+ Group(port_location + Optional(port_angle)) |
|
|
rdobuilder |
3e5fd2 |
+ Group(port_angle + Optional(port_location))
|
|
rdobuilder |
3e5fd2 |
+ ).setName("port")
|
|
rdobuilder |
3e5fd2 |
+
|
|
rdobuilder |
3e5fd2 |
node_id = (ID + Optional(port))
|
|
rdobuilder |
3e5fd2 |
- a_list = OneOrMore(ID + Optional(equals + righthand_id) +
|
|
rdobuilder |
3e5fd2 |
- Optional(comma.suppress())).setName("a_list")
|
|
rdobuilder |
3e5fd2 |
-
|
|
rdobuilder |
3e5fd2 |
- attr_list = OneOrMore(lbrack.suppress() + Optional(a_list) +
|
|
rdobuilder |
3e5fd2 |
- rbrack.suppress()).setName("attr_list")
|
|
rdobuilder |
3e5fd2 |
-
|
|
rdobuilder |
3e5fd2 |
+ a_list = OneOrMore(
|
|
rdobuilder |
3e5fd2 |
+ ID + Optional(equals + righthand_id) + Optional(comma.suppress())
|
|
rdobuilder |
3e5fd2 |
+ ).setName("a_list")
|
|
rdobuilder |
3e5fd2 |
+
|
|
rdobuilder |
3e5fd2 |
+ attr_list = OneOrMore(
|
|
rdobuilder |
3e5fd2 |
+ lbrack.suppress() + Optional(a_list) + rbrack.suppress()
|
|
rdobuilder |
3e5fd2 |
+ ).setName("attr_list")
|
|
rdobuilder |
3e5fd2 |
+
|
|
rdobuilder |
3e5fd2 |
attr_stmt = (Group(graph_ | node_ | edge_) + attr_list).setName("attr_stmt")
|
|
rdobuilder |
3e5fd2 |
-
|
|
rdobuilder |
3e5fd2 |
+
|
|
rdobuilder |
3e5fd2 |
edgeop = (Literal("--") | Literal("->")).setName("edgeop")
|
|
rdobuilder |
3e5fd2 |
-
|
|
rdobuilder |
3e5fd2 |
+
|
|
rdobuilder |
3e5fd2 |
stmt_list = Forward()
|
|
rdobuilder |
3e5fd2 |
- graph_stmt = Group(lbrace.suppress() + Optional(stmt_list) +
|
|
rdobuilder |
3e5fd2 |
- rbrace.suppress() + Optional(semi.suppress()) ).setName("graph_stmt")
|
|
rdobuilder |
3e5fd2 |
-
|
|
rdobuilder |
3e5fd2 |
-
|
|
rdobuilder |
3e5fd2 |
+ graph_stmt = Group(
|
|
rdobuilder |
3e5fd2 |
+ lbrace.suppress() + Optional(stmt_list) +
|
|
rdobuilder |
3e5fd2 |
+ rbrace.suppress() + Optional(semi.suppress())
|
|
rdobuilder |
3e5fd2 |
+ ).setName("graph_stmt")
|
|
rdobuilder |
3e5fd2 |
+
|
|
rdobuilder |
3e5fd2 |
edge_point = Forward()
|
|
rdobuilder |
3e5fd2 |
-
|
|
rdobuilder |
3e5fd2 |
+
|
|
rdobuilder |
3e5fd2 |
edgeRHS = OneOrMore(edgeop + edge_point)
|
|
rdobuilder |
3e5fd2 |
edge_stmt = edge_point + edgeRHS + Optional(attr_list)
|
|
rdobuilder |
3e5fd2 |
-
|
|
rdobuilder |
3e5fd2 |
+
|
|
rdobuilder |
3e5fd2 |
subgraph = Group(subgraph_ + Optional(ID) + graph_stmt).setName("subgraph")
|
|
rdobuilder |
3e5fd2 |
-
|
|
rdobuilder |
3e5fd2 |
- edge_point << Group( subgraph | graph_stmt | node_id ).setName('edge_point')
|
|
rdobuilder |
3e5fd2 |
-
|
|
rdobuilder |
3e5fd2 |
- node_stmt = (node_id + Optional(attr_list) + Optional(semi.suppress())).setName("node_stmt")
|
|
rdobuilder |
3e5fd2 |
-
|
|
rdobuilder |
3e5fd2 |
+
|
|
rdobuilder |
3e5fd2 |
+ edge_point << Group(subgraph | graph_stmt | node_id).setName('edge_point')
|
|
rdobuilder |
3e5fd2 |
+
|
|
rdobuilder |
3e5fd2 |
+ node_stmt = (
|
|
rdobuilder |
3e5fd2 |
+ node_id + Optional(attr_list) + Optional(semi.suppress())
|
|
rdobuilder |
3e5fd2 |
+ ).setName("node_stmt")
|
|
rdobuilder |
3e5fd2 |
+
|
|
rdobuilder |
3e5fd2 |
assignment = (ID + equals + righthand_id).setName("assignment")
|
|
rdobuilder |
3e5fd2 |
- stmt = (assignment | edge_stmt | attr_stmt | subgraph | graph_stmt | node_stmt).setName("stmt")
|
|
rdobuilder |
3e5fd2 |
+ stmt = (
|
|
rdobuilder |
3e5fd2 |
+ assignment | edge_stmt | attr_stmt |
|
|
rdobuilder |
3e5fd2 |
+ subgraph | graph_stmt | node_stmt
|
|
rdobuilder |
3e5fd2 |
+ ).setName("stmt")
|
|
rdobuilder |
3e5fd2 |
stmt_list << OneOrMore(stmt + Optional(semi.suppress()))
|
|
rdobuilder |
3e5fd2 |
-
|
|
rdobuilder |
3e5fd2 |
- graphparser = OneOrMore( (Optional(strict_) + Group((graph_ | digraph_)) +
|
|
rdobuilder |
3e5fd2 |
- Optional(ID) + graph_stmt).setResultsName("graph") )
|
|
rdobuilder |
3e5fd2 |
-
|
|
rdobuilder |
3e5fd2 |
+
|
|
rdobuilder |
3e5fd2 |
+ graphparser = OneOrMore((
|
|
rdobuilder |
3e5fd2 |
+ Optional(strict_) + Group((graph_ | digraph_)) +
|
|
rdobuilder |
3e5fd2 |
+ Optional(ID) + graph_stmt
|
|
rdobuilder |
3e5fd2 |
+ ).setResultsName("graph"))
|
|
rdobuilder |
3e5fd2 |
+
|
|
rdobuilder |
3e5fd2 |
singleLineComment = Group("//" + restOfLine) | Group("#" + restOfLine)
|
|
rdobuilder |
3e5fd2 |
-
|
|
rdobuilder |
3e5fd2 |
-
|
|
rdobuilder |
3e5fd2 |
+
|
|
rdobuilder |
3e5fd2 |
# actions
|
|
rdobuilder |
3e5fd2 |
-
|
|
rdobuilder |
3e5fd2 |
graphparser.ignore(singleLineComment)
|
|
rdobuilder |
3e5fd2 |
graphparser.ignore(cStyleComment)
|
|
rdobuilder |
3e5fd2 |
-
|
|
rdobuilder |
3e5fd2 |
+
|
|
rdobuilder |
3e5fd2 |
assignment.setParseAction(push_attr_list)
|
|
rdobuilder |
3e5fd2 |
a_list.setParseAction(push_attr_list)
|
|
rdobuilder |
3e5fd2 |
edge_stmt.setParseAction(push_edge_stmt)
|
|
rdobuilder |
3e5fd2 |
node_stmt.setParseAction(push_node_stmt)
|
|
rdobuilder |
3e5fd2 |
attr_stmt.setParseAction(push_default_stmt)
|
|
rdobuilder |
3e5fd2 |
-
|
|
rdobuilder |
3e5fd2 |
+
|
|
rdobuilder |
3e5fd2 |
subgraph.setParseAction(push_subgraph_stmt)
|
|
rdobuilder |
3e5fd2 |
graph_stmt.setParseAction(push_graph_stmt)
|
|
rdobuilder |
3e5fd2 |
graphparser.setParseAction(push_top_graph_stmt)
|
|
rdobuilder |
3e5fd2 |
-
|
|
rdobuilder |
3e5fd2 |
-
|
|
rdobuilder |
3e5fd2 |
+
|
|
rdobuilder |
3e5fd2 |
return graphparser
|
|
rdobuilder |
3e5fd2 |
|
|
rdobuilder |
3e5fd2 |
|
|
rdobuilder |
3e5fd2 |
def parse_dot_data(data):
|
|
rdobuilder |
3e5fd2 |
-
|
|
rdobuilder |
3e5fd2 |
global top_graphs
|
|
rdobuilder |
3e5fd2 |
-
|
|
rdobuilder |
3e5fd2 |
+
|
|
rdobuilder |
3e5fd2 |
top_graphs = list()
|
|
rdobuilder |
3e5fd2 |
|
|
rdobuilder |
3e5fd2 |
- if data.startswith(codecs.BOM_UTF8):
|
|
rdobuilder |
3e5fd2 |
- data = data.decode( 'utf-8' )
|
|
rdobuilder |
3e5fd2 |
-
|
|
rdobuilder |
3e5fd2 |
+ if PY3:
|
|
rdobuilder |
3e5fd2 |
+ if isinstance(data, bytes):
|
|
rdobuilder |
3e5fd2 |
+ # this is extremely hackish
|
|
rdobuilder |
3e5fd2 |
+ try:
|
|
rdobuilder |
3e5fd2 |
+ idx = data.index(b'charset') + 7
|
|
rdobuilder |
3e5fd2 |
+ while data[idx] in b' \t\n\r=':
|
|
rdobuilder |
3e5fd2 |
+ idx += 1
|
|
rdobuilder |
3e5fd2 |
+ fst = idx
|
|
rdobuilder |
3e5fd2 |
+ while data[idx] not in b' \t\n\r];,':
|
|
rdobuilder |
3e5fd2 |
+ idx += 1
|
|
rdobuilder |
3e5fd2 |
+ charset = data[fst:idx].strip(b'"\'').decode('ascii')
|
|
rdobuilder |
3e5fd2 |
+ data = data.decode(charset)
|
|
rdobuilder |
3e5fd2 |
+ except:
|
|
rdobuilder |
3e5fd2 |
+ data = data.decode('utf-8')
|
|
rdobuilder |
3e5fd2 |
+ else:
|
|
rdobuilder |
3e5fd2 |
+ if data.startswith(codecs.BOM_UTF8):
|
|
rdobuilder |
3e5fd2 |
+ data = data.decode('utf-8')
|
|
rdobuilder |
3e5fd2 |
+
|
|
rdobuilder |
3e5fd2 |
try:
|
|
rdobuilder |
3e5fd2 |
-
|
|
rdobuilder |
3e5fd2 |
+
|
|
rdobuilder |
3e5fd2 |
graphparser = graph_definition()
|
|
rdobuilder |
3e5fd2 |
-
|
|
rdobuilder |
3e5fd2 |
+
|
|
rdobuilder |
3e5fd2 |
if pyparsing_version >= '1.2':
|
|
rdobuilder |
3e5fd2 |
graphparser.parseWithTabs()
|
|
rdobuilder |
3e5fd2 |
-
|
|
rdobuilder |
3e5fd2 |
+
|
|
rdobuilder |
3e5fd2 |
tokens = graphparser.parseString(data)
|
|
rdobuilder |
3e5fd2 |
|
|
rdobuilder |
3e5fd2 |
if len(tokens) == 1:
|
|
rdobuilder |
3e5fd2 |
return tokens[0]
|
|
rdobuilder |
3e5fd2 |
else:
|
|
rdobuilder |
3e5fd2 |
return [g for g in tokens]
|
|
rdobuilder |
3e5fd2 |
-
|
|
rdobuilder |
3e5fd2 |
- except ParseException, err:
|
|
rdobuilder |
3e5fd2 |
-
|
|
rdobuilder |
3e5fd2 |
- print err.line
|
|
rdobuilder |
3e5fd2 |
- print " "*(err.column-1) + "^"
|
|
rdobuilder |
3e5fd2 |
- print err
|
|
rdobuilder |
3e5fd2 |
+
|
|
rdobuilder |
3e5fd2 |
+ except ParseException:
|
|
rdobuilder |
3e5fd2 |
+ err = sys.exc_info()[1]
|
|
rdobuilder |
3e5fd2 |
+ print(err.line)
|
|
rdobuilder |
3e5fd2 |
+ print(" " * (err.column - 1) + "^")
|
|
rdobuilder |
3e5fd2 |
+ print(err)
|
|
rdobuilder |
3e5fd2 |
return None
|
|
rdobuilder |
3e5fd2 |
diff --git a/pydot.py b/pydot.py
|
|
rdobuilder |
3e5fd2 |
index e9bd2a1..c20db18 100644
|
|
rdobuilder |
3e5fd2 |
--- a/pydot.py
|
|
rdobuilder |
3e5fd2 |
+++ b/pydot.py
|
|
rdobuilder |
3e5fd2 |
@@ -17,24 +17,40 @@ Copyright (c) 2005-2011 Ero Carrera <ero.carrera@gmail.com>
|
|
rdobuilder |
3e5fd2 |
Distributed under MIT license [http://opensource.org/licenses/mit-license.html].
|
|
rdobuilder |
3e5fd2 |
"""
|
|
rdobuilder |
3e5fd2 |
|
|
rdobuilder |
3e5fd2 |
-__revision__ = "$LastChangedRevision: 28 $"
|
|
rdobuilder |
3e5fd2 |
+from __future__ import division, print_function
|
|
rdobuilder |
3e5fd2 |
+
|
|
rdobuilder |
3e5fd2 |
__author__ = 'Ero Carrera'
|
|
rdobuilder |
3e5fd2 |
-__version__ = '1.0.%d' % int( __revision__[21:-2] )
|
|
rdobuilder |
3e5fd2 |
+__version__ = '1.0.29'
|
|
rdobuilder |
3e5fd2 |
__license__ = 'MIT'
|
|
rdobuilder |
3e5fd2 |
|
|
rdobuilder |
3e5fd2 |
import os
|
|
rdobuilder |
3e5fd2 |
import re
|
|
rdobuilder |
3e5fd2 |
import subprocess
|
|
rdobuilder |
3e5fd2 |
+import sys
|
|
rdobuilder |
3e5fd2 |
import tempfile
|
|
rdobuilder |
3e5fd2 |
import copy
|
|
rdobuilder |
3e5fd2 |
+
|
|
rdobuilder |
3e5fd2 |
+from operator import itemgetter
|
|
rdobuilder |
3e5fd2 |
+
|
|
rdobuilder |
3e5fd2 |
try:
|
|
rdobuilder |
3e5fd2 |
import dot_parser
|
|
rdobuilder |
3e5fd2 |
-except Exception, e:
|
|
rdobuilder |
3e5fd2 |
- print "Couldn't import dot_parser, loading of dot files will not be possible."
|
|
rdobuilder |
3e5fd2 |
-
|
|
rdobuilder |
3e5fd2 |
+except Exception:
|
|
rdobuilder |
3e5fd2 |
+ print("Couldn't import dot_parser, loading of dot files will not be possible.")
|
|
rdobuilder |
3e5fd2 |
+
|
|
rdobuilder |
3e5fd2 |
|
|
rdobuilder |
3e5fd2 |
+PY3 = not sys.version_info < (3, 0, 0)
|
|
rdobuilder |
3e5fd2 |
|
|
rdobuilder |
3e5fd2 |
-GRAPH_ATTRIBUTES = set( ['Damping', 'K', 'URL', 'aspect', 'bb', 'bgcolor',
|
|
rdobuilder |
3e5fd2 |
+if PY3:
|
|
rdobuilder |
3e5fd2 |
+ NULL_SEP = b''
|
|
rdobuilder |
3e5fd2 |
+ basestring = str
|
|
rdobuilder |
3e5fd2 |
+ long = int
|
|
rdobuilder |
3e5fd2 |
+ unicode = str
|
|
rdobuilder |
3e5fd2 |
+else:
|
|
rdobuilder |
3e5fd2 |
+ NULL_SEP = ''
|
|
rdobuilder |
3e5fd2 |
+
|
|
rdobuilder |
3e5fd2 |
+
|
|
rdobuilder |
3e5fd2 |
+GRAPH_ATTRIBUTES = set([
|
|
rdobuilder |
3e5fd2 |
+ 'Damping', 'K', 'URL', 'aspect', 'bb', 'bgcolor',
|
|
rdobuilder |
3e5fd2 |
'center', 'charset', 'clusterrank', 'colorscheme', 'comment', 'compound',
|
|
rdobuilder |
3e5fd2 |
'concentrate', 'defaultdist', 'dim', 'dimen', 'diredgeconstraints',
|
|
rdobuilder |
3e5fd2 |
'dpi', 'epsilon', 'esep', 'fontcolor', 'fontname', 'fontnames',
|
|
rdobuilder |
3e5fd2 |
@@ -46,13 +62,15 @@ GRAPH_ATTRIBUTES = set( ['Damping', 'K', 'URL', 'aspect', 'bb', 'bgcolor',
|
|
rdobuilder |
3e5fd2 |
'overlap_scaling', 'pack', 'packmode', 'pad', 'page', 'pagedir',
|
|
rdobuilder |
3e5fd2 |
'quadtree', 'quantum', 'rankdir', 'ranksep', 'ratio', 'remincross',
|
|
rdobuilder |
3e5fd2 |
'repulsiveforce', 'resolution', 'root', 'rotate', 'searchsize', 'sep',
|
|
rdobuilder |
3e5fd2 |
- 'showboxes', 'size', 'smoothing', 'sortv', 'splines', 'start',
|
|
rdobuilder |
3e5fd2 |
+ 'showboxes', 'size', 'smoothing', 'sortv', 'splines', 'start',
|
|
rdobuilder |
3e5fd2 |
'stylesheet', 'target', 'truecolor', 'viewport', 'voro_margin',
|
|
rdobuilder |
3e5fd2 |
- # for subgraphs
|
|
rdobuilder |
3e5fd2 |
- 'rank' ] )
|
|
rdobuilder |
3e5fd2 |
+ # for subgraphs
|
|
rdobuilder |
3e5fd2 |
+ 'rank'
|
|
rdobuilder |
3e5fd2 |
+ ])
|
|
rdobuilder |
3e5fd2 |
|
|
rdobuilder |
3e5fd2 |
|
|
rdobuilder |
3e5fd2 |
-EDGE_ATTRIBUTES = set( ['URL', 'arrowhead', 'arrowsize', 'arrowtail',
|
|
rdobuilder |
3e5fd2 |
+EDGE_ATTRIBUTES = set([
|
|
rdobuilder |
3e5fd2 |
+ 'URL', 'arrowhead', 'arrowsize', 'arrowtail',
|
|
rdobuilder |
3e5fd2 |
'color', 'colorscheme', 'comment', 'constraint', 'decorate', 'dir',
|
|
rdobuilder |
3e5fd2 |
'edgeURL', 'edgehref', 'edgetarget', 'edgetooltip', 'fontcolor',
|
|
rdobuilder |
3e5fd2 |
'fontname', 'fontsize', 'headURL', 'headclip', 'headhref', 'headlabel',
|
|
rdobuilder |
3e5fd2 |
@@ -63,10 +81,12 @@ EDGE_ATTRIBUTES = set( ['URL', 'arrowhead', 'arrowsize', 'arrowtail',
|
|
rdobuilder |
3e5fd2 |
'nojustify', 'penwidth', 'pos', 'samehead', 'sametail', 'showboxes',
|
|
rdobuilder |
3e5fd2 |
'style', 'tailURL', 'tailclip', 'tailhref', 'taillabel', 'tailport',
|
|
rdobuilder |
3e5fd2 |
'tailtarget', 'tailtooltip', 'target', 'tooltip', 'weight',
|
|
rdobuilder |
3e5fd2 |
- 'rank' ] )
|
|
rdobuilder |
3e5fd2 |
+ 'rank'
|
|
rdobuilder |
3e5fd2 |
+ ])
|
|
rdobuilder |
3e5fd2 |
|
|
rdobuilder |
3e5fd2 |
|
|
rdobuilder |
3e5fd2 |
-NODE_ATTRIBUTES = set( ['URL', 'color', 'colorscheme', 'comment',
|
|
rdobuilder |
3e5fd2 |
+NODE_ATTRIBUTES = set([
|
|
rdobuilder |
3e5fd2 |
+ 'URL', 'color', 'colorscheme', 'comment',
|
|
rdobuilder |
3e5fd2 |
'distortion', 'fillcolor', 'fixedsize', 'fontcolor', 'fontname',
|
|
rdobuilder |
3e5fd2 |
'fontsize', 'group', 'height', 'id', 'image', 'imagescale', 'label',
|
|
rdobuilder |
3e5fd2 |
'labelloc', 'layer', 'margin', 'nojustify', 'orientation', 'penwidth',
|
|
rdobuilder |
3e5fd2 |
@@ -74,14 +94,62 @@ NODE_ATTRIBUTES = set( ['URL', 'color', 'colorscheme', 'comment',
|
|
rdobuilder |
3e5fd2 |
'shape', 'shapefile', 'showboxes', 'sides', 'skew', 'sortv', 'style',
|
|
rdobuilder |
3e5fd2 |
'target', 'tooltip', 'vertices', 'width', 'z',
|
|
rdobuilder |
3e5fd2 |
# The following are attributes dot2tex
|
|
rdobuilder |
3e5fd2 |
- 'texlbl', 'texmode' ] )
|
|
rdobuilder |
3e5fd2 |
+ 'texlbl', 'texmode'
|
|
rdobuilder |
3e5fd2 |
+ ])
|
|
rdobuilder |
3e5fd2 |
|
|
rdobuilder |
3e5fd2 |
|
|
rdobuilder |
3e5fd2 |
-CLUSTER_ATTRIBUTES = set( ['K', 'URL', 'bgcolor', 'color', 'colorscheme',
|
|
rdobuilder |
3e5fd2 |
+CLUSTER_ATTRIBUTES = set([
|
|
rdobuilder |
3e5fd2 |
+ 'K', 'URL', 'bgcolor', 'color', 'colorscheme',
|
|
rdobuilder |
3e5fd2 |
'fillcolor', 'fontcolor', 'fontname', 'fontsize', 'label', 'labeljust',
|
|
rdobuilder |
3e5fd2 |
'labelloc', 'lheight', 'lp', 'lwidth', 'nojustify', 'pencolor',
|
|
rdobuilder |
3e5fd2 |
- 'penwidth', 'peripheries', 'sortv', 'style', 'target', 'tooltip'] )
|
|
rdobuilder |
3e5fd2 |
-
|
|
rdobuilder |
3e5fd2 |
+ 'penwidth', 'peripheries', 'sortv', 'style', 'target', 'tooltip'
|
|
rdobuilder |
3e5fd2 |
+ ])
|
|
rdobuilder |
3e5fd2 |
+
|
|
rdobuilder |
3e5fd2 |
+
|
|
rdobuilder |
3e5fd2 |
+def is_string_like(obj): # from John Hunter, types-free version
|
|
rdobuilder |
3e5fd2 |
+ """Check if obj is string."""
|
|
rdobuilder |
3e5fd2 |
+ try:
|
|
rdobuilder |
3e5fd2 |
+ obj + ''
|
|
rdobuilder |
3e5fd2 |
+ except (TypeError, ValueError):
|
|
rdobuilder |
3e5fd2 |
+ return False
|
|
rdobuilder |
3e5fd2 |
+ return True
|
|
rdobuilder |
3e5fd2 |
+
|
|
rdobuilder |
3e5fd2 |
+def get_fobj(fname, mode='w+'):
|
|
rdobuilder |
3e5fd2 |
+ """Obtain a proper file object.
|
|
rdobuilder |
3e5fd2 |
+
|
|
rdobuilder |
3e5fd2 |
+ Parameters
|
|
rdobuilder |
3e5fd2 |
+ ----------
|
|
rdobuilder |
3e5fd2 |
+ fname : string, file object, file descriptor
|
|
rdobuilder |
3e5fd2 |
+ If a string or file descriptor, then we create a file object. If *fname*
|
|
rdobuilder |
3e5fd2 |
+ is a file object, then we do nothing and ignore the specified *mode*
|
|
rdobuilder |
3e5fd2 |
+ parameter.
|
|
rdobuilder |
3e5fd2 |
+ mode : str
|
|
rdobuilder |
3e5fd2 |
+ The mode of the file to be opened.
|
|
rdobuilder |
3e5fd2 |
+
|
|
rdobuilder |
3e5fd2 |
+ Returns
|
|
rdobuilder |
3e5fd2 |
+ -------
|
|
rdobuilder |
3e5fd2 |
+ fobj : file object
|
|
rdobuilder |
3e5fd2 |
+ The file object.
|
|
rdobuilder |
3e5fd2 |
+ close : bool
|
|
rdobuilder |
3e5fd2 |
+ If *fname* was a string, then *close* will be *True* to signify that
|
|
rdobuilder |
3e5fd2 |
+ the file object should be closed after writing to it. Otherwise, *close*
|
|
rdobuilder |
3e5fd2 |
+ will be *False* signifying that the user, in essence, created the file
|
|
rdobuilder |
3e5fd2 |
+ object already and that subsequent operations should not close it.
|
|
rdobuilder |
3e5fd2 |
+
|
|
rdobuilder |
3e5fd2 |
+ """
|
|
rdobuilder |
3e5fd2 |
+ if is_string_like(fname):
|
|
rdobuilder |
3e5fd2 |
+ fobj = open(fname, mode)
|
|
rdobuilder |
3e5fd2 |
+ close = True
|
|
rdobuilder |
3e5fd2 |
+ elif hasattr(fname, 'write'):
|
|
rdobuilder |
3e5fd2 |
+ # fname is a file-like object, perhaps a StringIO (for example)
|
|
rdobuilder |
3e5fd2 |
+ fobj = fname
|
|
rdobuilder |
3e5fd2 |
+ close = False
|
|
rdobuilder |
3e5fd2 |
+ else:
|
|
rdobuilder |
3e5fd2 |
+ # assume it is a file descriptor
|
|
rdobuilder |
3e5fd2 |
+ fobj = os.fdopen(fname, mode)
|
|
rdobuilder |
3e5fd2 |
+ close = False
|
|
rdobuilder |
3e5fd2 |
+ return fobj, close
|
|
rdobuilder |
3e5fd2 |
+
|
|
rdobuilder |
3e5fd2 |
|
|
rdobuilder |
3e5fd2 |
#
|
|
rdobuilder |
3e5fd2 |
# Extented version of ASPN's Python Cookbook Recipe:
|
|
rdobuilder |
3e5fd2 |
@@ -92,7 +160,7 @@ CLUSTER_ATTRIBUTES = set( ['K', 'URL', 'bgcolor', 'color', 'colorscheme',
|
|
rdobuilder |
3e5fd2 |
#
|
|
rdobuilder |
3e5fd2 |
class frozendict(dict):
|
|
rdobuilder |
3e5fd2 |
def _blocked_attribute(obj):
|
|
rdobuilder |
3e5fd2 |
- raise AttributeError, "A frozendict cannot be modified."
|
|
rdobuilder |
3e5fd2 |
+ raise AttributeError("A frozendict cannot be modified.")
|
|
rdobuilder |
3e5fd2 |
_blocked_attribute = property(_blocked_attribute)
|
|
rdobuilder |
3e5fd2 |
|
|
rdobuilder |
3e5fd2 |
__delitem__ = __setitem__ = clear = _blocked_attribute
|
|
rdobuilder |
3e5fd2 |
@@ -105,7 +173,7 @@ class frozendict(dict):
|
|
rdobuilder |
3e5fd2 |
for arg in args:
|
|
rdobuilder |
3e5fd2 |
if isinstance(arg, dict):
|
|
rdobuilder |
3e5fd2 |
arg = copy.copy(arg)
|
|
rdobuilder |
3e5fd2 |
- for k, v in arg.iteritems():
|
|
rdobuilder |
3e5fd2 |
+ for k, v in arg.items():
|
|
rdobuilder |
3e5fd2 |
if isinstance(v, frozendict):
|
|
rdobuilder |
3e5fd2 |
arg[k] = v
|
|
rdobuilder |
3e5fd2 |
elif isinstance(v, dict):
|
|
rdobuilder |
3e5fd2 |
@@ -114,13 +182,13 @@ class frozendict(dict):
|
|
rdobuilder |
3e5fd2 |
v_ = list()
|
|
rdobuilder |
3e5fd2 |
for elm in v:
|
|
rdobuilder |
3e5fd2 |
if isinstance(elm, dict):
|
|
rdobuilder |
3e5fd2 |
- v_.append( frozendict(elm) )
|
|
rdobuilder |
3e5fd2 |
+ v_.append(frozendict(elm))
|
|
rdobuilder |
3e5fd2 |
else:
|
|
rdobuilder |
3e5fd2 |
- v_.append( elm )
|
|
rdobuilder |
3e5fd2 |
+ v_.append(elm)
|
|
rdobuilder |
3e5fd2 |
arg[k] = tuple(v_)
|
|
rdobuilder |
3e5fd2 |
- args_.append( arg )
|
|
rdobuilder |
3e5fd2 |
+ args_.append(arg)
|
|
rdobuilder |
3e5fd2 |
else:
|
|
rdobuilder |
3e5fd2 |
- args_.append( arg )
|
|
rdobuilder |
3e5fd2 |
+ args_.append(arg)
|
|
rdobuilder |
3e5fd2 |
|
|
rdobuilder |
3e5fd2 |
dict.__init__(new, *args_, **kw)
|
|
rdobuilder |
3e5fd2 |
return new
|
|
rdobuilder |
3e5fd2 |
@@ -132,7 +200,7 @@ class frozendict(dict):
|
|
rdobuilder |
3e5fd2 |
try:
|
|
rdobuilder |
3e5fd2 |
return self._cached_hash
|
|
rdobuilder |
3e5fd2 |
except AttributeError:
|
|
rdobuilder |
3e5fd2 |
- h = self._cached_hash = hash(tuple(sorted(self.iteritems())))
|
|
rdobuilder |
3e5fd2 |
+ h = self._cached_hash = hash(tuple(sorted(self.items())))
|
|
rdobuilder |
3e5fd2 |
return h
|
|
rdobuilder |
3e5fd2 |
|
|
rdobuilder |
3e5fd2 |
def __repr__(self):
|
|
rdobuilder |
3e5fd2 |
@@ -142,23 +210,25 @@ class frozendict(dict):
|
|
rdobuilder |
3e5fd2 |
dot_keywords = ['graph', 'subgraph', 'digraph', 'node', 'edge', 'strict']
|
|
rdobuilder |
3e5fd2 |
|
|
rdobuilder |
3e5fd2 |
id_re_alpha_nums = re.compile('^[_a-zA-Z][a-zA-Z0-9_,]*$', re.UNICODE)
|
|
rdobuilder |
3e5fd2 |
-id_re_alpha_nums_with_ports = re.compile('^[_a-zA-Z][a-zA-Z0-9_,:\"]*[a-zA-Z0-9_,\"]+$', re.UNICODE)
|
|
rdobuilder |
3e5fd2 |
+id_re_alpha_nums_with_ports = re.compile(
|
|
rdobuilder |
3e5fd2 |
+ '^[_a-zA-Z][a-zA-Z0-9_,:\"]*[a-zA-Z0-9_,\"]+$', re.UNICODE
|
|
rdobuilder |
3e5fd2 |
+ )
|
|
rdobuilder |
3e5fd2 |
id_re_num = re.compile('^[0-9,]+$', re.UNICODE)
|
|
rdobuilder |
3e5fd2 |
id_re_with_port = re.compile('^([^:]*):([^:]*)$', re.UNICODE)
|
|
rdobuilder |
3e5fd2 |
-id_re_dbl_quoted = re.compile('^\".*\"$', re.S|re.UNICODE)
|
|
rdobuilder |
3e5fd2 |
-id_re_html = re.compile('^<.*>$', re.S|re.UNICODE)
|
|
rdobuilder |
3e5fd2 |
+id_re_dbl_quoted = re.compile('^\".*\"$', re.S | re.UNICODE)
|
|
rdobuilder |
3e5fd2 |
+id_re_html = re.compile('^<.*>$', re.S | re.UNICODE)
|
|
rdobuilder |
3e5fd2 |
|
|
rdobuilder |
3e5fd2 |
|
|
rdobuilder |
3e5fd2 |
-def needs_quotes( s ):
|
|
rdobuilder |
3e5fd2 |
+def needs_quotes(s):
|
|
rdobuilder |
3e5fd2 |
"""Checks whether a string is a dot language ID.
|
|
rdobuilder |
3e5fd2 |
-
|
|
rdobuilder |
3e5fd2 |
+
|
|
rdobuilder |
3e5fd2 |
It will check whether the string is solely composed
|
|
rdobuilder |
3e5fd2 |
by the characters allowed in an ID or not.
|
|
rdobuilder |
3e5fd2 |
If the string is one of the reserved keywords it will
|
|
rdobuilder |
3e5fd2 |
need quotes too but the user will need to add them
|
|
rdobuilder |
3e5fd2 |
manually.
|
|
rdobuilder |
3e5fd2 |
"""
|
|
rdobuilder |
3e5fd2 |
-
|
|
rdobuilder |
3e5fd2 |
+
|
|
rdobuilder |
3e5fd2 |
# If the name is a reserved keyword it will need quotes but pydot
|
|
rdobuilder |
3e5fd2 |
# can't tell when it's being used as a keyword or when it's simply
|
|
rdobuilder |
3e5fd2 |
# a name. Hence the user needs to supply the quotes when an element
|
|
rdobuilder |
3e5fd2 |
@@ -168,11 +238,14 @@ def needs_quotes( s ):
|
|
rdobuilder |
3e5fd2 |
if s in dot_keywords:
|
|
rdobuilder |
3e5fd2 |
return False
|
|
rdobuilder |
3e5fd2 |
|
|
rdobuilder |
3e5fd2 |
- chars = [ord(c) for c in s if ord(c)>0x7f or ord(c)==0]
|
|
rdobuilder |
3e5fd2 |
+ chars = [ord(c) for c in s if ord(c) > 0x7f or ord(c) == 0]
|
|
rdobuilder |
3e5fd2 |
if chars and not id_re_dbl_quoted.match(s) and not id_re_html.match(s):
|
|
rdobuilder |
3e5fd2 |
return True
|
|
rdobuilder |
3e5fd2 |
-
|
|
rdobuilder |
3e5fd2 |
- for test_re in [id_re_alpha_nums, id_re_num, id_re_dbl_quoted, id_re_html, id_re_alpha_nums_with_ports]:
|
|
rdobuilder |
3e5fd2 |
+
|
|
rdobuilder |
3e5fd2 |
+ for test_re in [
|
|
rdobuilder |
3e5fd2 |
+ id_re_alpha_nums, id_re_num, id_re_dbl_quoted,
|
|
rdobuilder |
3e5fd2 |
+ id_re_html, id_re_alpha_nums_with_ports
|
|
rdobuilder |
3e5fd2 |
+ ]:
|
|
rdobuilder |
3e5fd2 |
if test_re.match(s):
|
|
rdobuilder |
3e5fd2 |
return False
|
|
rdobuilder |
3e5fd2 |
|
|
rdobuilder |
3e5fd2 |
@@ -184,109 +257,109 @@ def needs_quotes( s ):
|
|
rdobuilder |
3e5fd2 |
|
|
rdobuilder |
3e5fd2 |
|
|
rdobuilder |
3e5fd2 |
def quote_if_necessary(s):
|
|
rdobuilder |
3e5fd2 |
+ # Older versions of graphviz throws a syntax error for empty values without
|
|
rdobuilder |
3e5fd2 |
+ # quotes, e.g. [label=]
|
|
rdobuilder |
3e5fd2 |
+ if s == '':
|
|
rdobuilder |
3e5fd2 |
+ return '""'
|
|
rdobuilder |
3e5fd2 |
|
|
rdobuilder |
3e5fd2 |
if isinstance(s, bool):
|
|
rdobuilder |
3e5fd2 |
if s is True:
|
|
rdobuilder |
3e5fd2 |
return 'True'
|
|
rdobuilder |
3e5fd2 |
return 'False'
|
|
rdobuilder |
3e5fd2 |
|
|
rdobuilder |
3e5fd2 |
- if not isinstance( s, basestring ):
|
|
rdobuilder |
3e5fd2 |
+ if not isinstance(s, basestring):
|
|
rdobuilder |
3e5fd2 |
return s
|
|
rdobuilder |
3e5fd2 |
|
|
rdobuilder |
3e5fd2 |
if not s:
|
|
rdobuilder |
3e5fd2 |
return s
|
|
rdobuilder |
3e5fd2 |
-
|
|
rdobuilder |
3e5fd2 |
+
|
|
rdobuilder |
3e5fd2 |
if needs_quotes(s):
|
|
rdobuilder |
3e5fd2 |
- replace = {'"' : r'\"',
|
|
rdobuilder |
3e5fd2 |
- "\n" : r'\n',
|
|
rdobuilder |
3e5fd2 |
- "\r" : r'\r'}
|
|
rdobuilder |
3e5fd2 |
- for (a,b) in replace.items():
|
|
rdobuilder |
3e5fd2 |
+ replace = {'"': r'\"', "\n": r'\n', "\r": r'\r'}
|
|
rdobuilder |
3e5fd2 |
+ for (a, b) in replace.items():
|
|
rdobuilder |
3e5fd2 |
s = s.replace(a, b)
|
|
rdobuilder |
3e5fd2 |
|
|
rdobuilder |
3e5fd2 |
return '"' + s + '"'
|
|
rdobuilder |
3e5fd2 |
-
|
|
rdobuilder |
3e5fd2 |
- return s
|
|
rdobuilder |
3e5fd2 |
|
|
rdobuilder |
3e5fd2 |
+ return s
|
|
rdobuilder |
3e5fd2 |
|
|
rdobuilder |
3e5fd2 |
|
|
rdobuilder |
3e5fd2 |
def graph_from_dot_data(data):
|
|
rdobuilder |
3e5fd2 |
"""Load graph as defined by data in DOT format.
|
|
rdobuilder |
3e5fd2 |
-
|
|
rdobuilder |
3e5fd2 |
+
|
|
rdobuilder |
3e5fd2 |
The data is assumed to be in DOT format. It will
|
|
rdobuilder |
3e5fd2 |
- be parsed and a Dot class will be returned,
|
|
rdobuilder |
3e5fd2 |
+ be parsed and a Dot class will be returned,
|
|
rdobuilder |
3e5fd2 |
representing the graph.
|
|
rdobuilder |
3e5fd2 |
"""
|
|
rdobuilder |
3e5fd2 |
-
|
|
rdobuilder |
3e5fd2 |
+
|
|
rdobuilder |
3e5fd2 |
return dot_parser.parse_dot_data(data)
|
|
rdobuilder |
3e5fd2 |
|
|
rdobuilder |
3e5fd2 |
|
|
rdobuilder |
3e5fd2 |
def graph_from_dot_file(path):
|
|
rdobuilder |
3e5fd2 |
"""Load graph as defined by a DOT file.
|
|
rdobuilder |
3e5fd2 |
-
|
|
rdobuilder |
3e5fd2 |
+
|
|
rdobuilder |
3e5fd2 |
The file is assumed to be in DOT format. It will
|
|
rdobuilder |
3e5fd2 |
- be loaded, parsed and a Dot class will be returned,
|
|
rdobuilder |
3e5fd2 |
+ be loaded, parsed and a Dot class will be returned,
|
|
rdobuilder |
3e5fd2 |
representing the graph.
|
|
rdobuilder |
3e5fd2 |
"""
|
|
rdobuilder |
3e5fd2 |
-
|
|
rdobuilder |
3e5fd2 |
- fd = file(path, 'rb')
|
|
rdobuilder |
3e5fd2 |
+
|
|
rdobuilder |
3e5fd2 |
+ fd = open(path, 'rb')
|
|
rdobuilder |
3e5fd2 |
data = fd.read()
|
|
rdobuilder |
3e5fd2 |
fd.close()
|
|
rdobuilder |
3e5fd2 |
-
|
|
rdobuilder |
3e5fd2 |
- return graph_from_dot_data(data)
|
|
rdobuilder |
3e5fd2 |
|
|
rdobuilder |
3e5fd2 |
+ return graph_from_dot_data(data)
|
|
rdobuilder |
3e5fd2 |
|
|
rdobuilder |
3e5fd2 |
|
|
rdobuilder |
3e5fd2 |
def graph_from_edges(edge_list, node_prefix='', directed=False):
|
|
rdobuilder |
3e5fd2 |
"""Creates a basic graph out of an edge list.
|
|
rdobuilder |
3e5fd2 |
-
|
|
rdobuilder |
3e5fd2 |
+
|
|
rdobuilder |
3e5fd2 |
The edge list has to be a list of tuples representing
|
|
rdobuilder |
3e5fd2 |
the nodes connected by the edge.
|
|
rdobuilder |
3e5fd2 |
The values can be anything: bool, int, float, str.
|
|
rdobuilder |
3e5fd2 |
-
|
|
rdobuilder |
3e5fd2 |
+
|
|
rdobuilder |
3e5fd2 |
If the graph is undirected by default, it is only
|
|
rdobuilder |
3e5fd2 |
calculated from one of the symmetric halves of the matrix.
|
|
rdobuilder |
3e5fd2 |
"""
|
|
rdobuilder |
3e5fd2 |
-
|
|
rdobuilder |
3e5fd2 |
+
|
|
rdobuilder |
3e5fd2 |
if directed:
|
|
rdobuilder |
3e5fd2 |
graph = Dot(graph_type='digraph')
|
|
rdobuilder |
3e5fd2 |
-
|
|
rdobuilder |
3e5fd2 |
+
|
|
rdobuilder |
3e5fd2 |
else:
|
|
rdobuilder |
3e5fd2 |
graph = Dot(graph_type='graph')
|
|
rdobuilder |
3e5fd2 |
-
|
|
rdobuilder |
3e5fd2 |
+
|
|
rdobuilder |
3e5fd2 |
for edge in edge_list:
|
|
rdobuilder |
3e5fd2 |
-
|
|
rdobuilder |
3e5fd2 |
+
|
|
rdobuilder |
3e5fd2 |
if isinstance(edge[0], str):
|
|
rdobuilder |
3e5fd2 |
src = node_prefix + edge[0]
|
|
rdobuilder |
3e5fd2 |
else:
|
|
rdobuilder |
3e5fd2 |
src = node_prefix + str(edge[0])
|
|
rdobuilder |
3e5fd2 |
-
|
|
rdobuilder |
3e5fd2 |
+
|
|
rdobuilder |
3e5fd2 |
if isinstance(edge[1], str):
|
|
rdobuilder |
3e5fd2 |
dst = node_prefix + edge[1]
|
|
rdobuilder |
3e5fd2 |
else:
|
|
rdobuilder |
3e5fd2 |
dst = node_prefix + str(edge[1])
|
|
rdobuilder |
3e5fd2 |
|
|
rdobuilder |
3e5fd2 |
- e = Edge( src, dst )
|
|
rdobuilder |
3e5fd2 |
+ e = Edge(src, dst)
|
|
rdobuilder |
3e5fd2 |
graph.add_edge(e)
|
|
rdobuilder |
3e5fd2 |
-
|
|
rdobuilder |
3e5fd2 |
+
|
|
rdobuilder |
3e5fd2 |
return graph
|
|
rdobuilder |
3e5fd2 |
|
|
rdobuilder |
3e5fd2 |
|
|
rdobuilder |
3e5fd2 |
-def graph_from_adjacency_matrix(matrix, node_prefix= u'', directed=False):
|
|
rdobuilder |
3e5fd2 |
+def graph_from_adjacency_matrix(matrix, node_prefix='', directed=False):
|
|
rdobuilder |
3e5fd2 |
"""Creates a basic graph out of an adjacency matrix.
|
|
rdobuilder |
3e5fd2 |
-
|
|
rdobuilder |
3e5fd2 |
+
|
|
rdobuilder |
3e5fd2 |
The matrix has to be a list of rows of values
|
|
rdobuilder |
3e5fd2 |
representing an adjacency matrix.
|
|
rdobuilder |
3e5fd2 |
The values can be anything: bool, int, float, as long
|
|
rdobuilder |
3e5fd2 |
as they can evaluate to True or False.
|
|
rdobuilder |
3e5fd2 |
"""
|
|
rdobuilder |
3e5fd2 |
-
|
|
rdobuilder |
3e5fd2 |
+
|
|
rdobuilder |
3e5fd2 |
node_orig = 1
|
|
rdobuilder |
3e5fd2 |
-
|
|
rdobuilder |
3e5fd2 |
+
|
|
rdobuilder |
3e5fd2 |
if directed:
|
|
rdobuilder |
3e5fd2 |
graph = Dot(graph_type='digraph')
|
|
rdobuilder |
3e5fd2 |
else:
|
|
rdobuilder |
3e5fd2 |
graph = Dot(graph_type='graph')
|
|
rdobuilder |
3e5fd2 |
-
|
|
rdobuilder |
3e5fd2 |
+
|
|
rdobuilder |
3e5fd2 |
for row in matrix:
|
|
rdobuilder |
3e5fd2 |
if not directed:
|
|
rdobuilder |
3e5fd2 |
skip = matrix.index(row)
|
|
rdobuilder |
3e5fd2 |
@@ -294,320 +367,297 @@ def graph_from_adjacency_matrix(matrix, node_prefix= u'', directed=False):
|
|
rdobuilder |
3e5fd2 |
else:
|
|
rdobuilder |
3e5fd2 |
skip = 0
|
|
rdobuilder |
3e5fd2 |
r = row
|
|
rdobuilder |
3e5fd2 |
- node_dest = skip+1
|
|
rdobuilder |
3e5fd2 |
-
|
|
rdobuilder |
3e5fd2 |
+ node_dest = skip + 1
|
|
rdobuilder |
3e5fd2 |
+
|
|
rdobuilder |
3e5fd2 |
for e in r:
|
|
rdobuilder |
3e5fd2 |
if e:
|
|
rdobuilder |
3e5fd2 |
graph.add_edge(
|
|
rdobuilder |
3e5fd2 |
- Edge( node_prefix + node_orig,
|
|
rdobuilder |
3e5fd2 |
- node_prefix + node_dest) )
|
|
rdobuilder |
3e5fd2 |
+ Edge(
|
|
rdobuilder |
3e5fd2 |
+ node_prefix + node_orig,
|
|
rdobuilder |
3e5fd2 |
+ node_prefix + node_dest
|
|
rdobuilder |
3e5fd2 |
+ )
|
|
rdobuilder |
3e5fd2 |
+ )
|
|
rdobuilder |
3e5fd2 |
node_dest += 1
|
|
rdobuilder |
3e5fd2 |
node_orig += 1
|
|
rdobuilder |
3e5fd2 |
-
|
|
rdobuilder |
3e5fd2 |
- return graph
|
|
rdobuilder |
3e5fd2 |
|
|
rdobuilder |
3e5fd2 |
+ return graph
|
|
rdobuilder |
3e5fd2 |
|
|
rdobuilder |
3e5fd2 |
|
|
rdobuilder |
3e5fd2 |
def graph_from_incidence_matrix(matrix, node_prefix='', directed=False):
|
|
rdobuilder |
3e5fd2 |
"""Creates a basic graph out of an incidence matrix.
|
|
rdobuilder |
3e5fd2 |
-
|
|
rdobuilder |
3e5fd2 |
+
|
|
rdobuilder |
3e5fd2 |
The matrix has to be a list of rows of values
|
|
rdobuilder |
3e5fd2 |
representing an incidence matrix.
|
|
rdobuilder |
3e5fd2 |
The values can be anything: bool, int, float, as long
|
|
rdobuilder |
3e5fd2 |
as they can evaluate to True or False.
|
|
rdobuilder |
3e5fd2 |
"""
|
|
rdobuilder |
3e5fd2 |
-
|
|
rdobuilder |
3e5fd2 |
- node_orig = 1
|
|
rdobuilder |
3e5fd2 |
-
|
|
rdobuilder |
3e5fd2 |
+
|
|
rdobuilder |
3e5fd2 |
if directed:
|
|
rdobuilder |
3e5fd2 |
graph = Dot(graph_type='digraph')
|
|
rdobuilder |
3e5fd2 |
else:
|
|
rdobuilder |
3e5fd2 |
graph = Dot(graph_type='graph')
|
|
rdobuilder |
3e5fd2 |
-
|
|
rdobuilder |
3e5fd2 |
+
|
|
rdobuilder |
3e5fd2 |
for row in matrix:
|
|
rdobuilder |
3e5fd2 |
nodes = []
|
|
rdobuilder |
3e5fd2 |
c = 1
|
|
rdobuilder |
3e5fd2 |
-
|
|
rdobuilder |
3e5fd2 |
+
|
|
rdobuilder |
3e5fd2 |
for node in row:
|
|
rdobuilder |
3e5fd2 |
if node:
|
|
rdobuilder |
3e5fd2 |
- nodes.append(c*node)
|
|
rdobuilder |
3e5fd2 |
+ nodes.append(c * node)
|
|
rdobuilder |
3e5fd2 |
c += 1
|
|
rdobuilder |
3e5fd2 |
- nodes.sort()
|
|
rdobuilder |
3e5fd2 |
-
|
|
rdobuilder |
3e5fd2 |
+
|
|
rdobuilder |
3e5fd2 |
+ nodes.sort()
|
|
rdobuilder |
3e5fd2 |
+
|
|
rdobuilder |
3e5fd2 |
if len(nodes) == 2:
|
|
rdobuilder |
3e5fd2 |
- graph.add_edge(
|
|
rdobuilder |
3e5fd2 |
- Edge( node_prefix + abs(nodes[0]),
|
|
rdobuilder |
3e5fd2 |
- node_prefix + nodes[1] ))
|
|
rdobuilder |
3e5fd2 |
+ graph.add_edge(
|
|
rdobuilder |
3e5fd2 |
+ Edge(
|
|
rdobuilder |
3e5fd2 |
+ node_prefix + abs(nodes[0]),
|
|
rdobuilder |
3e5fd2 |
+ node_prefix + nodes[1]
|
|
rdobuilder |
3e5fd2 |
+ )
|
|
rdobuilder |
3e5fd2 |
+ )
|
|
rdobuilder |
3e5fd2 |
|
|
rdobuilder |
3e5fd2 |
if not directed:
|
|
rdobuilder |
3e5fd2 |
graph.set_simplify(True)
|
|
rdobuilder |
3e5fd2 |
|
|
rdobuilder |
3e5fd2 |
return graph
|
|
rdobuilder |
3e5fd2 |
|
|
rdobuilder |
3e5fd2 |
-
|
|
rdobuilder |
3e5fd2 |
-
|
|
rdobuilder |
3e5fd2 |
|
|
rdobuilder |
3e5fd2 |
def __find_executables(path):
|
|
rdobuilder |
3e5fd2 |
"""Used by find_graphviz
|
|
rdobuilder |
3e5fd2 |
-
|
|
rdobuilder |
3e5fd2 |
+
|
|
rdobuilder |
3e5fd2 |
path - single directory as a string
|
|
rdobuilder |
3e5fd2 |
-
|
|
rdobuilder |
3e5fd2 |
+
|
|
rdobuilder |
3e5fd2 |
If any of the executables are found, it will return a dictionary
|
|
rdobuilder |
3e5fd2 |
containing the program names as keys and their paths as values.
|
|
rdobuilder |
3e5fd2 |
-
|
|
rdobuilder |
3e5fd2 |
+
|
|
rdobuilder |
3e5fd2 |
Otherwise returns None
|
|
rdobuilder |
3e5fd2 |
"""
|
|
rdobuilder |
3e5fd2 |
-
|
|
rdobuilder |
3e5fd2 |
+
|
|
rdobuilder |
3e5fd2 |
success = False
|
|
rdobuilder |
3e5fd2 |
progs = {'dot': '', 'twopi': '', 'neato': '', 'circo': '', 'fdp': '', 'sfdp': ''}
|
|
rdobuilder |
3e5fd2 |
-
|
|
rdobuilder |
3e5fd2 |
+
|
|
rdobuilder |
3e5fd2 |
was_quoted = False
|
|
rdobuilder |
3e5fd2 |
path = path.strip()
|
|
rdobuilder |
3e5fd2 |
if path.startswith('"') and path.endswith('"'):
|
|
rdobuilder |
3e5fd2 |
path = path[1:-1]
|
|
rdobuilder |
3e5fd2 |
- was_quoted = True
|
|
rdobuilder |
3e5fd2 |
-
|
|
rdobuilder |
3e5fd2 |
- if os.path.isdir(path) :
|
|
rdobuilder |
3e5fd2 |
-
|
|
rdobuilder |
3e5fd2 |
- for prg in progs.iterkeys():
|
|
rdobuilder |
3e5fd2 |
-
|
|
rdobuilder |
3e5fd2 |
+ was_quoted = True
|
|
rdobuilder |
3e5fd2 |
+
|
|
rdobuilder |
3e5fd2 |
+ if os.path.isdir(path):
|
|
rdobuilder |
3e5fd2 |
+ for prg in progs.keys():
|
|
rdobuilder |
3e5fd2 |
if progs[prg]:
|
|
rdobuilder |
3e5fd2 |
continue
|
|
rdobuilder |
3e5fd2 |
-
|
|
rdobuilder |
3e5fd2 |
- if os.path.exists( os.path.join(path, prg) ):
|
|
rdobuilder |
3e5fd2 |
-
|
|
rdobuilder |
3e5fd2 |
+
|
|
rdobuilder |
3e5fd2 |
+ if os.path.exists(os.path.join(path, prg)):
|
|
rdobuilder |
3e5fd2 |
if was_quoted:
|
|
rdobuilder |
3e5fd2 |
progs[prg] = '"' + os.path.join(path, prg) + '"'
|
|
rdobuilder |
3e5fd2 |
else:
|
|
rdobuilder |
3e5fd2 |
progs[prg] = os.path.join(path, prg)
|
|
rdobuilder |
3e5fd2 |
-
|
|
rdobuilder |
3e5fd2 |
+
|
|
rdobuilder |
3e5fd2 |
success = True
|
|
rdobuilder |
3e5fd2 |
-
|
|
rdobuilder |
3e5fd2 |
- elif os.path.exists( os.path.join(path, prg + '.exe') ):
|
|
rdobuilder |
3e5fd2 |
|
|
rdobuilder |
3e5fd2 |
+ elif os.path.exists(os.path.join(path, prg + '.exe')):
|
|
rdobuilder |
3e5fd2 |
if was_quoted:
|
|
rdobuilder |
3e5fd2 |
progs[prg] = '"' + os.path.join(path, prg + '.exe') + '"'
|
|
rdobuilder |
3e5fd2 |
else:
|
|
rdobuilder |
3e5fd2 |
progs[prg] = os.path.join(path, prg + '.exe')
|
|
rdobuilder |
3e5fd2 |
-
|
|
rdobuilder |
3e5fd2 |
+
|
|
rdobuilder |
3e5fd2 |
success = True
|
|
rdobuilder |
3e5fd2 |
-
|
|
rdobuilder |
3e5fd2 |
+
|
|
rdobuilder |
3e5fd2 |
if success:
|
|
rdobuilder |
3e5fd2 |
-
|
|
rdobuilder |
3e5fd2 |
return progs
|
|
rdobuilder |
3e5fd2 |
-
|
|
rdobuilder |
3e5fd2 |
else:
|
|
rdobuilder |
3e5fd2 |
-
|
|
rdobuilder |
3e5fd2 |
return None
|
|
rdobuilder |
3e5fd2 |
|
|
rdobuilder |
3e5fd2 |
|
|
rdobuilder |
3e5fd2 |
-
|
|
rdobuilder |
3e5fd2 |
# The multi-platform version of this 'find_graphviz' function was
|
|
rdobuilder |
3e5fd2 |
# contributed by Peter Cock
|
|
rdobuilder |
3e5fd2 |
-#
|
|
rdobuilder |
3e5fd2 |
def find_graphviz():
|
|
rdobuilder |
3e5fd2 |
"""Locate Graphviz's executables in the system.
|
|
rdobuilder |
3e5fd2 |
-
|
|
rdobuilder |
3e5fd2 |
+
|
|
rdobuilder |
3e5fd2 |
Tries three methods:
|
|
rdobuilder |
3e5fd2 |
-
|
|
rdobuilder |
3e5fd2 |
+
|
|
rdobuilder |
3e5fd2 |
First: Windows Registry (Windows only)
|
|
rdobuilder |
3e5fd2 |
This requires Mark Hammond's pywin32 is installed.
|
|
rdobuilder |
3e5fd2 |
-
|
|
rdobuilder |
3e5fd2 |
+
|
|
rdobuilder |
3e5fd2 |
Secondly: Search the path
|
|
rdobuilder |
3e5fd2 |
It will look for 'dot', 'twopi' and 'neato' in all the directories
|
|
rdobuilder |
3e5fd2 |
specified in the PATH environment variable.
|
|
rdobuilder |
3e5fd2 |
-
|
|
rdobuilder |
3e5fd2 |
+
|
|
rdobuilder |
3e5fd2 |
Thirdly: Default install location (Windows only)
|
|
rdobuilder |
3e5fd2 |
It will look for 'dot', 'twopi' and 'neato' in the default install
|
|
rdobuilder |
3e5fd2 |
location under the "Program Files" directory.
|
|
rdobuilder |
3e5fd2 |
-
|
|
rdobuilder |
3e5fd2 |
+
|
|
rdobuilder |
3e5fd2 |
It will return a dictionary containing the program names as keys
|
|
rdobuilder |
3e5fd2 |
and their paths as values.
|
|
rdobuilder |
3e5fd2 |
-
|
|
rdobuilder |
3e5fd2 |
+
|
|
rdobuilder |
3e5fd2 |
If this fails, it returns None.
|
|
rdobuilder |
3e5fd2 |
"""
|
|
rdobuilder |
3e5fd2 |
-
|
|
rdobuilder |
3e5fd2 |
+
|
|
rdobuilder |
3e5fd2 |
# Method 1 (Windows only)
|
|
rdobuilder |
3e5fd2 |
- #
|
|
rdobuilder |
3e5fd2 |
if os.sys.platform == 'win32':
|
|
rdobuilder |
3e5fd2 |
-
|
|
rdobuilder |
3e5fd2 |
- HKEY_LOCAL_MACHINE = 0x80000002
|
|
rdobuilder |
3e5fd2 |
- KEY_QUERY_VALUE = 0x0001
|
|
rdobuilder |
3e5fd2 |
+
|
|
rdobuilder |
3e5fd2 |
+ HKEY_LOCAL_MACHINE = 0x80000002
|
|
rdobuilder |
3e5fd2 |
+ KEY_QUERY_VALUE = 0x0001
|
|
rdobuilder |
3e5fd2 |
|
|
rdobuilder |
3e5fd2 |
RegOpenKeyEx = None
|
|
rdobuilder |
3e5fd2 |
RegQueryValueEx = None
|
|
rdobuilder |
3e5fd2 |
RegCloseKey = None
|
|
rdobuilder |
3e5fd2 |
-
|
|
rdobuilder |
3e5fd2 |
+
|
|
rdobuilder |
3e5fd2 |
try:
|
|
rdobuilder |
3e5fd2 |
- import win32api, win32con
|
|
rdobuilder |
3e5fd2 |
+ import win32api
|
|
rdobuilder |
3e5fd2 |
RegOpenKeyEx = win32api.RegOpenKeyEx
|
|
rdobuilder |
3e5fd2 |
RegQueryValueEx = win32api.RegQueryValueEx
|
|
rdobuilder |
3e5fd2 |
RegCloseKey = win32api.RegCloseKey
|
|
rdobuilder |
3e5fd2 |
|
|
rdobuilder |
3e5fd2 |
except ImportError:
|
|
rdobuilder |
3e5fd2 |
# Print a messaged suggesting they install these?
|
|
rdobuilder |
3e5fd2 |
- #
|
|
rdobuilder |
3e5fd2 |
pass
|
|
rdobuilder |
3e5fd2 |
|
|
rdobuilder |
3e5fd2 |
try:
|
|
rdobuilder |
3e5fd2 |
import ctypes
|
|
rdobuilder |
3e5fd2 |
-
|
|
rdobuilder |
3e5fd2 |
+
|
|
rdobuilder |
3e5fd2 |
def RegOpenKeyEx(key, subkey, opt, sam):
|
|
rdobuilder |
3e5fd2 |
result = ctypes.c_uint(0)
|
|
rdobuilder |
3e5fd2 |
ctypes.windll.advapi32.RegOpenKeyExA(key, subkey, opt, sam, ctypes.byref(result))
|
|
rdobuilder |
3e5fd2 |
return result.value
|
|
rdobuilder |
3e5fd2 |
-
|
|
rdobuilder |
3e5fd2 |
- def RegQueryValueEx( hkey, valuename ):
|
|
rdobuilder |
3e5fd2 |
+
|
|
rdobuilder |
3e5fd2 |
+ def RegQueryValueEx(hkey, valuename):
|
|
rdobuilder |
3e5fd2 |
data_type = ctypes.c_uint(0)
|
|
rdobuilder |
3e5fd2 |
data_len = ctypes.c_uint(1024)
|
|
rdobuilder |
3e5fd2 |
- data = ctypes.create_string_buffer( 1024 )
|
|
rdobuilder |
3e5fd2 |
-
|
|
rdobuilder |
3e5fd2 |
- res = ctypes.windll.advapi32.RegQueryValueExA(hkey, valuename, 0,
|
|
rdobuilder |
3e5fd2 |
- ctypes.byref(data_type), data, ctypes.byref(data_len))
|
|
rdobuilder |
3e5fd2 |
-
|
|
rdobuilder |
3e5fd2 |
+ data = ctypes.create_string_buffer(1024)
|
|
rdobuilder |
3e5fd2 |
+
|
|
rdobuilder |
3e5fd2 |
+ # this has a return value, which we should probably check
|
|
rdobuilder |
3e5fd2 |
+ ctypes.windll.advapi32.RegQueryValueExA(
|
|
rdobuilder |
3e5fd2 |
+ hkey, valuename, 0, ctypes.byref(data_type),
|
|
rdobuilder |
3e5fd2 |
+ data, ctypes.byref(data_len)
|
|
rdobuilder |
3e5fd2 |
+ )
|
|
rdobuilder |
3e5fd2 |
+
|
|
rdobuilder |
3e5fd2 |
return data.value
|
|
rdobuilder |
3e5fd2 |
-
|
|
rdobuilder |
3e5fd2 |
+
|
|
rdobuilder |
3e5fd2 |
RegCloseKey = ctypes.windll.advapi32.RegCloseKey
|
|
rdobuilder |
3e5fd2 |
-
|
|
rdobuilder |
3e5fd2 |
+
|
|
rdobuilder |
3e5fd2 |
except ImportError:
|
|
rdobuilder |
3e5fd2 |
# Print a messaged suggesting they install these?
|
|
rdobuilder |
3e5fd2 |
- #
|
|
rdobuilder |
3e5fd2 |
pass
|
|
rdobuilder |
3e5fd2 |
|
|
rdobuilder |
3e5fd2 |
if RegOpenKeyEx is not None:
|
|
rdobuilder |
3e5fd2 |
-
|
|
rdobuilder |
3e5fd2 |
# Get the GraphViz install path from the registry
|
|
rdobuilder |
3e5fd2 |
- #
|
|
rdobuilder |
3e5fd2 |
hkey = None
|
|
rdobuilder |
3e5fd2 |
potentialKeys = [
|
|
rdobuilder |
3e5fd2 |
"SOFTWARE\\ATT\\Graphviz",
|
|
rdobuilder |
3e5fd2 |
- "SOFTWARE\\AT&T Research Labs\\Graphviz",
|
|
rdobuilder |
3e5fd2 |
- ]
|
|
rdobuilder |
3e5fd2 |
+ "SOFTWARE\\AT&T Research Labs\\Graphviz"
|
|
rdobuilder |
3e5fd2 |
+ ]
|
|
rdobuilder |
3e5fd2 |
for potentialKey in potentialKeys:
|
|
rdobuilder |
3e5fd2 |
-
|
|
rdobuilder |
3e5fd2 |
+
|
|
rdobuilder |
3e5fd2 |
try:
|
|
rdobuilder |
3e5fd2 |
- hkey = RegOpenKeyEx( HKEY_LOCAL_MACHINE,
|
|
rdobuilder |
3e5fd2 |
- potentialKey, 0, KEY_QUERY_VALUE )
|
|
rdobuilder |
3e5fd2 |
-
|
|
rdobuilder |
3e5fd2 |
+ hkey = RegOpenKeyEx(
|
|
rdobuilder |
3e5fd2 |
+ HKEY_LOCAL_MACHINE,
|
|
rdobuilder |
3e5fd2 |
+ potentialKey, 0, KEY_QUERY_VALUE
|
|
rdobuilder |
3e5fd2 |
+ )
|
|
rdobuilder |
3e5fd2 |
+
|
|
rdobuilder |
3e5fd2 |
if hkey is not None:
|
|
rdobuilder |
3e5fd2 |
- path = RegQueryValueEx( hkey, "InstallPath" )
|
|
rdobuilder |
3e5fd2 |
- RegCloseKey( hkey )
|
|
rdobuilder |
3e5fd2 |
-
|
|
rdobuilder |
3e5fd2 |
+ path = RegQueryValueEx(hkey, "InstallPath")
|
|
rdobuilder |
3e5fd2 |
+ RegCloseKey(hkey)
|
|
rdobuilder |
3e5fd2 |
+
|
|
rdobuilder |
3e5fd2 |
# The regitry variable might exist, left by old installations
|
|
rdobuilder |
3e5fd2 |
# but with no value, in those cases we keep searching...
|
|
rdobuilder |
3e5fd2 |
if not path:
|
|
rdobuilder |
3e5fd2 |
continue
|
|
rdobuilder |
3e5fd2 |
-
|
|
rdobuilder |
3e5fd2 |
+
|
|
rdobuilder |
3e5fd2 |
# Now append the "bin" subdirectory:
|
|
rdobuilder |
3e5fd2 |
- #
|
|
rdobuilder |
3e5fd2 |
path = os.path.join(path, "bin")
|
|
rdobuilder |
3e5fd2 |
progs = __find_executables(path)
|
|
rdobuilder |
3e5fd2 |
- if progs is not None :
|
|
rdobuilder |
3e5fd2 |
- #print "Used Windows registry"
|
|
rdobuilder |
3e5fd2 |
+ if progs is not None:
|
|
rdobuilder |
3e5fd2 |
+ #print("Used Windows registry")
|
|
rdobuilder |
3e5fd2 |
return progs
|
|
rdobuilder |
3e5fd2 |
-
|
|
rdobuilder |
3e5fd2 |
- except Exception, excp:
|
|
rdobuilder |
3e5fd2 |
- #raise excp
|
|
rdobuilder |
3e5fd2 |
+
|
|
rdobuilder |
3e5fd2 |
+ except Exception:
|
|
rdobuilder |
3e5fd2 |
+ #raise
|
|
rdobuilder |
3e5fd2 |
pass
|
|
rdobuilder |
3e5fd2 |
else:
|
|
rdobuilder |
3e5fd2 |
break
|
|
rdobuilder |
3e5fd2 |
-
|
|
rdobuilder |
3e5fd2 |
-
|
|
rdobuilder |
3e5fd2 |
|
|
rdobuilder |
3e5fd2 |
# Method 2 (Linux, Windows etc)
|
|
rdobuilder |
3e5fd2 |
- #
|
|
rdobuilder |
3e5fd2 |
- if os.environ.has_key('PATH'):
|
|
rdobuilder |
3e5fd2 |
-
|
|
rdobuilder |
3e5fd2 |
+ if 'PATH' in os.environ:
|
|
rdobuilder |
3e5fd2 |
for path in os.environ['PATH'].split(os.pathsep):
|
|
rdobuilder |
3e5fd2 |
progs = __find_executables(path)
|
|
rdobuilder |
3e5fd2 |
- if progs is not None :
|
|
rdobuilder |
3e5fd2 |
- #print "Used path"
|
|
rdobuilder |
3e5fd2 |
+ if progs is not None:
|
|
rdobuilder |
3e5fd2 |
+ #print("Used path")
|
|
rdobuilder |
3e5fd2 |
return progs
|
|
rdobuilder |
3e5fd2 |
|
|
rdobuilder |
3e5fd2 |
# Method 3 (Windows only)
|
|
rdobuilder |
3e5fd2 |
- #
|
|
rdobuilder |
3e5fd2 |
if os.sys.platform == 'win32':
|
|
rdobuilder |
3e5fd2 |
-
|
|
rdobuilder |
3e5fd2 |
+
|
|
rdobuilder |
3e5fd2 |
# Try and work out the equivalent of "C:\Program Files" on this
|
|
rdobuilder |
3e5fd2 |
# machine (might be on drive D:, or in a different language)
|
|
rdobuilder |
3e5fd2 |
- #
|
|
rdobuilder |
3e5fd2 |
-
|
|
rdobuilder |
3e5fd2 |
- if os.environ.has_key('PROGRAMFILES'):
|
|
rdobuilder |
3e5fd2 |
-
|
|
rdobuilder |
3e5fd2 |
+ if 'PROGRAMFILES' in os.environ:
|
|
rdobuilder |
3e5fd2 |
# Note, we could also use the win32api to get this
|
|
rdobuilder |
3e5fd2 |
# information, but win32api may not be installed.
|
|
rdobuilder |
3e5fd2 |
-
|
|
rdobuilder |
3e5fd2 |
path = os.path.join(os.environ['PROGRAMFILES'], 'ATT', 'GraphViz', 'bin')
|
|
rdobuilder |
3e5fd2 |
-
|
|
rdobuilder |
3e5fd2 |
else:
|
|
rdobuilder |
3e5fd2 |
-
|
|
rdobuilder |
3e5fd2 |
#Just in case, try the default...
|
|
rdobuilder |
3e5fd2 |
path = r"C:\Program Files\att\Graphviz\bin"
|
|
rdobuilder |
3e5fd2 |
-
|
|
rdobuilder |
3e5fd2 |
+
|
|
rdobuilder |
3e5fd2 |
progs = __find_executables(path)
|
|
rdobuilder |
3e5fd2 |
-
|
|
rdobuilder |
3e5fd2 |
- if progs is not None :
|
|
rdobuilder |
3e5fd2 |
-
|
|
rdobuilder |
3e5fd2 |
- #print "Used default install location"
|
|
rdobuilder |
3e5fd2 |
- return progs
|
|
rdobuilder |
3e5fd2 |
|
|
rdobuilder |
3e5fd2 |
+ if progs is not None:
|
|
rdobuilder |
3e5fd2 |
+
|
|
rdobuilder |
3e5fd2 |
+ #print("Used default install location")
|
|
rdobuilder |
3e5fd2 |
+ return progs
|
|
rdobuilder |
3e5fd2 |
|
|
rdobuilder |
3e5fd2 |
for path in (
|
|
rdobuilder |
3e5fd2 |
- '/usr/bin', '/usr/local/bin',
|
|
rdobuilder |
3e5fd2 |
- '/opt/local/bin',
|
|
rdobuilder |
3e5fd2 |
- '/opt/bin', '/sw/bin', '/usr/share',
|
|
rdobuilder |
3e5fd2 |
- '/Applications/Graphviz.app/Contents/MacOS/' ):
|
|
rdobuilder |
3e5fd2 |
-
|
|
rdobuilder |
3e5fd2 |
+ '/usr/bin', '/usr/local/bin',
|
|
rdobuilder |
3e5fd2 |
+ '/opt/local/bin',
|
|
rdobuilder |
3e5fd2 |
+ '/opt/bin', '/sw/bin', '/usr/share',
|
|
rdobuilder |
3e5fd2 |
+ '/Applications/Graphviz.app/Contents/MacOS/'
|
|
rdobuilder |
3e5fd2 |
+ ):
|
|
rdobuilder |
3e5fd2 |
+
|
|
rdobuilder |
3e5fd2 |
progs = __find_executables(path)
|
|
rdobuilder |
3e5fd2 |
- if progs is not None :
|
|
rdobuilder |
3e5fd2 |
- #print "Used path"
|
|
rdobuilder |
3e5fd2 |
+ if progs is not None:
|
|
rdobuilder |
3e5fd2 |
+ #print("Used path")
|
|
rdobuilder |
3e5fd2 |
return progs
|
|
rdobuilder |
3e5fd2 |
|
|
rdobuilder |
3e5fd2 |
# Failed to find GraphViz
|
|
rdobuilder |
3e5fd2 |
- #
|
|
rdobuilder |
3e5fd2 |
return None
|
|
rdobuilder |
3e5fd2 |
-
|
|
rdobuilder |
3e5fd2 |
|
|
rdobuilder |
3e5fd2 |
-class Common:
|
|
rdobuilder |
3e5fd2 |
+
|
|
rdobuilder |
3e5fd2 |
+class Common(object):
|
|
rdobuilder |
3e5fd2 |
"""Common information to several classes.
|
|
rdobuilder |
3e5fd2 |
-
|
|
rdobuilder |
3e5fd2 |
+
|
|
rdobuilder |
3e5fd2 |
Should not be directly used, several classes are derived from
|
|
rdobuilder |
3e5fd2 |
this one.
|
|
rdobuilder |
3e5fd2 |
"""
|
|
rdobuilder |
3e5fd2 |
-
|
|
rdobuilder |
3e5fd2 |
|
|
rdobuilder |
3e5fd2 |
def __getstate__(self):
|
|
rdobuilder |
3e5fd2 |
|
|
rdobuilder |
3e5fd2 |
dict = copy.copy(self.obj_dict)
|
|
rdobuilder |
3e5fd2 |
-
|
|
rdobuilder |
3e5fd2 |
+
|
|
rdobuilder |
3e5fd2 |
return dict
|
|
rdobuilder |
3e5fd2 |
|
|
rdobuilder |
3e5fd2 |
-
|
|
rdobuilder |
3e5fd2 |
def __setstate__(self, state):
|
|
rdobuilder |
3e5fd2 |
-
|
|
rdobuilder |
3e5fd2 |
- self.obj_dict = state
|
|
rdobuilder |
3e5fd2 |
|
|
rdobuilder |
3e5fd2 |
+ self.obj_dict = state
|
|
rdobuilder |
3e5fd2 |
|
|
rdobuilder |
3e5fd2 |
def __get_attribute__(self, attr):
|
|
rdobuilder |
3e5fd2 |
"""Look for default attributes for this node"""
|
|
rdobuilder |
3e5fd2 |
-
|
|
rdobuilder |
3e5fd2 |
+
|
|
rdobuilder |
3e5fd2 |
attr_val = self.obj_dict['attributes'].get(attr, None)
|
|
rdobuilder |
3e5fd2 |
-
|
|
rdobuilder |
3e5fd2 |
+
|
|
rdobuilder |
3e5fd2 |
if attr_val is None:
|
|
rdobuilder |
3e5fd2 |
# get the defaults for nodes/edges
|
|
rdobuilder |
3e5fd2 |
-
|
|
rdobuilder |
3e5fd2 |
+
|
|
rdobuilder |
3e5fd2 |
default_node_name = self.obj_dict['type']
|
|
rdobuilder |
3e5fd2 |
-
|
|
rdobuilder |
3e5fd2 |
+
|
|
rdobuilder |
3e5fd2 |
# The defaults for graphs are set on a node named 'graph'
|
|
rdobuilder |
3e5fd2 |
if default_node_name in ('subgraph', 'digraph', 'cluster'):
|
|
rdobuilder |
3e5fd2 |
default_node_name = 'graph'
|
|
rdobuilder |
3e5fd2 |
-
|
|
rdobuilder |
3e5fd2 |
+
|
|
rdobuilder |
3e5fd2 |
g = self.get_parent_graph()
|
|
rdobuilder |
3e5fd2 |
if g is not None:
|
|
rdobuilder |
3e5fd2 |
- defaults = g.get_node( default_node_name )
|
|
rdobuilder |
3e5fd2 |
+ defaults = g.get_node(default_node_name)
|
|
rdobuilder |
3e5fd2 |
else:
|
|
rdobuilder |
3e5fd2 |
return None
|
|
rdobuilder |
3e5fd2 |
-
|
|
rdobuilder |
3e5fd2 |
+
|
|
rdobuilder |
3e5fd2 |
# Multiple defaults could be set by having repeated 'graph [...]'
|
|
rdobuilder |
3e5fd2 |
# 'node [...]', 'edge [...]' statements. In such case, if the
|
|
rdobuilder |
3e5fd2 |
# same attribute is set in different statements, only the first
|
|
rdobuilder |
3e5fd2 |
@@ -618,84 +668,78 @@ class Common:
|
|
rdobuilder |
3e5fd2 |
#
|
|
rdobuilder |
3e5fd2 |
if not isinstance(defaults, (list, tuple)):
|
|
rdobuilder |
3e5fd2 |
defaults = [defaults]
|
|
rdobuilder |
3e5fd2 |
-
|
|
rdobuilder |
3e5fd2 |
+
|
|
rdobuilder |
3e5fd2 |
for default in defaults:
|
|
rdobuilder |
3e5fd2 |
attr_val = default.obj_dict['attributes'].get(attr, None)
|
|
rdobuilder |
3e5fd2 |
if attr_val:
|
|
rdobuilder |
3e5fd2 |
return attr_val
|
|
rdobuilder |
3e5fd2 |
else:
|
|
rdobuilder |
3e5fd2 |
return attr_val
|
|
rdobuilder |
3e5fd2 |
-
|
|
rdobuilder |
3e5fd2 |
+
|
|
rdobuilder |
3e5fd2 |
return None
|
|
rdobuilder |
3e5fd2 |
-
|
|
rdobuilder |
3e5fd2 |
|
|
rdobuilder |
3e5fd2 |
def set_parent_graph(self, parent_graph):
|
|
rdobuilder |
3e5fd2 |
-
|
|
rdobuilder |
3e5fd2 |
+
|
|
rdobuilder |
3e5fd2 |
self.obj_dict['parent_graph'] = parent_graph
|
|
rdobuilder |
3e5fd2 |
-
|
|
rdobuilder |
3e5fd2 |
|
|
rdobuilder |
3e5fd2 |
def get_parent_graph(self):
|
|
rdobuilder |
3e5fd2 |
-
|
|
rdobuilder |
3e5fd2 |
- return self.obj_dict.get('parent_graph', None)
|
|
rdobuilder |
3e5fd2 |
|
|
rdobuilder |
3e5fd2 |
+ return self.obj_dict.get('parent_graph', None)
|
|
rdobuilder |
3e5fd2 |
|
|
rdobuilder |
3e5fd2 |
def set(self, name, value):
|
|
rdobuilder |
3e5fd2 |
"""Set an attribute value by name.
|
|
rdobuilder |
3e5fd2 |
-
|
|
rdobuilder |
3e5fd2 |
+
|
|
rdobuilder |
3e5fd2 |
Given an attribute 'name' it will set its value to 'value'.
|
|
rdobuilder |
3e5fd2 |
There's always the possibility of using the methods:
|
|
rdobuilder |
3e5fd2 |
-
|
|
rdobuilder |
3e5fd2 |
+
|
|
rdobuilder |
3e5fd2 |
set_'name'(value)
|
|
rdobuilder |
3e5fd2 |
-
|
|
rdobuilder |
3e5fd2 |
+
|
|
rdobuilder |
3e5fd2 |
which are defined for all the existing attributes.
|
|
rdobuilder |
3e5fd2 |
"""
|
|
rdobuilder |
3e5fd2 |
|
|
rdobuilder |
3e5fd2 |
self.obj_dict['attributes'][name] = value
|
|
rdobuilder |
3e5fd2 |
|
|
rdobuilder |
3e5fd2 |
-
|
|
rdobuilder |
3e5fd2 |
def get(self, name):
|
|
rdobuilder |
3e5fd2 |
"""Get an attribute value by name.
|
|
rdobuilder |
3e5fd2 |
-
|
|
rdobuilder |
3e5fd2 |
+
|
|
rdobuilder |
3e5fd2 |
Given an attribute 'name' it will get its value.
|
|
rdobuilder |
3e5fd2 |
There's always the possibility of using the methods:
|
|
rdobuilder |
3e5fd2 |
-
|
|
rdobuilder |
3e5fd2 |
+
|
|
rdobuilder |
3e5fd2 |
get_'name'()
|
|
rdobuilder |
3e5fd2 |
-
|
|
rdobuilder |
3e5fd2 |
+
|
|
rdobuilder |
3e5fd2 |
which are defined for all the existing attributes.
|
|
rdobuilder |
3e5fd2 |
"""
|
|
rdobuilder |
3e5fd2 |
|
|
rdobuilder |
3e5fd2 |
return self.obj_dict['attributes'].get(name, None)
|
|
rdobuilder |
3e5fd2 |
-
|
|
rdobuilder |
3e5fd2 |
|
|
rdobuilder |
3e5fd2 |
def get_attributes(self):
|
|
rdobuilder |
3e5fd2 |
""""""
|
|
rdobuilder |
3e5fd2 |
-
|
|
rdobuilder |
3e5fd2 |
+
|
|
rdobuilder |
3e5fd2 |
return self.obj_dict['attributes']
|
|
rdobuilder |
3e5fd2 |
|
|
rdobuilder |
3e5fd2 |
-
|
|
rdobuilder |
3e5fd2 |
def set_sequence(self, seq):
|
|
rdobuilder |
3e5fd2 |
-
|
|
rdobuilder |
3e5fd2 |
- self.obj_dict['sequence'] = seq
|
|
rdobuilder |
3e5fd2 |
|
|
rdobuilder |
3e5fd2 |
+ self.obj_dict['sequence'] = seq
|
|
rdobuilder |
3e5fd2 |
|
|
rdobuilder |
3e5fd2 |
def get_sequence(self):
|
|
rdobuilder |
3e5fd2 |
-
|
|
rdobuilder |
3e5fd2 |
+
|
|
rdobuilder |
3e5fd2 |
return self.obj_dict['sequence']
|
|
rdobuilder |
3e5fd2 |
-
|
|
rdobuilder |
3e5fd2 |
-
|
|
rdobuilder |
3e5fd2 |
+
|
|
rdobuilder |
3e5fd2 |
def create_attribute_methods(self, obj_attributes):
|
|
rdobuilder |
3e5fd2 |
-
|
|
rdobuilder |
3e5fd2 |
+
|
|
rdobuilder |
3e5fd2 |
#for attr in self.obj_dict['attributes']:
|
|
rdobuilder |
3e5fd2 |
for attr in obj_attributes:
|
|
rdobuilder |
3e5fd2 |
-
|
|
rdobuilder |
3e5fd2 |
+
|
|
rdobuilder |
3e5fd2 |
# Generate all the Setter methods.
|
|
rdobuilder |
3e5fd2 |
#
|
|
rdobuilder |
3e5fd2 |
- self.__setattr__( 'set_'+attr, lambda x, a=attr : self.obj_dict['attributes'].__setitem__(a, x) )
|
|
rdobuilder |
3e5fd2 |
-
|
|
rdobuilder |
3e5fd2 |
+ self.__setattr__(
|
|
rdobuilder |
3e5fd2 |
+ 'set_' + attr,
|
|
rdobuilder |
3e5fd2 |
+ lambda x, a=attr: self.obj_dict['attributes'].__setitem__(a, x)
|
|
rdobuilder |
3e5fd2 |
+ )
|
|
rdobuilder |
3e5fd2 |
+
|
|
rdobuilder |
3e5fd2 |
# Generate all the Getter methods.
|
|
rdobuilder |
3e5fd2 |
#
|
|
rdobuilder |
3e5fd2 |
- self.__setattr__('get_'+attr, lambda a=attr : self.__get_attribute__(a))
|
|
rdobuilder |
3e5fd2 |
-
|
|
rdobuilder |
3e5fd2 |
+ self.__setattr__('get_' + attr, lambda a=attr: self.__get_attribute__(a))
|
|
rdobuilder |
3e5fd2 |
|
|
rdobuilder |
3e5fd2 |
|
|
rdobuilder |
3e5fd2 |
class Error(Exception):
|
|
rdobuilder |
3e5fd2 |
@@ -703,6 +747,7 @@ class Error(Exception):
|
|
rdobuilder |
3e5fd2 |
"""
|
|
rdobuilder |
3e5fd2 |
def __init__(self, value):
|
|
rdobuilder |
3e5fd2 |
self.value = value
|
|
rdobuilder |
3e5fd2 |
+
|
|
rdobuilder |
3e5fd2 |
def __str__(self):
|
|
rdobuilder |
3e5fd2 |
return self.value
|
|
rdobuilder |
3e5fd2 |
|
|
rdobuilder |
3e5fd2 |
@@ -712,119 +757,108 @@ class InvocationException(Exception):
|
|
rdobuilder |
3e5fd2 |
"""
|
|
rdobuilder |
3e5fd2 |
def __init__(self, value):
|
|
rdobuilder |
3e5fd2 |
self.value = value
|
|
rdobuilder |
3e5fd2 |
+
|
|
rdobuilder |
3e5fd2 |
def __str__(self):
|
|
rdobuilder |
3e5fd2 |
return self.value
|
|
rdobuilder |
3e5fd2 |
|
|
rdobuilder |
3e5fd2 |
|
|
rdobuilder |
3e5fd2 |
-
|
|
rdobuilder |
3e5fd2 |
-class Node(object, Common):
|
|
rdobuilder |
3e5fd2 |
+class Node(Common):
|
|
rdobuilder |
3e5fd2 |
"""A graph node.
|
|
rdobuilder |
3e5fd2 |
-
|
|
rdobuilder |
3e5fd2 |
+
|
|
rdobuilder |
3e5fd2 |
This class represents a graph's node with all its attributes.
|
|
rdobuilder |
3e5fd2 |
-
|
|
rdobuilder |
3e5fd2 |
+
|
|
rdobuilder |
3e5fd2 |
node(name, attribute=value, ...)
|
|
rdobuilder |
3e5fd2 |
-
|
|
rdobuilder |
3e5fd2 |
+
|
|
rdobuilder |
3e5fd2 |
name: node's name
|
|
rdobuilder |
3e5fd2 |
-
|
|
rdobuilder |
3e5fd2 |
+
|
|
rdobuilder |
3e5fd2 |
All the attributes defined in the Graphviz dot language should
|
|
rdobuilder |
3e5fd2 |
be supported.
|
|
rdobuilder |
3e5fd2 |
"""
|
|
rdobuilder |
3e5fd2 |
|
|
rdobuilder |
3e5fd2 |
- def __init__(self, name = '', obj_dict = None, **attrs):
|
|
rdobuilder |
3e5fd2 |
-
|
|
rdobuilder |
3e5fd2 |
+ def __init__(self, name='', obj_dict=None, **attrs):
|
|
rdobuilder |
3e5fd2 |
+
|
|
rdobuilder |
3e5fd2 |
#
|
|
rdobuilder |
3e5fd2 |
# Nodes will take attributes of all other types because the defaults
|
|
rdobuilder |
3e5fd2 |
# for any GraphViz object are dealt with as if they were Node definitions
|
|
rdobuilder |
3e5fd2 |
#
|
|
rdobuilder |
3e5fd2 |
-
|
|
rdobuilder |
3e5fd2 |
+
|
|
rdobuilder |
3e5fd2 |
if obj_dict is not None:
|
|
rdobuilder |
3e5fd2 |
-
|
|
rdobuilder |
3e5fd2 |
self.obj_dict = obj_dict
|
|
rdobuilder |
3e5fd2 |
-
|
|
rdobuilder |
3e5fd2 |
else:
|
|
rdobuilder |
3e5fd2 |
-
|
|
rdobuilder |
3e5fd2 |
self.obj_dict = dict()
|
|
rdobuilder |
3e5fd2 |
-
|
|
rdobuilder |
3e5fd2 |
+
|
|
rdobuilder |
3e5fd2 |
# Copy the attributes
|
|
rdobuilder |
3e5fd2 |
#
|
|
rdobuilder |
3e5fd2 |
- self.obj_dict[ 'attributes' ] = dict( attrs )
|
|
rdobuilder |
3e5fd2 |
- self.obj_dict[ 'type' ] = 'node'
|
|
rdobuilder |
3e5fd2 |
- self.obj_dict[ 'parent_graph' ] = None
|
|
rdobuilder |
3e5fd2 |
- self.obj_dict[ 'parent_node_list' ] = None
|
|
rdobuilder |
3e5fd2 |
- self.obj_dict[ 'sequence' ] = None
|
|
rdobuilder |
3e5fd2 |
-
|
|
rdobuilder |
3e5fd2 |
+ self.obj_dict['attributes'] = dict(attrs)
|
|
rdobuilder |
3e5fd2 |
+ self.obj_dict['type'] = 'node'
|
|
rdobuilder |
3e5fd2 |
+ self.obj_dict['parent_graph'] = None
|
|
rdobuilder |
3e5fd2 |
+ self.obj_dict['parent_node_list'] = None
|
|
rdobuilder |
3e5fd2 |
+ self.obj_dict['sequence'] = None
|
|
rdobuilder |
3e5fd2 |
+
|
|
rdobuilder |
3e5fd2 |
# Remove the compass point
|
|
rdobuilder |
3e5fd2 |
#
|
|
rdobuilder |
3e5fd2 |
port = None
|
|
rdobuilder |
3e5fd2 |
if isinstance(name, basestring) and not name.startswith('"'):
|
|
rdobuilder |
3e5fd2 |
idx = name.find(':')
|
|
rdobuilder |
3e5fd2 |
- if idx > 0 and idx+1 < len(name):
|
|
rdobuilder |
3e5fd2 |
+ if idx > 0 and idx + 1 < len(name):
|
|
rdobuilder |
3e5fd2 |
name, port = name[:idx], name[idx:]
|
|
rdobuilder |
3e5fd2 |
|
|
rdobuilder |
3e5fd2 |
if isinstance(name, (long, int)):
|
|
rdobuilder |
3e5fd2 |
name = str(name)
|
|
rdobuilder |
3e5fd2 |
-
|
|
rdobuilder |
3e5fd2 |
- self.obj_dict['name'] = quote_if_necessary( name )
|
|
rdobuilder |
3e5fd2 |
+
|
|
rdobuilder |
3e5fd2 |
+ self.obj_dict['name'] = quote_if_necessary(name)
|
|
rdobuilder |
3e5fd2 |
self.obj_dict['port'] = port
|
|
rdobuilder |
3e5fd2 |
-
|
|
rdobuilder |
3e5fd2 |
+
|
|
rdobuilder |
3e5fd2 |
self.create_attribute_methods(NODE_ATTRIBUTES)
|
|
rdobuilder |
3e5fd2 |
-
|
|
rdobuilder |
3e5fd2 |
-
|
|
rdobuilder |
3e5fd2 |
-
|
|
rdobuilder |
3e5fd2 |
+
|
|
rdobuilder |
3e5fd2 |
def set_name(self, node_name):
|
|
rdobuilder |
3e5fd2 |
"""Set the node's name."""
|
|
rdobuilder |
3e5fd2 |
-
|
|
rdobuilder |
3e5fd2 |
+
|
|
rdobuilder |
3e5fd2 |
self.obj_dict['name'] = node_name
|
|
rdobuilder |
3e5fd2 |
-
|
|
rdobuilder |
3e5fd2 |
-
|
|
rdobuilder |
3e5fd2 |
+
|
|
rdobuilder |
3e5fd2 |
def get_name(self):
|
|
rdobuilder |
3e5fd2 |
"""Get the node's name."""
|
|
rdobuilder |
3e5fd2 |
-
|
|
rdobuilder |
3e5fd2 |
+
|
|
rdobuilder |
3e5fd2 |
return self.obj_dict['name']
|
|
rdobuilder |
3e5fd2 |
|
|
rdobuilder |
3e5fd2 |
-
|
|
rdobuilder |
3e5fd2 |
def get_port(self):
|
|
rdobuilder |
3e5fd2 |
"""Get the node's port."""
|
|
rdobuilder |
3e5fd2 |
-
|
|
rdobuilder |
3e5fd2 |
- return self.obj_dict['port']
|
|
rdobuilder |
3e5fd2 |
|
|
rdobuilder |
3e5fd2 |
+ return self.obj_dict['port']
|
|
rdobuilder |
3e5fd2 |
|
|
rdobuilder |
3e5fd2 |
def add_style(self, style):
|
|
rdobuilder |
3e5fd2 |
-
|
|
rdobuilder |
3e5fd2 |
+
|
|
rdobuilder |
3e5fd2 |
styles = self.obj_dict['attributes'].get('style', None)
|
|
rdobuilder |
3e5fd2 |
if not styles and style:
|
|
rdobuilder |
3e5fd2 |
- styles = [ style ]
|
|
rdobuilder |
3e5fd2 |
+ styles = [style]
|
|
rdobuilder |
3e5fd2 |
else:
|
|
rdobuilder |
3e5fd2 |
styles = styles.split(',')
|
|
rdobuilder |
3e5fd2 |
- styles.append( style )
|
|
rdobuilder |
3e5fd2 |
-
|
|
rdobuilder |
3e5fd2 |
- self.obj_dict['attributes']['style'] = ','.join( styles )
|
|
rdobuilder |
3e5fd2 |
-
|
|
rdobuilder |
3e5fd2 |
+ styles.append(style)
|
|
rdobuilder |
3e5fd2 |
+
|
|
rdobuilder |
3e5fd2 |
+ self.obj_dict['attributes']['style'] = ','.join(styles)
|
|
rdobuilder |
3e5fd2 |
|
|
rdobuilder |
3e5fd2 |
def to_string(self):
|
|
rdobuilder |
3e5fd2 |
"""Returns a string representation of the node in dot language.
|
|
rdobuilder |
3e5fd2 |
"""
|
|
rdobuilder |
3e5fd2 |
-
|
|
rdobuilder |
3e5fd2 |
-
|
|
rdobuilder |
3e5fd2 |
+
|
|
rdobuilder |
3e5fd2 |
# RMF: special case defaults for node, edge and graph properties.
|
|
rdobuilder |
3e5fd2 |
#
|
|
rdobuilder |
3e5fd2 |
node = quote_if_necessary(self.obj_dict['name'])
|
|
rdobuilder |
3e5fd2 |
|
|
rdobuilder |
3e5fd2 |
node_attr = list()
|
|
rdobuilder |
3e5fd2 |
|
|
rdobuilder |
3e5fd2 |
- for attr, value in self.obj_dict['attributes'].iteritems():
|
|
rdobuilder |
3e5fd2 |
+ for attr, value in sorted(self.obj_dict['attributes'].items(), key=itemgetter(0)):
|
|
rdobuilder |
3e5fd2 |
if value is not None:
|
|
rdobuilder |
3e5fd2 |
- node_attr.append( '%s=%s' % (attr, quote_if_necessary(value) ) )
|
|
rdobuilder |
3e5fd2 |
+ node_attr.append('%s=%s' % (attr, quote_if_necessary(value)))
|
|
rdobuilder |
3e5fd2 |
else:
|
|
rdobuilder |
3e5fd2 |
- node_attr.append( attr )
|
|
rdobuilder |
3e5fd2 |
-
|
|
rdobuilder |
3e5fd2 |
-
|
|
rdobuilder |
3e5fd2 |
+ node_attr.append(attr)
|
|
rdobuilder |
3e5fd2 |
+
|
|
rdobuilder |
3e5fd2 |
# No point in having nodes setting any defaults if the don't set
|
|
rdobuilder |
3e5fd2 |
# any attributes...
|
|
rdobuilder |
3e5fd2 |
#
|
|
rdobuilder |
3e5fd2 |
if node in ('graph', 'node', 'edge') and len(node_attr) == 0:
|
|
rdobuilder |
3e5fd2 |
return ''
|
|
rdobuilder |
3e5fd2 |
-
|
|
rdobuilder |
3e5fd2 |
+
|
|
rdobuilder |
3e5fd2 |
node_attr = ', '.join(node_attr)
|
|
rdobuilder |
3e5fd2 |
|
|
rdobuilder |
3e5fd2 |
if node_attr:
|
|
rdobuilder |
3e5fd2 |
@@ -833,207 +867,191 @@ class Node(object, Common):
|
|
rdobuilder |
3e5fd2 |
return node + ';'
|
|
rdobuilder |
3e5fd2 |
|
|
rdobuilder |
3e5fd2 |
|
|
rdobuilder |
3e5fd2 |
-
|
|
rdobuilder |
3e5fd2 |
-class Edge(object, Common ):
|
|
rdobuilder |
3e5fd2 |
+class Edge(Common):
|
|
rdobuilder |
3e5fd2 |
"""A graph edge.
|
|
rdobuilder |
3e5fd2 |
-
|
|
rdobuilder |
3e5fd2 |
+
|
|
rdobuilder |
3e5fd2 |
This class represents a graph's edge with all its attributes.
|
|
rdobuilder |
3e5fd2 |
-
|
|
rdobuilder |
3e5fd2 |
+
|
|
rdobuilder |
3e5fd2 |
edge(src, dst, attribute=value, ...)
|
|
rdobuilder |
3e5fd2 |
-
|
|
rdobuilder |
3e5fd2 |
+
|
|
rdobuilder |
3e5fd2 |
src: source node's name
|
|
rdobuilder |
3e5fd2 |
dst: destination node's name
|
|
rdobuilder |
3e5fd2 |
-
|
|
rdobuilder |
3e5fd2 |
+
|
|
rdobuilder |
3e5fd2 |
All the attributes defined in the Graphviz dot language should
|
|
rdobuilder |
3e5fd2 |
be supported.
|
|
rdobuilder |
3e5fd2 |
-
|
|
rdobuilder |
3e5fd2 |
- Attributes can be set through the dynamically generated methods:
|
|
rdobuilder |
3e5fd2 |
-
|
|
rdobuilder |
3e5fd2 |
+
|
|
rdobuilder |
3e5fd2 |
+ Attributes can be set through the dynamically generated methods:
|
|
rdobuilder |
3e5fd2 |
+
|
|
rdobuilder |
3e5fd2 |
set_[attribute name], i.e. set_label, set_fontname
|
|
rdobuilder |
3e5fd2 |
-
|
|
rdobuilder |
3e5fd2 |
+
|
|
rdobuilder |
3e5fd2 |
or directly by using the instance's special dictionary:
|
|
rdobuilder |
3e5fd2 |
-
|
|
rdobuilder |
3e5fd2 |
- Edge.obj_dict['attributes'][attribute name], i.e.
|
|
rdobuilder |
3e5fd2 |
-
|
|
rdobuilder |
3e5fd2 |
+
|
|
rdobuilder |
3e5fd2 |
+ Edge.obj_dict['attributes'][attribute name], i.e.
|
|
rdobuilder |
3e5fd2 |
+
|
|
rdobuilder |
3e5fd2 |
edge_instance.obj_dict['attributes']['label']
|
|
rdobuilder |
3e5fd2 |
edge_instance.obj_dict['attributes']['fontname']
|
|
rdobuilder |
3e5fd2 |
-
|
|
rdobuilder |
3e5fd2 |
- """
|
|
rdobuilder |
3e5fd2 |
-
|
|
rdobuilder |
3e5fd2 |
|
|
rdobuilder |
3e5fd2 |
+ """
|
|
rdobuilder |
3e5fd2 |
|
|
rdobuilder |
3e5fd2 |
def __init__(self, src='', dst='', obj_dict=None, **attrs):
|
|
rdobuilder |
3e5fd2 |
-
|
|
rdobuilder |
3e5fd2 |
+
|
|
rdobuilder |
3e5fd2 |
if isinstance(src, (list, tuple)) and dst == '':
|
|
rdobuilder |
3e5fd2 |
src, dst = src
|
|
rdobuilder |
3e5fd2 |
-
|
|
rdobuilder |
3e5fd2 |
+
|
|
rdobuilder |
3e5fd2 |
if obj_dict is not None:
|
|
rdobuilder |
3e5fd2 |
-
|
|
rdobuilder |
3e5fd2 |
+
|
|
rdobuilder |
3e5fd2 |
self.obj_dict = obj_dict
|
|
rdobuilder |
3e5fd2 |
-
|
|
rdobuilder |
3e5fd2 |
+
|
|
rdobuilder |
3e5fd2 |
else:
|
|
rdobuilder |
3e5fd2 |
-
|
|
rdobuilder |
3e5fd2 |
+
|
|
rdobuilder |
3e5fd2 |
self.obj_dict = dict()
|
|
rdobuilder |
3e5fd2 |
-
|
|
rdobuilder |
3e5fd2 |
+
|
|
rdobuilder |
3e5fd2 |
# Copy the attributes
|
|
rdobuilder |
3e5fd2 |
#
|
|
rdobuilder |
3e5fd2 |
- self.obj_dict[ 'attributes' ] = dict( attrs )
|
|
rdobuilder |
3e5fd2 |
- self.obj_dict[ 'type' ] = 'edge'
|
|
rdobuilder |
3e5fd2 |
- self.obj_dict[ 'parent_graph' ] = None
|
|
rdobuilder |
3e5fd2 |
- self.obj_dict[ 'parent_edge_list' ] = None
|
|
rdobuilder |
3e5fd2 |
- self.obj_dict[ 'sequence' ] = None
|
|
rdobuilder |
3e5fd2 |
+ self.obj_dict['attributes'] = dict(attrs)
|
|
rdobuilder |
3e5fd2 |
+ self.obj_dict['type'] = 'edge'
|
|
rdobuilder |
3e5fd2 |
+ self.obj_dict['parent_graph'] = None
|
|
rdobuilder |
3e5fd2 |
+ self.obj_dict['parent_edge_list'] = None
|
|
rdobuilder |
3e5fd2 |
+ self.obj_dict['sequence'] = None
|
|
rdobuilder |
3e5fd2 |
|
|
rdobuilder |
3e5fd2 |
if isinstance(src, Node):
|
|
rdobuilder |
3e5fd2 |
src = src.get_name()
|
|
rdobuilder |
3e5fd2 |
-
|
|
rdobuilder |
3e5fd2 |
+
|
|
rdobuilder |
3e5fd2 |
if isinstance(dst, Node):
|
|
rdobuilder |
3e5fd2 |
dst = dst.get_name()
|
|
rdobuilder |
3e5fd2 |
-
|
|
rdobuilder |
3e5fd2 |
- points = ( quote_if_necessary( src) , quote_if_necessary( dst) )
|
|
rdobuilder |
3e5fd2 |
-
|
|
rdobuilder |
3e5fd2 |
+
|
|
rdobuilder |
3e5fd2 |
+ points = (quote_if_necessary(src), quote_if_necessary(dst))
|
|
rdobuilder |
3e5fd2 |
+
|
|
rdobuilder |
3e5fd2 |
self.obj_dict['points'] = points
|
|
rdobuilder |
3e5fd2 |
-
|
|
rdobuilder |
3e5fd2 |
- self.create_attribute_methods(EDGE_ATTRIBUTES)
|
|
rdobuilder |
3e5fd2 |
|
|
rdobuilder |
3e5fd2 |
+ self.create_attribute_methods(EDGE_ATTRIBUTES)
|
|
rdobuilder |
3e5fd2 |
|
|
rdobuilder |
3e5fd2 |
def get_source(self):
|
|
rdobuilder |
3e5fd2 |
"""Get the edges source node name."""
|
|
rdobuilder |
3e5fd2 |
-
|
|
rdobuilder |
3e5fd2 |
+
|
|
rdobuilder |
3e5fd2 |
return self.obj_dict['points'][0]
|
|
rdobuilder |
3e5fd2 |
-
|
|
rdobuilder |
3e5fd2 |
-
|
|
rdobuilder |
3e5fd2 |
+
|
|
rdobuilder |
3e5fd2 |
def get_destination(self):
|
|
rdobuilder |
3e5fd2 |
"""Get the edge's destination node name."""
|
|
rdobuilder |
3e5fd2 |
-
|
|
rdobuilder |
3e5fd2 |
+
|
|
rdobuilder |
3e5fd2 |
return self.obj_dict['points'][1]
|
|
rdobuilder |
3e5fd2 |
-
|
|
rdobuilder |
3e5fd2 |
-
|
|
rdobuilder |
3e5fd2 |
+
|
|
rdobuilder |
3e5fd2 |
def __hash__(self):
|
|
rdobuilder |
3e5fd2 |
-
|
|
rdobuilder |
3e5fd2 |
- return hash( hash(self.get_source()) + hash(self.get_destination()) )
|
|
rdobuilder |
3e5fd2 |
-
|
|
rdobuilder |
3e5fd2 |
-
|
|
rdobuilder |
3e5fd2 |
+ return hash(hash(self.get_source()) + hash(self.get_destination()))
|
|
rdobuilder |
3e5fd2 |
+
|
|
rdobuilder |
3e5fd2 |
def __eq__(self, edge):
|
|
rdobuilder |
3e5fd2 |
"""Compare two edges.
|
|
rdobuilder |
3e5fd2 |
-
|
|
rdobuilder |
3e5fd2 |
+
|
|
rdobuilder |
3e5fd2 |
If the parent graph is directed, arcs linking
|
|
rdobuilder |
3e5fd2 |
node A to B are considered equal and A->B != B->A
|
|
rdobuilder |
3e5fd2 |
-
|
|
rdobuilder |
3e5fd2 |
+
|
|
rdobuilder |
3e5fd2 |
If the parent graph is undirected, any edge
|
|
rdobuilder |
3e5fd2 |
connecting two nodes is equal to any other
|
|
rdobuilder |
3e5fd2 |
edge connecting the same nodes, A->B == B->A
|
|
rdobuilder |
3e5fd2 |
"""
|
|
rdobuilder |
3e5fd2 |
-
|
|
rdobuilder |
3e5fd2 |
+
|
|
rdobuilder |
3e5fd2 |
if not isinstance(edge, Edge):
|
|
rdobuilder |
3e5fd2 |
- raise Error, "Can't compare and edge to a non-edge object."
|
|
rdobuilder |
3e5fd2 |
-
|
|
rdobuilder |
3e5fd2 |
+ raise Error("Can't compare and edge to a non-edge object.")
|
|
rdobuilder |
3e5fd2 |
+
|
|
rdobuilder |
3e5fd2 |
if self.get_parent_graph().get_top_graph_type() == 'graph':
|
|
rdobuilder |
3e5fd2 |
-
|
|
rdobuilder |
3e5fd2 |
+
|
|
rdobuilder |
3e5fd2 |
# If the graph is undirected, the edge has neither
|
|
rdobuilder |
3e5fd2 |
# source nor destination.
|
|
rdobuilder |
3e5fd2 |
#
|
|
rdobuilder |
3e5fd2 |
- if ( ( self.get_source() == edge.get_source() and self.get_destination() == edge.get_destination() ) or
|
|
rdobuilder |
3e5fd2 |
- ( edge.get_source() == self.get_destination() and edge.get_destination() == self.get_source() ) ):
|
|
rdobuilder |
3e5fd2 |
+ if ((self.get_source() == edge.get_source() and
|
|
rdobuilder |
3e5fd2 |
+ self.get_destination() == edge.get_destination()) or
|
|
rdobuilder |
3e5fd2 |
+ (edge.get_source() == self.get_destination() and
|
|
rdobuilder |
3e5fd2 |
+ edge.get_destination() == self.get_source())):
|
|
rdobuilder |
3e5fd2 |
return True
|
|
rdobuilder |
3e5fd2 |
-
|
|
rdobuilder |
3e5fd2 |
+
|
|
rdobuilder |
3e5fd2 |
else:
|
|
rdobuilder |
3e5fd2 |
-
|
|
rdobuilder |
3e5fd2 |
- if self.get_source()==edge.get_source() and self.get_destination()==edge.get_destination() :
|
|
rdobuilder |
3e5fd2 |
+ if (self.get_source() == edge.get_source() and
|
|
rdobuilder |
3e5fd2 |
+ self.get_destination() == edge.get_destination()):
|
|
rdobuilder |
3e5fd2 |
return True
|
|
rdobuilder |
3e5fd2 |
-
|
|
rdobuilder |
3e5fd2 |
+
|
|
rdobuilder |
3e5fd2 |
return False
|
|
rdobuilder |
3e5fd2 |
|
|
rdobuilder |
3e5fd2 |
-
|
|
rdobuilder |
3e5fd2 |
-
|
|
rdobuilder |
3e5fd2 |
def parse_node_ref(self, node_str):
|
|
rdobuilder |
3e5fd2 |
-
|
|
rdobuilder |
3e5fd2 |
+
|
|
rdobuilder |
3e5fd2 |
if not isinstance(node_str, str):
|
|
rdobuilder |
3e5fd2 |
return node_str
|
|
rdobuilder |
3e5fd2 |
-
|
|
rdobuilder |
3e5fd2 |
+
|
|
rdobuilder |
3e5fd2 |
if node_str.startswith('"') and node_str.endswith('"'):
|
|
rdobuilder |
3e5fd2 |
-
|
|
rdobuilder |
3e5fd2 |
return node_str
|
|
rdobuilder |
3e5fd2 |
-
|
|
rdobuilder |
3e5fd2 |
+
|
|
rdobuilder |
3e5fd2 |
node_port_idx = node_str.rfind(':')
|
|
rdobuilder |
3e5fd2 |
-
|
|
rdobuilder |
3e5fd2 |
- if node_port_idx>0 and node_str[0]=='"' and node_str[node_port_idx-1]=='"':
|
|
rdobuilder |
3e5fd2 |
-
|
|
rdobuilder |
3e5fd2 |
+
|
|
rdobuilder |
3e5fd2 |
+ if (node_port_idx > 0 and node_str[0] == '"' and
|
|
rdobuilder |
3e5fd2 |
+ node_str[node_port_idx - 1] == '"'):
|
|
rdobuilder |
3e5fd2 |
return node_str
|
|
rdobuilder |
3e5fd2 |
-
|
|
rdobuilder |
3e5fd2 |
- if node_port_idx>0:
|
|
rdobuilder |
3e5fd2 |
-
|
|
rdobuilder |
3e5fd2 |
+
|
|
rdobuilder |
3e5fd2 |
+ if node_port_idx > 0:
|
|
rdobuilder |
3e5fd2 |
a = node_str[:node_port_idx]
|
|
rdobuilder |
3e5fd2 |
- b = node_str[node_port_idx+1:]
|
|
rdobuilder |
3e5fd2 |
+ b = node_str[node_port_idx + 1:]
|
|
rdobuilder |
3e5fd2 |
|
|
rdobuilder |
3e5fd2 |
node = quote_if_necessary(a)
|
|
rdobuilder |
3e5fd2 |
|
|
rdobuilder |
3e5fd2 |
- node += ':'+quote_if_necessary(b)
|
|
rdobuilder |
3e5fd2 |
+ node += ':' + quote_if_necessary(b)
|
|
rdobuilder |
3e5fd2 |
|
|
rdobuilder |
3e5fd2 |
return node
|
|
rdobuilder |
3e5fd2 |
-
|
|
rdobuilder |
3e5fd2 |
+
|
|
rdobuilder |
3e5fd2 |
return node_str
|
|
rdobuilder |
3e5fd2 |
-
|
|
rdobuilder |
3e5fd2 |
-
|
|
rdobuilder |
3e5fd2 |
+
|
|
rdobuilder |
3e5fd2 |
def to_string(self):
|
|
rdobuilder |
3e5fd2 |
"""Returns a string representation of the edge in dot language.
|
|
rdobuilder |
3e5fd2 |
"""
|
|
rdobuilder |
3e5fd2 |
|
|
rdobuilder |
3e5fd2 |
- src = self.parse_node_ref( self.get_source() )
|
|
rdobuilder |
3e5fd2 |
- dst = self.parse_node_ref( self.get_destination() )
|
|
rdobuilder |
3e5fd2 |
-
|
|
rdobuilder |
3e5fd2 |
+ src = self.parse_node_ref(self.get_source())
|
|
rdobuilder |
3e5fd2 |
+ dst = self.parse_node_ref(self.get_destination())
|
|
rdobuilder |
3e5fd2 |
+
|
|
rdobuilder |
3e5fd2 |
if isinstance(src, frozendict):
|
|
rdobuilder |
3e5fd2 |
- edge = [ Subgraph(obj_dict=src).to_string() ]
|
|
rdobuilder |
3e5fd2 |
+ edge = [Subgraph(obj_dict=src).to_string()]
|
|
rdobuilder |
3e5fd2 |
elif isinstance(src, (int, long)):
|
|
rdobuilder |
3e5fd2 |
- edge = [ str(src) ]
|
|
rdobuilder |
3e5fd2 |
+ edge = [str(src)]
|
|
rdobuilder |
3e5fd2 |
else:
|
|
rdobuilder |
3e5fd2 |
- edge = [ src ]
|
|
rdobuilder |
3e5fd2 |
-
|
|
rdobuilder |
3e5fd2 |
- if (self.get_parent_graph() and
|
|
rdobuilder |
3e5fd2 |
- self.get_parent_graph().get_top_graph_type() and
|
|
rdobuilder |
3e5fd2 |
- self.get_parent_graph().get_top_graph_type() == 'digraph' ):
|
|
rdobuilder |
3e5fd2 |
-
|
|
rdobuilder |
3e5fd2 |
- edge.append( '->' )
|
|
rdobuilder |
3e5fd2 |
-
|
|
rdobuilder |
3e5fd2 |
+ edge = [src]
|
|
rdobuilder |
3e5fd2 |
+
|
|
rdobuilder |
3e5fd2 |
+ if (self.get_parent_graph() and
|
|
rdobuilder |
3e5fd2 |
+ self.get_parent_graph().get_top_graph_type() and
|
|
rdobuilder |
3e5fd2 |
+ self.get_parent_graph().get_top_graph_type() == 'digraph'):
|
|
rdobuilder |
3e5fd2 |
+
|
|
rdobuilder |
3e5fd2 |
+ edge.append('->')
|
|
rdobuilder |
3e5fd2 |
+
|
|
rdobuilder |
3e5fd2 |
else:
|
|
rdobuilder |
3e5fd2 |
- edge.append( '--' )
|
|
rdobuilder |
3e5fd2 |
-
|
|
rdobuilder |
3e5fd2 |
+ edge.append('--')
|
|
rdobuilder |
3e5fd2 |
+
|
|
rdobuilder |
3e5fd2 |
if isinstance(dst, frozendict):
|
|
rdobuilder |
3e5fd2 |
- edge.append( Subgraph(obj_dict=dst).to_string() )
|
|
rdobuilder |
3e5fd2 |
+ edge.append(Subgraph(obj_dict=dst).to_string())
|
|
rdobuilder |
3e5fd2 |
elif isinstance(dst, (int, long)):
|
|
rdobuilder |
3e5fd2 |
- edge.append( str(dst) )
|
|
rdobuilder |
3e5fd2 |
+ edge.append(str(dst))
|
|
rdobuilder |
3e5fd2 |
else:
|
|
rdobuilder |
3e5fd2 |
- edge.append( dst )
|
|
rdobuilder |
3e5fd2 |
-
|
|
rdobuilder |
3e5fd2 |
+ edge.append(dst)
|
|
rdobuilder |
3e5fd2 |
|
|
rdobuilder |
3e5fd2 |
edge_attr = list()
|
|
rdobuilder |
3e5fd2 |
-
|
|
rdobuilder |
3e5fd2 |
- for attr, value in self.obj_dict['attributes'].iteritems():
|
|
rdobuilder |
3e5fd2 |
-
|
|
rdobuilder |
3e5fd2 |
+
|
|
rdobuilder |
3e5fd2 |
+ for attr, value in sorted(self.obj_dict['attributes'].items(), key=itemgetter(0)):
|
|
rdobuilder |
3e5fd2 |
if value is not None:
|
|
rdobuilder |
3e5fd2 |
- edge_attr.append( '%s=%s' % (attr, quote_if_necessary(value) ) )
|
|
rdobuilder |
3e5fd2 |
+ edge_attr.append('%s=%s' % (attr, quote_if_necessary(value)))
|
|
rdobuilder |
3e5fd2 |
else:
|
|
rdobuilder |
3e5fd2 |
- edge_attr.append( attr )
|
|
rdobuilder |
3e5fd2 |
+ edge_attr.append(attr)
|
|
rdobuilder |
3e5fd2 |
|
|
rdobuilder |
3e5fd2 |
edge_attr = ', '.join(edge_attr)
|
|
rdobuilder |
3e5fd2 |
-
|
|
rdobuilder |
3e5fd2 |
+
|
|
rdobuilder |
3e5fd2 |
if edge_attr:
|
|
rdobuilder |
3e5fd2 |
- edge.append( ' [' + edge_attr + ']' )
|
|
rdobuilder |
3e5fd2 |
+ edge.append(' [' + edge_attr + ']')
|
|
rdobuilder |
3e5fd2 |
|
|
rdobuilder |
3e5fd2 |
return ' '.join(edge) + ';'
|
|
rdobuilder |
3e5fd2 |
-
|
|
rdobuilder |
3e5fd2 |
-
|
|
rdobuilder |
3e5fd2 |
-
|
|
rdobuilder |
3e5fd2 |
-
|
|
rdobuilder |
3e5fd2 |
-
|
|
rdobuilder |
3e5fd2 |
-class Graph(object, Common):
|
|
rdobuilder |
3e5fd2 |
+
|
|
rdobuilder |
3e5fd2 |
+
|
|
rdobuilder |
3e5fd2 |
+class Graph(Common):
|
|
rdobuilder |
3e5fd2 |
"""Class representing a graph in Graphviz's dot language.
|
|
rdobuilder |
3e5fd2 |
|
|
rdobuilder |
3e5fd2 |
This class implements the methods to work on a representation
|
|
rdobuilder |
3e5fd2 |
of a graph in Graphviz's dot language.
|
|
rdobuilder |
3e5fd2 |
-
|
|
rdobuilder |
3e5fd2 |
- graph( graph_name='G', graph_type='digraph',
|
|
rdobuilder |
3e5fd2 |
+
|
|
rdobuilder |
3e5fd2 |
+ graph(graph_name='G', graph_type='digraph',
|
|
rdobuilder |
3e5fd2 |
strict=False, suppress_disconnected=False, attribute=value, ...)
|
|
rdobuilder |
3e5fd2 |
-
|
|
rdobuilder |
3e5fd2 |
+
|
|
rdobuilder |
3e5fd2 |
graph_name:
|
|
rdobuilder |
3e5fd2 |
the graph's name
|
|
rdobuilder |
3e5fd2 |
graph_type:
|
|
rdobuilder |
3e5fd2 |
@@ -1045,222 +1063,178 @@ class Graph(object, Common):
|
|
rdobuilder |
3e5fd2 |
if True it will avoid displaying equal edges, i.e.
|
|
rdobuilder |
3e5fd2 |
only one edge between two nodes. removing the
|
|
rdobuilder |
3e5fd2 |
duplicated ones.
|
|
rdobuilder |
3e5fd2 |
-
|
|
rdobuilder |
3e5fd2 |
+
|
|
rdobuilder |
3e5fd2 |
All the attributes defined in the Graphviz dot language should
|
|
rdobuilder |
3e5fd2 |
be supported.
|
|
rdobuilder |
3e5fd2 |
-
|
|
rdobuilder |
3e5fd2 |
+
|
|
rdobuilder |
3e5fd2 |
Attributes can be set through the dynamically generated methods:
|
|
rdobuilder |
3e5fd2 |
-
|
|
rdobuilder |
3e5fd2 |
+
|
|
rdobuilder |
3e5fd2 |
set_[attribute name], i.e. set_size, set_fontname
|
|
rdobuilder |
3e5fd2 |
-
|
|
rdobuilder |
3e5fd2 |
+
|
|
rdobuilder |
3e5fd2 |
or using the instance's attributes:
|
|
rdobuilder |
3e5fd2 |
-
|
|
rdobuilder |
3e5fd2 |
- Graph.obj_dict['attributes'][attribute name], i.e.
|
|
rdobuilder |
3e5fd2 |
-
|
|
rdobuilder |
3e5fd2 |
+
|
|
rdobuilder |
3e5fd2 |
+ Graph.obj_dict['attributes'][attribute name], i.e.
|
|
rdobuilder |
3e5fd2 |
+
|
|
rdobuilder |
3e5fd2 |
graph_instance.obj_dict['attributes']['label']
|
|
rdobuilder |
3e5fd2 |
graph_instance.obj_dict['attributes']['fontname']
|
|
rdobuilder |
3e5fd2 |
"""
|
|
rdobuilder |
3e5fd2 |
-
|
|
rdobuilder |
3e5fd2 |
|
|
rdobuilder |
3e5fd2 |
- def __init__(self, graph_name='G', obj_dict=None, graph_type='digraph', strict=False,
|
|
rdobuilder |
3e5fd2 |
- suppress_disconnected=False, simplify=False, **attrs):
|
|
rdobuilder |
3e5fd2 |
+ def __init__(
|
|
rdobuilder |
3e5fd2 |
+ self, graph_name='G', obj_dict=None, graph_type='digraph', strict=False,
|
|
rdobuilder |
3e5fd2 |
+ suppress_disconnected=False, simplify=False, **attrs):
|
|
rdobuilder |
3e5fd2 |
|
|
rdobuilder |
3e5fd2 |
if obj_dict is not None:
|
|
rdobuilder |
3e5fd2 |
self.obj_dict = obj_dict
|
|
rdobuilder |
3e5fd2 |
-
|
|
rdobuilder |
3e5fd2 |
else:
|
|
rdobuilder |
3e5fd2 |
-
|
|
rdobuilder |
3e5fd2 |
self.obj_dict = dict()
|
|
rdobuilder |
3e5fd2 |
-
|
|
rdobuilder |
3e5fd2 |
+
|
|
rdobuilder |
3e5fd2 |
self.obj_dict['attributes'] = dict(attrs)
|
|
rdobuilder |
3e5fd2 |
-
|
|
rdobuilder |
3e5fd2 |
+
|
|
rdobuilder |
3e5fd2 |
if graph_type not in ['graph', 'digraph']:
|
|
rdobuilder |
3e5fd2 |
- raise Error, 'Invalid type "%s". Accepted graph types are: graph, digraph, subgraph' % graph_type
|
|
rdobuilder |
3e5fd2 |
-
|
|
rdobuilder |
3e5fd2 |
-
|
|
rdobuilder |
3e5fd2 |
+ raise Error((
|
|
rdobuilder |
3e5fd2 |
+ 'Invalid type "%s". Accepted graph types are: '
|
|
rdobuilder |
3e5fd2 |
+ 'graph, digraph, subgraph' % graph_type
|
|
rdobuilder |
3e5fd2 |
+ ))
|
|
rdobuilder |
3e5fd2 |
+
|
|
rdobuilder |
3e5fd2 |
self.obj_dict['name'] = quote_if_necessary(graph_name)
|
|
rdobuilder |
3e5fd2 |
self.obj_dict['type'] = graph_type
|
|
rdobuilder |
3e5fd2 |
-
|
|
rdobuilder |
3e5fd2 |
+
|
|
rdobuilder |
3e5fd2 |
self.obj_dict['strict'] = strict
|
|
rdobuilder |
3e5fd2 |
self.obj_dict['suppress_disconnected'] = suppress_disconnected
|
|
rdobuilder |
3e5fd2 |
self.obj_dict['simplify'] = simplify
|
|
rdobuilder |
3e5fd2 |
-
|
|
rdobuilder |
3e5fd2 |
+
|
|
rdobuilder |
3e5fd2 |
self.obj_dict['current_child_sequence'] = 1
|
|
rdobuilder |
3e5fd2 |
self.obj_dict['nodes'] = dict()
|
|
rdobuilder |
3e5fd2 |
self.obj_dict['edges'] = dict()
|
|
rdobuilder |
3e5fd2 |
self.obj_dict['subgraphs'] = dict()
|
|
rdobuilder |
3e5fd2 |
|
|
rdobuilder |
3e5fd2 |
self.set_parent_graph(self)
|
|
rdobuilder |
3e5fd2 |
-
|
|
rdobuilder |
3e5fd2 |
|
|
rdobuilder |
3e5fd2 |
self.create_attribute_methods(GRAPH_ATTRIBUTES)
|
|
rdobuilder |
3e5fd2 |
|
|
rdobuilder |
3e5fd2 |
-
|
|
rdobuilder |
3e5fd2 |
def get_graph_type(self):
|
|
rdobuilder |
3e5fd2 |
-
|
|
rdobuilder |
3e5fd2 |
return self.obj_dict['type']
|
|
rdobuilder |
3e5fd2 |
|
|
rdobuilder |
3e5fd2 |
-
|
|
rdobuilder |
3e5fd2 |
def get_top_graph_type(self):
|
|
rdobuilder |
3e5fd2 |
-
|
|
rdobuilder |
3e5fd2 |
parent = self
|
|
rdobuilder |
3e5fd2 |
while True:
|
|
rdobuilder |
3e5fd2 |
parent_ = parent.get_parent_graph()
|
|
rdobuilder |
3e5fd2 |
if parent_ == parent:
|
|
rdobuilder |
3e5fd2 |
break
|
|
rdobuilder |
3e5fd2 |
parent = parent_
|
|
rdobuilder |
3e5fd2 |
-
|
|
rdobuilder |
3e5fd2 |
+
|
|
rdobuilder |
3e5fd2 |
return parent.obj_dict['type']
|
|
rdobuilder |
3e5fd2 |
-
|
|
rdobuilder |
3e5fd2 |
|
|
rdobuilder |
3e5fd2 |
def set_graph_defaults(self, **attrs):
|
|
rdobuilder |
3e5fd2 |
-
|
|
rdobuilder |
3e5fd2 |
- self.add_node( Node('graph', **attrs) )
|
|
rdobuilder |
3e5fd2 |
-
|
|
rdobuilder |
3e5fd2 |
+ self.add_node(Node('graph', **attrs))
|
|
rdobuilder |
3e5fd2 |
|
|
rdobuilder |
3e5fd2 |
def get_graph_defaults(self, **attrs):
|
|
rdobuilder |
3e5fd2 |
-
|
|
rdobuilder |
3e5fd2 |
+
|
|
rdobuilder |
3e5fd2 |
graph_nodes = self.get_node('graph')
|
|
rdobuilder |
3e5fd2 |
-
|
|
rdobuilder |
3e5fd2 |
- if isinstance( graph_nodes, (list, tuple)):
|
|
rdobuilder |
3e5fd2 |
- return [ node.get_attributes() for node in graph_nodes ]
|
|
rdobuilder |
3e5fd2 |
-
|
|
rdobuilder |
3e5fd2 |
- return graph_nodes.get_attributes()
|
|
rdobuilder |
3e5fd2 |
-
|
|
rdobuilder |
3e5fd2 |
-
|
|
rdobuilder |
3e5fd2 |
|
|
rdobuilder |
3e5fd2 |
- def set_node_defaults(self, **attrs):
|
|
rdobuilder |
3e5fd2 |
+ if isinstance(graph_nodes, (list, tuple)):
|
|
rdobuilder |
3e5fd2 |
+ return [node.get_attributes() for node in graph_nodes]
|
|
rdobuilder |
3e5fd2 |
|
|
rdobuilder |
3e5fd2 |
- self.add_node( Node('node', **attrs) )
|
|
rdobuilder |
3e5fd2 |
+ return graph_nodes.get_attributes()
|
|
rdobuilder |
3e5fd2 |
|
|
rdobuilder |
3e5fd2 |
+ def set_node_defaults(self, **attrs):
|
|
rdobuilder |
3e5fd2 |
+ self.add_node(Node('node', **attrs))
|
|
rdobuilder |
3e5fd2 |
|
|
rdobuilder |
3e5fd2 |
def get_node_defaults(self, **attrs):
|
|
rdobuilder |
3e5fd2 |
-
|
|
rdobuilder |
3e5fd2 |
-
|
|
rdobuilder |
3e5fd2 |
graph_nodes = self.get_node('node')
|
|
rdobuilder |
3e5fd2 |
|
|
rdobuilder |
3e5fd2 |
- if isinstance( graph_nodes, (list, tuple)):
|
|
rdobuilder |
3e5fd2 |
- return [ node.get_attributes() for node in graph_nodes ]
|
|
rdobuilder |
3e5fd2 |
-
|
|
rdobuilder |
3e5fd2 |
- return graph_nodes.get_attributes()
|
|
rdobuilder |
3e5fd2 |
-
|
|
rdobuilder |
3e5fd2 |
-
|
|
rdobuilder |
3e5fd2 |
- def set_edge_defaults(self, **attrs):
|
|
rdobuilder |
3e5fd2 |
-
|
|
rdobuilder |
3e5fd2 |
- self.add_node( Node('edge', **attrs) )
|
|
rdobuilder |
3e5fd2 |
+ if isinstance(graph_nodes, (list, tuple)):
|
|
rdobuilder |
3e5fd2 |
+ return [node.get_attributes() for node in graph_nodes]
|
|
rdobuilder |
3e5fd2 |
|
|
rdobuilder |
3e5fd2 |
+ return graph_nodes.get_attributes()
|
|
rdobuilder |
3e5fd2 |
|
|
rdobuilder |
3e5fd2 |
+ def set_edge_defaults(self, **attrs):
|
|
rdobuilder |
3e5fd2 |
+ self.add_node(Node('edge', **attrs))
|
|
rdobuilder |
3e5fd2 |
|
|
rdobuilder |
3e5fd2 |
def get_edge_defaults(self, **attrs):
|
|
rdobuilder |
3e5fd2 |
-
|
|
rdobuilder |
3e5fd2 |
graph_nodes = self.get_node('edge')
|
|
rdobuilder |
3e5fd2 |
|
|
rdobuilder |
3e5fd2 |
- if isinstance( graph_nodes, (list, tuple)):
|
|
rdobuilder |
3e5fd2 |
- return [ node.get_attributes() for node in graph_nodes ]
|
|
rdobuilder |
3e5fd2 |
-
|
|
rdobuilder |
3e5fd2 |
- return graph_nodes.get_attributes()
|
|
rdobuilder |
3e5fd2 |
+ if isinstance(graph_nodes, (list, tuple)):
|
|
rdobuilder |
3e5fd2 |
+ return [node.get_attributes() for node in graph_nodes]
|
|
rdobuilder |
3e5fd2 |
|
|
rdobuilder |
3e5fd2 |
-
|
|
rdobuilder |
3e5fd2 |
+ return graph_nodes.get_attributes()
|
|
rdobuilder |
3e5fd2 |
|
|
rdobuilder |
3e5fd2 |
def set_simplify(self, simplify):
|
|
rdobuilder |
3e5fd2 |
"""Set whether to simplify or not.
|
|
rdobuilder |
3e5fd2 |
-
|
|
rdobuilder |
3e5fd2 |
+
|
|
rdobuilder |
3e5fd2 |
If True it will avoid displaying equal edges, i.e.
|
|
rdobuilder |
3e5fd2 |
only one edge between two nodes. removing the
|
|
rdobuilder |
3e5fd2 |
duplicated ones.
|
|
rdobuilder |
3e5fd2 |
"""
|
|
rdobuilder |
3e5fd2 |
-
|
|
rdobuilder |
3e5fd2 |
- self.obj_dict['simplify'] = simplify
|
|
rdobuilder |
3e5fd2 |
-
|
|
rdobuilder |
3e5fd2 |
|
|
rdobuilder |
3e5fd2 |
+ self.obj_dict['simplify'] = simplify
|
|
rdobuilder |
3e5fd2 |
|
|
rdobuilder |
3e5fd2 |
def get_simplify(self):
|
|
rdobuilder |
3e5fd2 |
"""Get whether to simplify or not.
|
|
rdobuilder |
3e5fd2 |
-
|
|
rdobuilder |
3e5fd2 |
+
|
|
rdobuilder |
3e5fd2 |
Refer to set_simplify for more information.
|
|
rdobuilder |
3e5fd2 |
"""
|
|
rdobuilder |
3e5fd2 |
-
|
|
rdobuilder |
3e5fd2 |
+
|
|
rdobuilder |
3e5fd2 |
return self.obj_dict['simplify']
|
|
rdobuilder |
3e5fd2 |
|
|
rdobuilder |
3e5fd2 |
-
|
|
rdobuilder |
3e5fd2 |
def set_type(self, graph_type):
|
|
rdobuilder |
3e5fd2 |
"""Set the graph's type, 'graph' or 'digraph'."""
|
|
rdobuilder |
3e5fd2 |
|
|
rdobuilder |
3e5fd2 |
self.obj_dict['type'] = graph_type
|
|
rdobuilder |
3e5fd2 |
|
|
rdobuilder |
3e5fd2 |
-
|
|
rdobuilder |
3e5fd2 |
-
|
|
rdobuilder |
3e5fd2 |
def get_type(self):
|
|
rdobuilder |
3e5fd2 |
"""Get the graph's type, 'graph' or 'digraph'."""
|
|
rdobuilder |
3e5fd2 |
|
|
rdobuilder |
3e5fd2 |
return self.obj_dict['type']
|
|
rdobuilder |
3e5fd2 |
|
|
rdobuilder |
3e5fd2 |
-
|
|
rdobuilder |
3e5fd2 |
-
|
|
rdobuilder |
3e5fd2 |
def set_name(self, graph_name):
|
|
rdobuilder |
3e5fd2 |
"""Set the graph's name."""
|
|
rdobuilder |
3e5fd2 |
-
|
|
rdobuilder |
3e5fd2 |
- self.obj_dict['name'] = graph_name
|
|
rdobuilder |
3e5fd2 |
-
|
|
rdobuilder |
3e5fd2 |
|
|
rdobuilder |
3e5fd2 |
+ self.obj_dict['name'] = graph_name
|
|
rdobuilder |
3e5fd2 |
|
|
rdobuilder |
3e5fd2 |
def get_name(self):
|
|
rdobuilder |
3e5fd2 |
"""Get the graph's name."""
|
|
rdobuilder |
3e5fd2 |
-
|
|
rdobuilder |
3e5fd2 |
- return self.obj_dict['name']
|
|
rdobuilder |
3e5fd2 |
|
|
rdobuilder |
3e5fd2 |
+ return self.obj_dict['name']
|
|
rdobuilder |
3e5fd2 |
|
|
rdobuilder |
3e5fd2 |
-
|
|
rdobuilder |
3e5fd2 |
def set_strict(self, val):
|
|
rdobuilder |
3e5fd2 |
"""Set graph to 'strict' mode.
|
|
rdobuilder |
3e5fd2 |
-
|
|
rdobuilder |
3e5fd2 |
+
|
|
rdobuilder |
3e5fd2 |
This option is only valid for top level graphs.
|
|
rdobuilder |
3e5fd2 |
"""
|
|
rdobuilder |
3e5fd2 |
-
|
|
rdobuilder |
3e5fd2 |
- self.obj_dict['strict'] = val
|
|
rdobuilder |
3e5fd2 |
-
|
|
rdobuilder |
3e5fd2 |
|
|
rdobuilder |
3e5fd2 |
+ self.obj_dict['strict'] = val
|
|
rdobuilder |
3e5fd2 |
|
|
rdobuilder |
3e5fd2 |
def get_strict(self, val):
|
|
rdobuilder |
3e5fd2 |
"""Get graph's 'strict' mode (True, False).
|
|
rdobuilder |
3e5fd2 |
-
|
|
rdobuilder |
3e5fd2 |
+
|
|
rdobuilder |
3e5fd2 |
This option is only valid for top level graphs.
|
|
rdobuilder |
3e5fd2 |
"""
|
|
rdobuilder |
3e5fd2 |
-
|
|
rdobuilder |
3e5fd2 |
- return self.obj_dict['strict']
|
|
rdobuilder |
3e5fd2 |
-
|
|
rdobuilder |
3e5fd2 |
|
|
rdobuilder |
3e5fd2 |
+ return self.obj_dict['strict']
|
|
rdobuilder |
3e5fd2 |
|
|
rdobuilder |
3e5fd2 |
def set_suppress_disconnected(self, val):
|
|
rdobuilder |
3e5fd2 |
"""Suppress disconnected nodes in the output graph.
|
|
rdobuilder |
3e5fd2 |
-
|
|
rdobuilder |
3e5fd2 |
+
|
|
rdobuilder |
3e5fd2 |
This option will skip nodes in the graph with no incoming or outgoing
|
|
rdobuilder |
3e5fd2 |
edges. This option works also for subgraphs and has effect only in the
|
|
rdobuilder |
3e5fd2 |
current graph/subgraph.
|
|
rdobuilder |
3e5fd2 |
"""
|
|
rdobuilder |
3e5fd2 |
-
|
|
rdobuilder |
3e5fd2 |
- self.obj_dict['suppress_disconnected'] = val
|
|
rdobuilder |
3e5fd2 |
-
|
|
rdobuilder |
3e5fd2 |
|
|
rdobuilder |
3e5fd2 |
+ self.obj_dict['suppress_disconnected'] = val
|
|
rdobuilder |
3e5fd2 |
|
|
rdobuilder |
3e5fd2 |
def get_suppress_disconnected(self, val):
|
|
rdobuilder |
3e5fd2 |
"""Get if suppress disconnected is set.
|
|
rdobuilder |
3e5fd2 |
-
|
|
rdobuilder |
3e5fd2 |
+
|
|
rdobuilder |
3e5fd2 |
Refer to set_suppress_disconnected for more information.
|
|
rdobuilder |
3e5fd2 |
"""
|
|
rdobuilder |
3e5fd2 |
-
|
|
rdobuilder |
3e5fd2 |
+
|
|
rdobuilder |
3e5fd2 |
return self.obj_dict['suppress_disconnected']
|
|
rdobuilder |
3e5fd2 |
-
|
|
rdobuilder |
3e5fd2 |
|
|
rdobuilder |
3e5fd2 |
def get_next_sequence_number(self):
|
|
rdobuilder |
3e5fd2 |
-
|
|
rdobuilder |
3e5fd2 |
seq = self.obj_dict['current_child_sequence']
|
|
rdobuilder |
3e5fd2 |
-
|
|
rdobuilder |
3e5fd2 |
self.obj_dict['current_child_sequence'] += 1
|
|
rdobuilder |
3e5fd2 |
-
|
|
rdobuilder |
3e5fd2 |
return seq
|
|
rdobuilder |
3e5fd2 |
-
|
|
rdobuilder |
3e5fd2 |
-
|
|
rdobuilder |
3e5fd2 |
|
|
rdobuilder |
3e5fd2 |
def add_node(self, graph_node):
|
|
rdobuilder |
3e5fd2 |
"""Adds a node object to the graph.
|
|
rdobuilder |
3e5fd2 |
@@ -1268,106 +1242,101 @@ class Graph(object, Common):
|
|
rdobuilder |
3e5fd2 |
It takes a node object as its only argument and returns
|
|
rdobuilder |
3e5fd2 |
None.
|
|
rdobuilder |
3e5fd2 |
"""
|
|
rdobuilder |
3e5fd2 |
-
|
|
rdobuilder |
3e5fd2 |
+
|
|
rdobuilder |
3e5fd2 |
if not isinstance(graph_node, Node):
|
|
rdobuilder |
3e5fd2 |
raise TypeError('add_node() received a non node class object: ' + str(graph_node))
|
|
rdobuilder |
3e5fd2 |
|
|
rdobuilder |
3e5fd2 |
-
|
|
rdobuilder |
3e5fd2 |
node = self.get_node(graph_node.get_name())
|
|
rdobuilder |
3e5fd2 |
-
|
|
rdobuilder |
3e5fd2 |
+
|
|
rdobuilder |
3e5fd2 |
if not node:
|
|
rdobuilder |
3e5fd2 |
+ self.obj_dict['nodes'][graph_node.get_name()] = [graph_node.obj_dict]
|
|
rdobuilder |
3e5fd2 |
|
|
rdobuilder |
3e5fd2 |
- self.obj_dict['nodes'][graph_node.get_name()] = [ graph_node.obj_dict ]
|
|
rdobuilder |
3e5fd2 |
-
|
|
rdobuilder |
3e5fd2 |
#self.node_dict[graph_node.get_name()] = graph_node.attributes
|
|
rdobuilder |
3e5fd2 |
graph_node.set_parent_graph(self.get_parent_graph())
|
|
rdobuilder |
3e5fd2 |
-
|
|
rdobuilder |
3e5fd2 |
else:
|
|
rdobuilder |
3e5fd2 |
-
|
|
rdobuilder |
3e5fd2 |
- self.obj_dict['nodes'][graph_node.get_name()].append( graph_node.obj_dict )
|
|
rdobuilder |
3e5fd2 |
+ self.obj_dict['nodes'][graph_node.get_name()].append(graph_node.obj_dict)
|
|
rdobuilder |
3e5fd2 |
|
|
rdobuilder |
3e5fd2 |
graph_node.set_sequence(self.get_next_sequence_number())
|
|
rdobuilder |
3e5fd2 |
|
|
rdobuilder |
3e5fd2 |
-
|
|
rdobuilder |
3e5fd2 |
-
|
|
rdobuilder |
3e5fd2 |
def del_node(self, name, index=None):
|
|
rdobuilder |
3e5fd2 |
"""Delete a node from the graph.
|
|
rdobuilder |
3e5fd2 |
-
|
|
rdobuilder |
3e5fd2 |
+
|
|
rdobuilder |
3e5fd2 |
Given a node's name all node(s) with that same name
|
|
rdobuilder |
3e5fd2 |
will be deleted if 'index' is not specified or set
|
|
rdobuilder |
3e5fd2 |
to None.
|
|
rdobuilder |
3e5fd2 |
If there are several nodes with that same name and
|
|
rdobuilder |
3e5fd2 |
'index' is given, only the node in that position
|
|
rdobuilder |
3e5fd2 |
will be deleted.
|
|
rdobuilder |
3e5fd2 |
-
|
|
rdobuilder |
3e5fd2 |
- 'index' should be an integer specifying the position
|
|
rdobuilder |
3e5fd2 |
+
|
|
rdobuilder |
3e5fd2 |
+ 'index' should be an integer specifying the position
|
|
rdobuilder |
3e5fd2 |
of the node to delete. If index is larger than the
|
|
rdobuilder |
3e5fd2 |
number of nodes with that name, no action is taken.
|
|
rdobuilder |
3e5fd2 |
-
|
|
rdobuilder |
3e5fd2 |
+
|
|
rdobuilder |
3e5fd2 |
If nodes are deleted it returns True. If no action
|
|
rdobuilder |
3e5fd2 |
is taken it returns False.
|
|
rdobuilder |
3e5fd2 |
"""
|
|
rdobuilder |
3e5fd2 |
-
|
|
rdobuilder |
3e5fd2 |
+
|
|
rdobuilder |
3e5fd2 |
if isinstance(name, Node):
|
|
rdobuilder |
3e5fd2 |
name = name.get_name()
|
|
rdobuilder |
3e5fd2 |
-
|
|
rdobuilder |
3e5fd2 |
- if self.obj_dict['nodes'].has_key(name):
|
|
rdobuilder |
3e5fd2 |
-
|
|
rdobuilder |
3e5fd2 |
+
|
|
rdobuilder |
3e5fd2 |
+ if name in self.obj_dict['nodes']:
|
|
rdobuilder |
3e5fd2 |
if index is not None and index < len(self.obj_dict['nodes'][name]):
|
|
rdobuilder |
3e5fd2 |
del self.obj_dict['nodes'][name][index]
|
|
rdobuilder |
3e5fd2 |
return True
|
|
rdobuilder |
3e5fd2 |
else:
|
|
rdobuilder |
3e5fd2 |
del self.obj_dict['nodes'][name]
|
|
rdobuilder |
3e5fd2 |
return True
|
|
rdobuilder |
3e5fd2 |
-
|
|
rdobuilder |
3e5fd2 |
+
|
|
rdobuilder |
3e5fd2 |
return False
|
|
rdobuilder |
3e5fd2 |
-
|
|
rdobuilder |
3e5fd2 |
|
|
rdobuilder |
3e5fd2 |
def get_node(self, name):
|
|
rdobuilder |
3e5fd2 |
"""Retrieve a node from the graph.
|
|
rdobuilder |
3e5fd2 |
-
|
|
rdobuilder |
3e5fd2 |
+
|
|
rdobuilder |
3e5fd2 |
Given a node's name the corresponding Node
|
|
rdobuilder |
3e5fd2 |
instance will be returned.
|
|
rdobuilder |
3e5fd2 |
-
|
|
rdobuilder |
3e5fd2 |
+
|
|
rdobuilder |
3e5fd2 |
If one or more nodes exist with that name a list of
|
|
rdobuilder |
3e5fd2 |
Node instances is returned.
|
|
rdobuilder |
3e5fd2 |
An empty list is returned otherwise.
|
|
rdobuilder |
3e5fd2 |
"""
|
|
rdobuilder |
3e5fd2 |
-
|
|
rdobuilder |
3e5fd2 |
+
|
|
rdobuilder |
3e5fd2 |
match = list()
|
|
rdobuilder |
3e5fd2 |
-
|
|
rdobuilder |
3e5fd2 |
- if self.obj_dict['nodes'].has_key(name):
|
|
rdobuilder |
3e5fd2 |
-
|
|
rdobuilder |
3e5fd2 |
- match.extend( [ Node( obj_dict = obj_dict ) for obj_dict in self.obj_dict['nodes'][name] ])
|
|
rdobuilder |
3e5fd2 |
-
|
|
rdobuilder |
3e5fd2 |
- return match
|
|
rdobuilder |
3e5fd2 |
|
|
rdobuilder |
3e5fd2 |
+ if name in self.obj_dict['nodes']:
|
|
rdobuilder |
3e5fd2 |
+ match.extend([
|
|
rdobuilder |
3e5fd2 |
+ Node(obj_dict=obj_dict)
|
|
rdobuilder |
3e5fd2 |
+ for obj_dict
|
|
rdobuilder |
3e5fd2 |
+ in self.obj_dict['nodes'][name]
|
|
rdobuilder |
3e5fd2 |
+ ])
|
|
rdobuilder |
3e5fd2 |
+
|
|
rdobuilder |
3e5fd2 |
+ return match
|
|
rdobuilder |
3e5fd2 |
|
|
rdobuilder |
3e5fd2 |
def get_nodes(self):
|
|
rdobuilder |
3e5fd2 |
"""Get the list of Node instances."""
|
|
rdobuilder |
3e5fd2 |
-
|
|
rdobuilder |
3e5fd2 |
+
|
|
rdobuilder |
3e5fd2 |
return self.get_node_list()
|
|
rdobuilder |
3e5fd2 |
-
|
|
rdobuilder |
3e5fd2 |
-
|
|
rdobuilder |
3e5fd2 |
+
|
|
rdobuilder |
3e5fd2 |
def get_node_list(self):
|
|
rdobuilder |
3e5fd2 |
"""Get the list of Node instances.
|
|
rdobuilder |
3e5fd2 |
-
|
|
rdobuilder |
3e5fd2 |
+
|
|
rdobuilder |
3e5fd2 |
This method returns the list of Node instances
|
|
rdobuilder |
3e5fd2 |
composing the graph.
|
|
rdobuilder |
3e5fd2 |
"""
|
|
rdobuilder |
3e5fd2 |
-
|
|
rdobuilder |
3e5fd2 |
+
|
|
rdobuilder |
3e5fd2 |
node_objs = list()
|
|
rdobuilder |
3e5fd2 |
-
|
|
rdobuilder |
3e5fd2 |
- for node, obj_dict_list in self.obj_dict['nodes'].iteritems():
|
|
rdobuilder |
3e5fd2 |
- node_objs.extend( [ Node( obj_dict = obj_d ) for obj_d in obj_dict_list ] )
|
|
rdobuilder |
3e5fd2 |
-
|
|
rdobuilder |
3e5fd2 |
- return node_objs
|
|
rdobuilder |
3e5fd2 |
|
|
rdobuilder |
3e5fd2 |
+ for node, obj_dict_list in self.obj_dict['nodes'].items():
|
|
rdobuilder |
3e5fd2 |
+ node_objs.extend([
|
|
rdobuilder |
3e5fd2 |
+ Node(obj_dict=obj_d)
|
|
rdobuilder |
3e5fd2 |
+ for obj_d
|
|
rdobuilder |
3e5fd2 |
+ in obj_dict_list
|
|
rdobuilder |
3e5fd2 |
+ ])
|
|
rdobuilder |
3e5fd2 |
|
|
rdobuilder |
3e5fd2 |
+ return node_objs
|
|
rdobuilder |
3e5fd2 |
|
|
rdobuilder |
3e5fd2 |
def add_edge(self, graph_edge):
|
|
rdobuilder |
3e5fd2 |
"""Adds an edge object to the graph.
|
|
rdobuilder |
3e5fd2 |
-
|
|
rdobuilder |
3e5fd2 |
+
|
|
rdobuilder |
3e5fd2 |
It takes a edge object as its only argument and returns
|
|
rdobuilder |
3e5fd2 |
None.
|
|
rdobuilder |
3e5fd2 |
"""
|
|
rdobuilder |
3e5fd2 |
@@ -1375,78 +1344,70 @@ class Graph(object, Common):
|
|
rdobuilder |
3e5fd2 |
if not isinstance(graph_edge, Edge):
|
|
rdobuilder |
3e5fd2 |
raise TypeError('add_edge() received a non edge class object: ' + str(graph_edge))
|
|
rdobuilder |
3e5fd2 |
|
|
rdobuilder |
3e5fd2 |
- edge_points = ( graph_edge.get_source(), graph_edge.get_destination() )
|
|
rdobuilder |
3e5fd2 |
+ edge_points = (graph_edge.get_source(), graph_edge.get_destination())
|
|
rdobuilder |
3e5fd2 |
|
|
rdobuilder |
3e5fd2 |
- if self.obj_dict['edges'].has_key(edge_points):
|
|
rdobuilder |
3e5fd2 |
+ if edge_points in self.obj_dict['edges']:
|
|
rdobuilder |
3e5fd2 |
|
|
rdobuilder |
3e5fd2 |
edge_list = self.obj_dict['edges'][edge_points]
|
|
rdobuilder |
3e5fd2 |
edge_list.append(graph_edge.obj_dict)
|
|
rdobuilder |
3e5fd2 |
-
|
|
rdobuilder |
3e5fd2 |
else:
|
|
rdobuilder |
3e5fd2 |
+ self.obj_dict['edges'][edge_points] = [graph_edge.obj_dict]
|
|
rdobuilder |
3e5fd2 |
|
|
rdobuilder |
3e5fd2 |
- self.obj_dict['edges'][edge_points] = [ graph_edge.obj_dict ]
|
|
rdobuilder |
3e5fd2 |
-
|
|
rdobuilder |
3e5fd2 |
-
|
|
rdobuilder |
3e5fd2 |
- graph_edge.set_sequence( self.get_next_sequence_number() )
|
|
rdobuilder |
3e5fd2 |
-
|
|
rdobuilder |
3e5fd2 |
- graph_edge.set_parent_graph( self.get_parent_graph() )
|
|
rdobuilder |
3e5fd2 |
-
|
|
rdobuilder |
3e5fd2 |
-
|
|
rdobuilder |
3e5fd2 |
+ graph_edge.set_sequence(self.get_next_sequence_number())
|
|
rdobuilder |
3e5fd2 |
+ graph_edge.set_parent_graph(self.get_parent_graph())
|
|
rdobuilder |
3e5fd2 |
|
|
rdobuilder |
3e5fd2 |
def del_edge(self, src_or_list, dst=None, index=None):
|
|
rdobuilder |
3e5fd2 |
"""Delete an edge from the graph.
|
|
rdobuilder |
3e5fd2 |
-
|
|
rdobuilder |
3e5fd2 |
+
|
|
rdobuilder |
3e5fd2 |
Given an edge's (source, destination) node names all
|
|
rdobuilder |
3e5fd2 |
matching edges(s) will be deleted if 'index' is not
|
|
rdobuilder |
3e5fd2 |
specified or set to None.
|
|
rdobuilder |
3e5fd2 |
If there are several matching edges and 'index' is
|
|
rdobuilder |
3e5fd2 |
given, only the edge in that position will be deleted.
|
|
rdobuilder |
3e5fd2 |
-
|
|
rdobuilder |
3e5fd2 |
- 'index' should be an integer specifying the position
|
|
rdobuilder |
3e5fd2 |
+
|
|
rdobuilder |
3e5fd2 |
+ 'index' should be an integer specifying the position
|
|
rdobuilder |
3e5fd2 |
of the edge to delete. If index is larger than the
|
|
rdobuilder |
3e5fd2 |
number of matching edges, no action is taken.
|
|
rdobuilder |
3e5fd2 |
-
|
|
rdobuilder |
3e5fd2 |
+
|
|
rdobuilder |
3e5fd2 |
If edges are deleted it returns True. If no action
|
|
rdobuilder |
3e5fd2 |
is taken it returns False.
|
|
rdobuilder |
3e5fd2 |
"""
|
|
rdobuilder |
3e5fd2 |
|
|
rdobuilder |
3e5fd2 |
- if isinstance( src_or_list, (list, tuple)):
|
|
rdobuilder |
3e5fd2 |
+ if isinstance(src_or_list, (list, tuple)):
|
|
rdobuilder |
3e5fd2 |
if dst is not None and isinstance(dst, (int, long)):
|
|
rdobuilder |
3e5fd2 |
index = dst
|
|
rdobuilder |
3e5fd2 |
src, dst = src_or_list
|
|
rdobuilder |
3e5fd2 |
else:
|
|
rdobuilder |
3e5fd2 |
src, dst = src_or_list, dst
|
|
rdobuilder |
3e5fd2 |
-
|
|
rdobuilder |
3e5fd2 |
+
|
|
rdobuilder |
3e5fd2 |
if isinstance(src, Node):
|
|
rdobuilder |
3e5fd2 |
src = src.get_name()
|
|
rdobuilder |
3e5fd2 |
|
|
rdobuilder |
3e5fd2 |
if isinstance(dst, Node):
|
|
rdobuilder |
3e5fd2 |
dst = dst.get_name()
|
|
rdobuilder |
3e5fd2 |
-
|
|
rdobuilder |
3e5fd2 |
- if self.obj_dict['edges'].has_key( (src, dst) ):
|
|
rdobuilder |
3e5fd2 |
-
|
|
rdobuilder |
3e5fd2 |
+
|
|
rdobuilder |
3e5fd2 |
+ if (src, dst) in self.obj_dict['edges']:
|
|
rdobuilder |
3e5fd2 |
if index is not None and index < len(self.obj_dict['edges'][(src, dst)]):
|
|
rdobuilder |
3e5fd2 |
del self.obj_dict['edges'][(src, dst)][index]
|
|
rdobuilder |
3e5fd2 |
return True
|
|
rdobuilder |
3e5fd2 |
else:
|
|
rdobuilder |
3e5fd2 |
del self.obj_dict['edges'][(src, dst)]
|
|
rdobuilder |
3e5fd2 |
return True
|
|
rdobuilder |
3e5fd2 |
-
|
|
rdobuilder |
3e5fd2 |
+
|
|
rdobuilder |
3e5fd2 |
return False
|
|
rdobuilder |
3e5fd2 |
-
|
|
rdobuilder |
3e5fd2 |
|
|
rdobuilder |
3e5fd2 |
def get_edge(self, src_or_list, dst=None):
|
|
rdobuilder |
3e5fd2 |
"""Retrieved an edge from the graph.
|
|
rdobuilder |
3e5fd2 |
-
|
|
rdobuilder |
3e5fd2 |
+
|
|
rdobuilder |
3e5fd2 |
Given an edge's source and destination the corresponding
|
|
rdobuilder |
3e5fd2 |
Edge instance(s) will be returned.
|
|
rdobuilder |
3e5fd2 |
-
|
|
rdobuilder |
3e5fd2 |
+
|
|
rdobuilder |
3e5fd2 |
If one or more edges exist with that source and destination
|
|
rdobuilder |
3e5fd2 |
a list of Edge instances is returned.
|
|
rdobuilder |
3e5fd2 |
An empty list is returned otherwise.
|
|
rdobuilder |
3e5fd2 |
"""
|
|
rdobuilder |
3e5fd2 |
|
|
rdobuilder |
3e5fd2 |
- if isinstance( src_or_list, (list, tuple)) and dst is None:
|
|
rdobuilder |
3e5fd2 |
+ if isinstance(src_or_list, (list, tuple)) and dst is None:
|
|
rdobuilder |
3e5fd2 |
edge_points = tuple(src_or_list)
|
|
rdobuilder |
3e5fd2 |
edge_points_reverse = (edge_points[1], edge_points[0])
|
|
rdobuilder |
3e5fd2 |
else:
|
|
rdobuilder |
3e5fd2 |
@@ -1454,224 +1415,205 @@ class Graph(object, Common):
|
|
rdobuilder |
3e5fd2 |
edge_points_reverse = (dst, src_or_list)
|
|
rdobuilder |
3e5fd2 |
|
|
rdobuilder |
3e5fd2 |
match = list()
|
|
rdobuilder |
3e5fd2 |
-
|
|
rdobuilder |
3e5fd2 |
- if self.obj_dict['edges'].has_key( edge_points ) or (
|
|
rdobuilder |
3e5fd2 |
- self.get_top_graph_type() == 'graph' and self.obj_dict['edges'].has_key( edge_points_reverse )):
|
|
rdobuilder |
3e5fd2 |
-
|
|
rdobuilder |
3e5fd2 |
+
|
|
rdobuilder |
3e5fd2 |
+ if edge_points in self.obj_dict['edges'] or (
|
|
rdobuilder |
3e5fd2 |
+ self.get_top_graph_type() == 'graph' and
|
|
rdobuilder |
3e5fd2 |
+ edge_points_reverse in self.obj_dict['edges']
|
|
rdobuilder |
3e5fd2 |
+ ):
|
|
rdobuilder |
3e5fd2 |
+
|
|
rdobuilder |
3e5fd2 |
edges_obj_dict = self.obj_dict['edges'].get(
|
|
rdobuilder |
3e5fd2 |
edge_points,
|
|
rdobuilder |
3e5fd2 |
- self.obj_dict['edges'].get( edge_points_reverse, None ))
|
|
rdobuilder |
3e5fd2 |
-
|
|
rdobuilder |
3e5fd2 |
+ self.obj_dict['edges'].get(edge_points_reverse, None))
|
|
rdobuilder |
3e5fd2 |
+
|
|
rdobuilder |
3e5fd2 |
for edge_obj_dict in edges_obj_dict:
|
|
rdobuilder |
3e5fd2 |
- match.append( Edge( edge_points[0], edge_points[1], obj_dict = edge_obj_dict ) )
|
|
rdobuilder |
3e5fd2 |
+ match.append(
|
|
rdobuilder |
3e5fd2 |
+ Edge(edge_points[0], edge_points[1], obj_dict=edge_obj_dict)
|
|
rdobuilder |
3e5fd2 |
+ )
|
|
rdobuilder |
3e5fd2 |
|
|
rdobuilder |
3e5fd2 |
return match
|
|
rdobuilder |
3e5fd2 |
|
|
rdobuilder |
3e5fd2 |
-
|
|
rdobuilder |
3e5fd2 |
def get_edges(self):
|
|
rdobuilder |
3e5fd2 |
return self.get_edge_list()
|
|
rdobuilder |
3e5fd2 |
-
|
|
rdobuilder |
3e5fd2 |
-
|
|
rdobuilder |
3e5fd2 |
+
|
|
rdobuilder |
3e5fd2 |
def get_edge_list(self):
|
|
rdobuilder |
3e5fd2 |
"""Get the list of Edge instances.
|
|
rdobuilder |
3e5fd2 |
-
|
|
rdobuilder |
3e5fd2 |
+
|
|
rdobuilder |
3e5fd2 |
This method returns the list of Edge instances
|
|
rdobuilder |
3e5fd2 |
composing the graph.
|
|
rdobuilder |
3e5fd2 |
"""
|
|
rdobuilder |
3e5fd2 |
-
|
|
rdobuilder |
3e5fd2 |
+
|
|
rdobuilder |
3e5fd2 |
edge_objs = list()
|
|
rdobuilder |
3e5fd2 |
-
|
|
rdobuilder |
3e5fd2 |
- for edge, obj_dict_list in self.obj_dict['edges'].iteritems():
|
|
rdobuilder |
3e5fd2 |
- edge_objs.extend( [ Edge( obj_dict = obj_d ) for obj_d in obj_dict_list ] )
|
|
rdobuilder |
3e5fd2 |
-
|
|
rdobuilder |
3e5fd2 |
- return edge_objs
|
|
rdobuilder |
3e5fd2 |
|
|
rdobuilder |
3e5fd2 |
+ for edge, obj_dict_list in self.obj_dict['edges'].items():
|
|
rdobuilder |
3e5fd2 |
+ edge_objs.extend([
|
|
rdobuilder |
3e5fd2 |
+ Edge(obj_dict=obj_d)
|
|
rdobuilder |
3e5fd2 |
+ for obj_d
|
|
rdobuilder |
3e5fd2 |
+ in obj_dict_list
|
|
rdobuilder |
3e5fd2 |
+ ])
|
|
rdobuilder |
3e5fd2 |
+
|
|
rdobuilder |
3e5fd2 |
+ return edge_objs
|
|
rdobuilder |
3e5fd2 |
|
|
rdobuilder |
3e5fd2 |
-
|
|
rdobuilder |
3e5fd2 |
def add_subgraph(self, sgraph):
|
|
rdobuilder |
3e5fd2 |
"""Adds an subgraph object to the graph.
|
|
rdobuilder |
3e5fd2 |
-
|
|
rdobuilder |
3e5fd2 |
+
|
|
rdobuilder |
3e5fd2 |
It takes a subgraph object as its only argument and returns
|
|
rdobuilder |
3e5fd2 |
None.
|
|
rdobuilder |
3e5fd2 |
"""
|
|
rdobuilder |
3e5fd2 |
|
|
rdobuilder |
3e5fd2 |
if not isinstance(sgraph, Subgraph) and not isinstance(sgraph, Cluster):
|
|
rdobuilder |
3e5fd2 |
raise TypeError('add_subgraph() received a non subgraph class object:' + str(sgraph))
|
|
rdobuilder |
3e5fd2 |
-
|
|
rdobuilder |
3e5fd2 |
- if self.obj_dict['subgraphs'].has_key(sgraph.get_name()):
|
|
rdobuilder |
3e5fd2 |
-
|
|
rdobuilder |
3e5fd2 |
- sgraph_list = self.obj_dict['subgraphs'][ sgraph.get_name() ]
|
|
rdobuilder |
3e5fd2 |
- sgraph_list.append( sgraph.obj_dict )
|
|
rdobuilder |
3e5fd2 |
-
|
|
rdobuilder |
3e5fd2 |
+
|
|
rdobuilder |
3e5fd2 |
+ if sgraph.get_name() in self.obj_dict['subgraphs']:
|
|
rdobuilder |
3e5fd2 |
+
|
|
rdobuilder |
3e5fd2 |
+ sgraph_list = self.obj_dict['subgraphs'][sgraph.get_name()]
|
|
rdobuilder |
3e5fd2 |
+ sgraph_list.append(sgraph.obj_dict)
|
|
rdobuilder |
3e5fd2 |
+
|
|
rdobuilder |
3e5fd2 |
else:
|
|
rdobuilder |
3e5fd2 |
- self.obj_dict['subgraphs'][ sgraph.get_name() ] = [ sgraph.obj_dict ]
|
|
rdobuilder |
3e5fd2 |
-
|
|
rdobuilder |
3e5fd2 |
- sgraph.set_sequence( self.get_next_sequence_number() )
|
|
rdobuilder |
3e5fd2 |
-
|
|
rdobuilder |
3e5fd2 |
- sgraph.set_parent_graph( self.get_parent_graph() )
|
|
rdobuilder |
3e5fd2 |
+ self.obj_dict['subgraphs'][sgraph.get_name()] = [sgraph.obj_dict]
|
|
rdobuilder |
3e5fd2 |
|
|
rdobuilder |
3e5fd2 |
+ sgraph.set_sequence(self.get_next_sequence_number())
|
|
rdobuilder |
3e5fd2 |
|
|
rdobuilder |
3e5fd2 |
+ sgraph.set_parent_graph(self.get_parent_graph())
|
|
rdobuilder |
3e5fd2 |
|
|
rdobuilder |
3e5fd2 |
-
|
|
rdobuilder |
3e5fd2 |
def get_subgraph(self, name):
|
|
rdobuilder |
3e5fd2 |
"""Retrieved a subgraph from the graph.
|
|
rdobuilder |
3e5fd2 |
-
|
|
rdobuilder |
3e5fd2 |
+
|
|
rdobuilder |
3e5fd2 |
Given a subgraph's name the corresponding
|
|
rdobuilder |
3e5fd2 |
Subgraph instance will be returned.
|
|
rdobuilder |
3e5fd2 |
-
|
|
rdobuilder |
3e5fd2 |
+
|
|
rdobuilder |
3e5fd2 |
If one or more subgraphs exist with the same name, a list of
|
|
rdobuilder |
3e5fd2 |
Subgraph instances is returned.
|
|
rdobuilder |
3e5fd2 |
An empty list is returned otherwise.
|
|
rdobuilder |
3e5fd2 |
"""
|
|
rdobuilder |
3e5fd2 |
-
|
|
rdobuilder |
3e5fd2 |
+
|
|
rdobuilder |
3e5fd2 |
match = list()
|
|
rdobuilder |
3e5fd2 |
-
|
|
rdobuilder |
3e5fd2 |
- if self.obj_dict['subgraphs'].has_key( name ):
|
|
rdobuilder |
3e5fd2 |
-
|
|
rdobuilder |
3e5fd2 |
- sgraphs_obj_dict = self.obj_dict['subgraphs'].get( name )
|
|
rdobuilder |
3e5fd2 |
-
|
|
rdobuilder |
3e5fd2 |
+
|
|
rdobuilder |
3e5fd2 |
+ if name in self.obj_dict['subgraphs']:
|
|
rdobuilder |
3e5fd2 |
+ sgraphs_obj_dict = self.obj_dict['subgraphs'].get(name)
|
|
rdobuilder |
3e5fd2 |
+
|
|
rdobuilder |
3e5fd2 |
for obj_dict_list in sgraphs_obj_dict:
|
|
rdobuilder |
3e5fd2 |
- #match.extend( Subgraph( obj_dict = obj_d ) for obj_d in obj_dict_list )
|
|
rdobuilder |
3e5fd2 |
- match.append( Subgraph( obj_dict = obj_dict_list ) )
|
|
rdobuilder |
3e5fd2 |
-
|
|
rdobuilder |
3e5fd2 |
- return match
|
|
rdobuilder |
3e5fd2 |
+ #match.extend(Subgraph(obj_dict = obj_d) for obj_d in obj_dict_list)
|
|
rdobuilder |
3e5fd2 |
+ match.append(Subgraph(obj_dict=obj_dict_list))
|
|
rdobuilder |
3e5fd2 |
|
|
rdobuilder |
3e5fd2 |
+ return match
|
|
rdobuilder |
3e5fd2 |
|
|
rdobuilder |
3e5fd2 |
def get_subgraphs(self):
|
|
rdobuilder |
3e5fd2 |
-
|
|
rdobuilder |
3e5fd2 |
return self.get_subgraph_list()
|
|
rdobuilder |
3e5fd2 |
-
|
|
rdobuilder |
3e5fd2 |
-
|
|
rdobuilder |
3e5fd2 |
+
|
|
rdobuilder |
3e5fd2 |
def get_subgraph_list(self):
|
|
rdobuilder |
3e5fd2 |
"""Get the list of Subgraph instances.
|
|
rdobuilder |
3e5fd2 |
-
|
|
rdobuilder |
3e5fd2 |
+
|
|
rdobuilder |
3e5fd2 |
This method returns the list of Subgraph instances
|
|
rdobuilder |
3e5fd2 |
in the graph.
|
|
rdobuilder |
3e5fd2 |
"""
|
|
rdobuilder |
3e5fd2 |
-
|
|
rdobuilder |
3e5fd2 |
+
|
|
rdobuilder |
3e5fd2 |
sgraph_objs = list()
|
|
rdobuilder |
3e5fd2 |
-
|
|
rdobuilder |
3e5fd2 |
- for sgraph, obj_dict_list in self.obj_dict['subgraphs'].iteritems():
|
|
rdobuilder |
3e5fd2 |
- sgraph_objs.extend( [ Subgraph( obj_dict = obj_d ) for obj_d in obj_dict_list ] )
|
|
rdobuilder |
3e5fd2 |
-
|
|
rdobuilder |
3e5fd2 |
- return sgraph_objs
|
|
rdobuilder |
3e5fd2 |
-
|
|
rdobuilder |
3e5fd2 |
|
|
rdobuilder |
3e5fd2 |
+ for sgraph, obj_dict_list in self.obj_dict['subgraphs'].items():
|
|
rdobuilder |
3e5fd2 |
+ sgraph_objs.extend([
|
|
rdobuilder |
3e5fd2 |
+ Subgraph(obj_dict=obj_d)
|
|
rdobuilder |
3e5fd2 |
+ for obj_d
|
|
rdobuilder |
3e5fd2 |
+ in obj_dict_list
|
|
rdobuilder |
3e5fd2 |
+ ])
|
|
rdobuilder |
3e5fd2 |
+
|
|
rdobuilder |
3e5fd2 |
+ return sgraph_objs
|
|
rdobuilder |
3e5fd2 |
|
|
rdobuilder |
3e5fd2 |
def set_parent_graph(self, parent_graph):
|
|
rdobuilder |
3e5fd2 |
-
|
|
rdobuilder |
3e5fd2 |
+
|
|
rdobuilder |
3e5fd2 |
self.obj_dict['parent_graph'] = parent_graph
|
|
rdobuilder |
3e5fd2 |
-
|
|
rdobuilder |
3e5fd2 |
- for obj_list in self.obj_dict['nodes'].itervalues():
|
|
rdobuilder |
3e5fd2 |
+
|
|
rdobuilder |
3e5fd2 |
+ for obj_list in self.obj_dict['nodes'].values():
|
|
rdobuilder |
3e5fd2 |
for obj in obj_list:
|
|
rdobuilder |
3e5fd2 |
obj['parent_graph'] = parent_graph
|
|
rdobuilder |
3e5fd2 |
|
|
rdobuilder |
3e5fd2 |
- for obj_list in self.obj_dict['edges'].itervalues():
|
|
rdobuilder |
3e5fd2 |
+ for obj_list in self.obj_dict['edges'].values():
|
|
rdobuilder |
3e5fd2 |
for obj in obj_list:
|
|
rdobuilder |
3e5fd2 |
obj['parent_graph'] = parent_graph
|
|
rdobuilder |
3e5fd2 |
|
|
rdobuilder |
3e5fd2 |
- for obj_list in self.obj_dict['subgraphs'].itervalues():
|
|
rdobuilder |
3e5fd2 |
+ for obj_list in self.obj_dict['subgraphs'].values():
|
|
rdobuilder |
3e5fd2 |
for obj in obj_list:
|
|
rdobuilder |
3e5fd2 |
Graph(obj_dict=obj).set_parent_graph(parent_graph)
|
|
rdobuilder |
3e5fd2 |
|
|
rdobuilder |
3e5fd2 |
-
|
|
rdobuilder |
3e5fd2 |
-
|
|
rdobuilder |
3e5fd2 |
def to_string(self):
|
|
rdobuilder |
3e5fd2 |
"""Returns a string representation of the graph in dot language.
|
|
rdobuilder |
3e5fd2 |
-
|
|
rdobuilder |
3e5fd2 |
+
|
|
rdobuilder |
3e5fd2 |
It will return the graph and all its subelements in string from.
|
|
rdobuilder |
3e5fd2 |
"""
|
|
rdobuilder |
3e5fd2 |
-
|
|
rdobuilder |
3e5fd2 |
-
|
|
rdobuilder |
3e5fd2 |
+
|
|
rdobuilder |
3e5fd2 |
graph = list()
|
|
rdobuilder |
3e5fd2 |
-
|
|
rdobuilder |
3e5fd2 |
+
|
|
rdobuilder |
3e5fd2 |
if self.obj_dict.get('strict', None) is not None:
|
|
rdobuilder |
3e5fd2 |
-
|
|
rdobuilder |
3e5fd2 |
- if self==self.get_parent_graph() and self.obj_dict['strict']:
|
|
rdobuilder |
3e5fd2 |
-
|
|
rdobuilder |
3e5fd2 |
+ if self == self.get_parent_graph() and self.obj_dict['strict']:
|
|
rdobuilder |
3e5fd2 |
graph.append('strict ')
|
|
rdobuilder |
3e5fd2 |
|
|
rdobuilder |
3e5fd2 |
if self.obj_dict['name'] == '':
|
|
rdobuilder |
3e5fd2 |
if 'show_keyword' in self.obj_dict and self.obj_dict['show_keyword']:
|
|
rdobuilder |
3e5fd2 |
- graph.append( 'subgraph {\n' )
|
|
rdobuilder |
3e5fd2 |
+ graph.append('subgraph {\n')
|
|
rdobuilder |
3e5fd2 |
else:
|
|
rdobuilder |
3e5fd2 |
- graph.append( '{\n' )
|
|
rdobuilder |
3e5fd2 |
+ graph.append('{\n')
|
|
rdobuilder |
3e5fd2 |
else:
|
|
rdobuilder |
3e5fd2 |
- graph.append( '%s %s {\n' % (self.obj_dict['type'], self.obj_dict['name']) )
|
|
rdobuilder |
3e5fd2 |
-
|
|
rdobuilder |
3e5fd2 |
+ graph.append('%s %s {\n' % (self.obj_dict['type'], self.obj_dict['name']))
|
|
rdobuilder |
3e5fd2 |
|
|
rdobuilder |
3e5fd2 |
- for attr in self.obj_dict['attributes'].iterkeys():
|
|
rdobuilder |
3e5fd2 |
-
|
|
rdobuilder |
3e5fd2 |
- if self.obj_dict['attributes'].get(attr, None) is not None:
|
|
rdobuilder |
3e5fd2 |
-
|
|
rdobuilder |
3e5fd2 |
- val = self.obj_dict['attributes'].get(attr)
|
|
rdobuilder |
3e5fd2 |
- if val is not None:
|
|
rdobuilder |
3e5fd2 |
- graph.append( '%s=%s' % (attr, quote_if_necessary(val)) )
|
|
rdobuilder |
3e5fd2 |
- else:
|
|
rdobuilder |
3e5fd2 |
- graph.append( attr )
|
|
rdobuilder |
3e5fd2 |
-
|
|
rdobuilder |
3e5fd2 |
- graph.append( ';\n' )
|
|
rdobuilder |
3e5fd2 |
+ for attr, value in sorted(self.obj_dict['attributes'].items(), key=itemgetter(0)):
|
|
rdobuilder |
3e5fd2 |
+ if value is not None:
|
|
rdobuilder |
3e5fd2 |
+ graph.append('%s=%s' % (attr, quote_if_necessary(value)))
|
|
rdobuilder |
3e5fd2 |
+ else:
|
|
rdobuilder |
3e5fd2 |
+ graph.append(attr)
|
|
rdobuilder |
3e5fd2 |
|
|
rdobuilder |
3e5fd2 |
+ graph.append(';\n')
|
|
rdobuilder |
3e5fd2 |
|
|
rdobuilder |
3e5fd2 |
edges_done = set()
|
|
rdobuilder |
3e5fd2 |
-
|
|
rdobuilder |
3e5fd2 |
+
|
|
rdobuilder |
3e5fd2 |
edge_obj_dicts = list()
|
|
rdobuilder |
3e5fd2 |
- for e in self.obj_dict['edges'].itervalues():
|
|
rdobuilder |
3e5fd2 |
+ for e in self.obj_dict['edges'].values():
|
|
rdobuilder |
3e5fd2 |
edge_obj_dicts.extend(e)
|
|
rdobuilder |
3e5fd2 |
-
|
|
rdobuilder |
3e5fd2 |
+
|
|
rdobuilder |
3e5fd2 |
if edge_obj_dicts:
|
|
rdobuilder |
3e5fd2 |
- edge_src_set, edge_dst_set = zip( *[obj['points'] for obj in edge_obj_dicts] )
|
|
rdobuilder |
3e5fd2 |
+ edge_src_set, edge_dst_set = list(zip(*[obj['points'] for obj in edge_obj_dicts]))
|
|
rdobuilder |
3e5fd2 |
edge_src_set, edge_dst_set = set(edge_src_set), set(edge_dst_set)
|
|
rdobuilder |
3e5fd2 |
else:
|
|
rdobuilder |
3e5fd2 |
edge_src_set, edge_dst_set = set(), set()
|
|
rdobuilder |
3e5fd2 |
-
|
|
rdobuilder |
3e5fd2 |
+
|
|
rdobuilder |
3e5fd2 |
node_obj_dicts = list()
|
|
rdobuilder |
3e5fd2 |
- for e in self.obj_dict['nodes'].itervalues():
|
|
rdobuilder |
3e5fd2 |
+ for e in self.obj_dict['nodes'].values():
|
|
rdobuilder |
3e5fd2 |
node_obj_dicts.extend(e)
|
|
rdobuilder |
3e5fd2 |
|
|
rdobuilder |
3e5fd2 |
sgraph_obj_dicts = list()
|
|
rdobuilder |
3e5fd2 |
- for sg in self.obj_dict['subgraphs'].itervalues():
|
|
rdobuilder |
3e5fd2 |
+ for sg in self.obj_dict['subgraphs'].values():
|
|
rdobuilder |
3e5fd2 |
sgraph_obj_dicts.extend(sg)
|
|
rdobuilder |
3e5fd2 |
|
|
rdobuilder |
3e5fd2 |
-
|
|
rdobuilder |
3e5fd2 |
- obj_list = [ (obj['sequence'], obj) for obj in (edge_obj_dicts + node_obj_dicts + sgraph_obj_dicts) ]
|
|
rdobuilder |
3e5fd2 |
- obj_list.sort()
|
|
rdobuilder |
3e5fd2 |
-
|
|
rdobuilder |
3e5fd2 |
+ obj_list = sorted([
|
|
rdobuilder |
3e5fd2 |
+ (obj['sequence'], obj)
|
|
rdobuilder |
3e5fd2 |
+ for obj
|
|
rdobuilder |
3e5fd2 |
+ in (edge_obj_dicts + node_obj_dicts + sgraph_obj_dicts)
|
|
rdobuilder |
3e5fd2 |
+ ])
|
|
rdobuilder |
3e5fd2 |
+
|
|
rdobuilder |
3e5fd2 |
for idx, obj in obj_list:
|
|
rdobuilder |
3e5fd2 |
-
|
|
rdobuilder |
3e5fd2 |
if obj['type'] == 'node':
|
|
rdobuilder |
3e5fd2 |
-
|
|
rdobuilder |
3e5fd2 |
node = Node(obj_dict=obj)
|
|
rdobuilder |
3e5fd2 |
-
|
|
rdobuilder |
3e5fd2 |
+
|
|
rdobuilder |
3e5fd2 |
if self.obj_dict.get('suppress_disconnected', False):
|
|
rdobuilder |
3e5fd2 |
-
|
|
rdobuilder |
3e5fd2 |
if (node.get_name() not in edge_src_set and
|
|
rdobuilder |
3e5fd2 |
- node.get_name() not in edge_dst_set):
|
|
rdobuilder |
3e5fd2 |
-
|
|
rdobuilder |
3e5fd2 |
+ node.get_name() not in edge_dst_set):
|
|
rdobuilder |
3e5fd2 |
continue
|
|
rdobuilder |
3e5fd2 |
-
|
|
rdobuilder |
3e5fd2 |
- graph.append( node.to_string()+'\n' )
|
|
rdobuilder |
3e5fd2 |
|
|
rdobuilder |
3e5fd2 |
- elif obj['type'] == 'edge':
|
|
rdobuilder |
3e5fd2 |
+ graph.append(node.to_string() + '\n')
|
|
rdobuilder |
3e5fd2 |
|
|
rdobuilder |
3e5fd2 |
+ elif obj['type'] == 'edge':
|
|
rdobuilder |
3e5fd2 |
edge = Edge(obj_dict=obj)
|
|
rdobuilder |
3e5fd2 |
-
|
|
rdobuilder |
3e5fd2 |
+
|
|
rdobuilder |
3e5fd2 |
if self.obj_dict.get('simplify', False) and edge in edges_done:
|
|
rdobuilder |
3e5fd2 |
continue
|
|
rdobuilder |
3e5fd2 |
-
|
|
rdobuilder |
3e5fd2 |
- graph.append( edge.to_string() + '\n' )
|
|
rdobuilder |
3e5fd2 |
+
|
|
rdobuilder |
3e5fd2 |
+ graph.append(edge.to_string() + '\n')
|
|
rdobuilder |
3e5fd2 |
edges_done.add(edge)
|
|
rdobuilder |
3e5fd2 |
-
|
|
rdobuilder |
3e5fd2 |
else:
|
|
rdobuilder |
3e5fd2 |
-
|
|
rdobuilder |
3e5fd2 |
sgraph = Subgraph(obj_dict=obj)
|
|
rdobuilder |
3e5fd2 |
-
|
|
rdobuilder |
3e5fd2 |
- graph.append( sgraph.to_string()+'\n' )
|
|
rdobuilder |
3e5fd2 |
+ graph.append(sgraph.to_string() + '\n')
|
|
rdobuilder |
3e5fd2 |
|
|
rdobuilder |
3e5fd2 |
- graph.append( '}\n' )
|
|
rdobuilder |
3e5fd2 |
-
|
|
rdobuilder |
3e5fd2 |
- return ''.join(graph)
|
|
rdobuilder |
3e5fd2 |
+ graph.append('}\n')
|
|
rdobuilder |
3e5fd2 |
|
|
rdobuilder |
3e5fd2 |
+ return ''.join(graph)
|
|
rdobuilder |
3e5fd2 |
|
|
rdobuilder |
3e5fd2 |
|
|
rdobuilder |
3e5fd2 |
class Subgraph(Graph):
|
|
rdobuilder |
3e5fd2 |
@@ -1680,9 +1622,9 @@ class Subgraph(Graph):
|
|
rdobuilder |
3e5fd2 |
|
|
rdobuilder |
3e5fd2 |
This class implements the methods to work on a representation
|
|
rdobuilder |
3e5fd2 |
of a subgraph in Graphviz's dot language.
|
|
rdobuilder |
3e5fd2 |
-
|
|
rdobuilder |
3e5fd2 |
+
|
|
rdobuilder |
3e5fd2 |
subgraph(graph_name='subG', suppress_disconnected=False, attribute=value, ...)
|
|
rdobuilder |
3e5fd2 |
-
|
|
rdobuilder |
3e5fd2 |
+
|
|
rdobuilder |
3e5fd2 |
graph_name:
|
|
rdobuilder |
3e5fd2 |
the subgraph's name
|
|
rdobuilder |
3e5fd2 |
suppress_disconnected:
|
|
rdobuilder |
3e5fd2 |
@@ -1690,46 +1632,43 @@ class Subgraph(Graph):
|
|
rdobuilder |
3e5fd2 |
subgraph any disconnected nodes.
|
|
rdobuilder |
3e5fd2 |
All the attributes defined in the Graphviz dot language should
|
|
rdobuilder |
3e5fd2 |
be supported.
|
|
rdobuilder |
3e5fd2 |
-
|
|
rdobuilder |
3e5fd2 |
+
|
|
rdobuilder |
3e5fd2 |
Attributes can be set through the dynamically generated methods:
|
|
rdobuilder |
3e5fd2 |
-
|
|
rdobuilder |
3e5fd2 |
+
|
|
rdobuilder |
3e5fd2 |
set_[attribute name], i.e. set_size, set_fontname
|
|
rdobuilder |
3e5fd2 |
-
|
|
rdobuilder |
3e5fd2 |
+
|
|
rdobuilder |
3e5fd2 |
or using the instance's attributes:
|
|
rdobuilder |
3e5fd2 |
-
|
|
rdobuilder |
3e5fd2 |
- Subgraph.obj_dict['attributes'][attribute name], i.e.
|
|
rdobuilder |
3e5fd2 |
-
|
|
rdobuilder |
3e5fd2 |
+
|
|
rdobuilder |
3e5fd2 |
+ Subgraph.obj_dict['attributes'][attribute name], i.e.
|
|
rdobuilder |
3e5fd2 |
+
|
|
rdobuilder |
3e5fd2 |
subgraph_instance.obj_dict['attributes']['label']
|
|
rdobuilder |
3e5fd2 |
subgraph_instance.obj_dict['attributes']['fontname']
|
|
rdobuilder |
3e5fd2 |
"""
|
|
rdobuilder |
3e5fd2 |
-
|
|
rdobuilder |
3e5fd2 |
-
|
|
rdobuilder |
3e5fd2 |
+
|
|
rdobuilder |
3e5fd2 |
# RMF: subgraph should have all the attributes of graph so it can be passed
|
|
rdobuilder |
3e5fd2 |
# as a graph to all methods
|
|
rdobuilder |
3e5fd2 |
#
|
|
rdobuilder |
3e5fd2 |
- def __init__(self, graph_name='', obj_dict=None, suppress_disconnected=False,
|
|
rdobuilder |
3e5fd2 |
- simplify=False, **attrs):
|
|
rdobuilder |
3e5fd2 |
-
|
|
rdobuilder |
3e5fd2 |
+ def __init__(
|
|
rdobuilder |
3e5fd2 |
+ self, graph_name='', obj_dict=None, suppress_disconnected=False,
|
|
rdobuilder |
3e5fd2 |
+ simplify=False, **attrs):
|
|
rdobuilder |
3e5fd2 |
|
|
rdobuilder |
3e5fd2 |
- Graph.__init__(self, graph_name=graph_name, obj_dict=obj_dict,
|
|
rdobuilder |
3e5fd2 |
+ Graph.__init__(
|
|
rdobuilder |
3e5fd2 |
+ self, graph_name=graph_name, obj_dict=obj_dict,
|
|
rdobuilder |
3e5fd2 |
suppress_disconnected=suppress_disconnected, simplify=simplify, **attrs)
|
|
rdobuilder |
3e5fd2 |
|
|
rdobuilder |
3e5fd2 |
if obj_dict is None:
|
|
rdobuilder |
3e5fd2 |
-
|
|
rdobuilder |
3e5fd2 |
self.obj_dict['type'] = 'subgraph'
|
|
rdobuilder |
3e5fd2 |
|
|
rdobuilder |
3e5fd2 |
|
|
rdobuilder |
3e5fd2 |
-
|
|
rdobuilder |
3e5fd2 |
-
|
|
rdobuilder |
3e5fd2 |
class Cluster(Graph):
|
|
rdobuilder |
3e5fd2 |
|
|
rdobuilder |
3e5fd2 |
"""Class representing a cluster in Graphviz's dot language.
|
|
rdobuilder |
3e5fd2 |
|
|
rdobuilder |
3e5fd2 |
This class implements the methods to work on a representation
|
|
rdobuilder |
3e5fd2 |
of a cluster in Graphviz's dot language.
|
|
rdobuilder |
3e5fd2 |
-
|
|
rdobuilder |
3e5fd2 |
+
|
|
rdobuilder |
3e5fd2 |
cluster(graph_name='subG', suppress_disconnected=False, attribute=value, ...)
|
|
rdobuilder |
3e5fd2 |
-
|
|
rdobuilder |
3e5fd2 |
+
|
|
rdobuilder |
3e5fd2 |
graph_name:
|
|
rdobuilder |
3e5fd2 |
the cluster's name (the string 'cluster' will be always prepended)
|
|
rdobuilder |
3e5fd2 |
suppress_disconnected:
|
|
rdobuilder |
3e5fd2 |
@@ -1737,38 +1676,35 @@ class Cluster(Graph):
|
|
rdobuilder |
3e5fd2 |
cluster any disconnected nodes.
|
|
rdobuilder |
3e5fd2 |
All the attributes defined in the Graphviz dot language should
|
|
rdobuilder |
3e5fd2 |
be supported.
|
|
rdobuilder |
3e5fd2 |
-
|
|
rdobuilder |
3e5fd2 |
+
|
|
rdobuilder |
3e5fd2 |
Attributes can be set through the dynamically generated methods:
|
|
rdobuilder |
3e5fd2 |
-
|
|
rdobuilder |
3e5fd2 |
+
|
|
rdobuilder |
3e5fd2 |
set_[attribute name], i.e. set_color, set_fontname
|
|
rdobuilder |
3e5fd2 |
-
|
|
rdobuilder |
3e5fd2 |
+
|
|
rdobuilder |
3e5fd2 |
or using the instance's attributes:
|
|
rdobuilder |
3e5fd2 |
-
|
|
rdobuilder |
3e5fd2 |
- Cluster.obj_dict['attributes'][attribute name], i.e.
|
|
rdobuilder |
3e5fd2 |
-
|
|
rdobuilder |
3e5fd2 |
+
|
|
rdobuilder |
3e5fd2 |
+ Cluster.obj_dict['attributes'][attribute name], i.e.
|
|
rdobuilder |
3e5fd2 |
+
|
|
rdobuilder |
3e5fd2 |
cluster_instance.obj_dict['attributes']['label']
|
|
rdobuilder |
3e5fd2 |
cluster_instance.obj_dict['attributes']['fontname']
|
|
rdobuilder |
3e5fd2 |
"""
|
|
rdobuilder |
3e5fd2 |
-
|
|
rdobuilder |
3e5fd2 |
|
|
rdobuilder |
3e5fd2 |
- def __init__(self, graph_name='subG', obj_dict=None, suppress_disconnected=False,
|
|
rdobuilder |
3e5fd2 |
- simplify=False, **attrs):
|
|
rdobuilder |
3e5fd2 |
+ def __init__(
|
|
rdobuilder |
3e5fd2 |
+ self, graph_name='subG', obj_dict=None, suppress_disconnected=False,
|
|
rdobuilder |
3e5fd2 |
+ simplify=False, **attrs):
|
|
rdobuilder |
3e5fd2 |
|
|
rdobuilder |
3e5fd2 |
- Graph.__init__(self, graph_name=graph_name, obj_dict=obj_dict,
|
|
rdobuilder |
3e5fd2 |
- suppress_disconnected=suppress_disconnected, simplify=simplify, **attrs)
|
|
rdobuilder |
3e5fd2 |
+ Graph.__init__(
|
|
rdobuilder |
3e5fd2 |
+ self, graph_name=graph_name, obj_dict=obj_dict,
|
|
rdobuilder |
3e5fd2 |
+ suppress_disconnected=suppress_disconnected, simplify=simplify, **attrs
|
|
rdobuilder |
3e5fd2 |
+ )
|
|
rdobuilder |
3e5fd2 |
|
|
rdobuilder |
3e5fd2 |
if obj_dict is None:
|
|
rdobuilder |
3e5fd2 |
-
|
|
rdobuilder |
3e5fd2 |
self.obj_dict['type'] = 'subgraph'
|
|
rdobuilder |
3e5fd2 |
- self.obj_dict['name'] = 'cluster_'+graph_name
|
|
rdobuilder |
3e5fd2 |
+ self.obj_dict['name'] = 'cluster_' + graph_name
|
|
rdobuilder |
3e5fd2 |
|
|
rdobuilder |
3e5fd2 |
self.create_attribute_methods(CLUSTER_ATTRIBUTES)
|
|
rdobuilder |
3e5fd2 |
|
|
rdobuilder |
3e5fd2 |
|
|
rdobuilder |
3e5fd2 |
-
|
|
rdobuilder |
3e5fd2 |
-
|
|
rdobuilder |
3e5fd2 |
-
|
|
rdobuilder |
3e5fd2 |
-
|
|
rdobuilder |
3e5fd2 |
class Dot(Graph):
|
|
rdobuilder |
3e5fd2 |
"""A container for handling a dot language file.
|
|
rdobuilder |
3e5fd2 |
|
|
rdobuilder |
3e5fd2 |
@@ -1776,144 +1712,148 @@ class Dot(Graph):
|
|
rdobuilder |
3e5fd2 |
a dot language file. It is a derived class of
|
|
rdobuilder |
3e5fd2 |
the base class 'Graph'.
|
|
rdobuilder |
3e5fd2 |
"""
|
|
rdobuilder |
3e5fd2 |
-
|
|
rdobuilder |
3e5fd2 |
-
|
|
rdobuilder |
3e5fd2 |
-
|
|
rdobuilder |
3e5fd2 |
+
|
|
rdobuilder |
3e5fd2 |
def __init__(self, *argsl, **argsd):
|
|
rdobuilder |
3e5fd2 |
Graph.__init__(self, *argsl, **argsd)
|
|
rdobuilder |
3e5fd2 |
|
|
rdobuilder |
3e5fd2 |
self.shape_files = list()
|
|
rdobuilder |
3e5fd2 |
-
|
|
rdobuilder |
3e5fd2 |
self.progs = None
|
|
rdobuilder |
3e5fd2 |
-
|
|
rdobuilder |
3e5fd2 |
- self.formats = ['canon', 'cmap', 'cmapx', 'cmapx_np', 'dia', 'dot',
|
|
rdobuilder |
3e5fd2 |
+ self.formats = [
|
|
rdobuilder |
3e5fd2 |
+ 'canon', 'cmap', 'cmapx', 'cmapx_np', 'dia', 'dot',
|
|
rdobuilder |
3e5fd2 |
'fig', 'gd', 'gd2', 'gif', 'hpgl', 'imap', 'imap_np', 'ismap',
|
|
rdobuilder |
3e5fd2 |
'jpe', 'jpeg', 'jpg', 'mif', 'mp', 'pcl', 'pdf', 'pic', 'plain',
|
|
rdobuilder |
3e5fd2 |
'plain-ext', 'png', 'ps', 'ps2', 'svg', 'svgz', 'vml', 'vmlz',
|
|
rdobuilder |
3e5fd2 |
- 'vrml', 'vtx', 'wbmp', 'xdot', 'xlib' ]
|
|
rdobuilder |
3e5fd2 |
-
|
|
rdobuilder |
3e5fd2 |
+ 'vrml', 'vtx', 'wbmp', 'xdot', 'xlib'
|
|
rdobuilder |
3e5fd2 |
+ ]
|
|
rdobuilder |
3e5fd2 |
self.prog = 'dot'
|
|
rdobuilder |
3e5fd2 |
-
|
|
rdobuilder |
3e5fd2 |
+
|
|
rdobuilder |
3e5fd2 |
# Automatically creates all the methods enabling the creation
|
|
rdobuilder |
3e5fd2 |
# of output in any of the supported formats.
|
|
rdobuilder |
3e5fd2 |
for frmt in self.formats:
|
|
rdobuilder |
3e5fd2 |
self.__setattr__(
|
|
rdobuilder |
3e5fd2 |
- 'create_'+frmt,
|
|
rdobuilder |
3e5fd2 |
- lambda f=frmt, prog=self.prog : self.create(format=f, prog=prog))
|
|
rdobuilder |
3e5fd2 |
- f = self.__dict__['create_'+frmt]
|
|
rdobuilder |
3e5fd2 |
- f.__doc__ = '''Refer to the docstring accompanying the 'create' method for more information.'''
|
|
rdobuilder |
3e5fd2 |
-
|
|
rdobuilder |
3e5fd2 |
- for frmt in self.formats+['raw']:
|
|
rdobuilder |
3e5fd2 |
+ 'create_' + frmt,
|
|
rdobuilder |
3e5fd2 |
+ lambda f=frmt, prog=self.prog: self.create(format=f, prog=prog)
|
|
rdobuilder |
3e5fd2 |
+ )
|
|
rdobuilder |
3e5fd2 |
+ f = self.__dict__['create_' + frmt]
|
|
rdobuilder |
3e5fd2 |
+ f.__doc__ = (
|
|
rdobuilder |
3e5fd2 |
+ '''Refer to the docstring accompanying the'''
|
|
rdobuilder |
3e5fd2 |
+ ''''create' method for more information.'''
|
|
rdobuilder |
3e5fd2 |
+ )
|
|
rdobuilder |
3e5fd2 |
+
|
|
rdobuilder |
3e5fd2 |
+ for frmt in self.formats + ['raw']:
|
|
rdobuilder |
3e5fd2 |
self.__setattr__(
|
|
rdobuilder |
3e5fd2 |
- 'write_'+frmt,
|
|
rdobuilder |
3e5fd2 |
- lambda path, f=frmt, prog=self.prog : self.write(path, format=f, prog=prog))
|
|
rdobuilder |
3e5fd2 |
-
|
|
rdobuilder |
3e5fd2 |
- f = self.__dict__['write_'+frmt]
|
|
rdobuilder |
3e5fd2 |
- f.__doc__ = '''Refer to the docstring accompanying the 'write' method for more information.'''
|
|
rdobuilder |
3e5fd2 |
-
|
|
rdobuilder |
3e5fd2 |
-
|
|
rdobuilder |
3e5fd2 |
-
|
|
rdobuilder |
3e5fd2 |
+ 'write_' + frmt,
|
|
rdobuilder |
3e5fd2 |
+ lambda path, f=frmt, prog=self.prog: self.write(path, format=f, prog=prog)
|
|
rdobuilder |
3e5fd2 |
+ )
|
|
rdobuilder |
3e5fd2 |
+
|
|
rdobuilder |
3e5fd2 |
+ f = self.__dict__['write_' + frmt]
|
|
rdobuilder |
3e5fd2 |
+ f.__doc__ = (
|
|
rdobuilder |
3e5fd2 |
+ '''Refer to the docstring accompanying the'''
|
|
rdobuilder |
3e5fd2 |
+ ''''write' method for more information.'''
|
|
rdobuilder |
3e5fd2 |
+ )
|
|
rdobuilder |
3e5fd2 |
+
|
|
rdobuilder |
3e5fd2 |
def __getstate__(self):
|
|
rdobuilder |
3e5fd2 |
-
|
|
rdobuilder |
3e5fd2 |
- dict = copy.copy(self.obj_dict)
|
|
rdobuilder |
3e5fd2 |
-
|
|
rdobuilder |
3e5fd2 |
- return dict
|
|
rdobuilder |
3e5fd2 |
-
|
|
rdobuilder |
3e5fd2 |
+ return copy.copy(self.obj_dict)
|
|
rdobuilder |
3e5fd2 |
+
|
|
rdobuilder |
3e5fd2 |
def __setstate__(self, state):
|
|
rdobuilder |
3e5fd2 |
-
|
|
rdobuilder |
3e5fd2 |
self.obj_dict = state
|
|
rdobuilder |
3e5fd2 |
-
|
|
rdobuilder |
3e5fd2 |
-
|
|
rdobuilder |
3e5fd2 |
+
|
|
rdobuilder |
3e5fd2 |
def set_shape_files(self, file_paths):
|
|
rdobuilder |
3e5fd2 |
"""Add the paths of the required image files.
|
|
rdobuilder |
3e5fd2 |
-
|
|
rdobuilder |
3e5fd2 |
+
|
|
rdobuilder |
3e5fd2 |
If the graph needs graphic objects to be used as shapes or otherwise
|
|
rdobuilder |
3e5fd2 |
those need to be in the same folder as the graph is going to be rendered
|
|
rdobuilder |
3e5fd2 |
from. Alternatively the absolute path to the files can be specified when
|
|
rdobuilder |
3e5fd2 |
including the graphics in the graph.
|
|
rdobuilder |
3e5fd2 |
-
|
|
rdobuilder |
3e5fd2 |
+
|
|
rdobuilder |
3e5fd2 |
The files in the location pointed to by the path(s) specified as arguments
|
|
rdobuilder |
3e5fd2 |
to this method will be copied to the same temporary location where the
|
|
rdobuilder |
3e5fd2 |
graph is going to be rendered.
|
|
rdobuilder |
3e5fd2 |
"""
|
|
rdobuilder |
3e5fd2 |
-
|
|
rdobuilder |
3e5fd2 |
- if isinstance( file_paths, basestring ):
|
|
rdobuilder |
3e5fd2 |
- self.shape_files.append( file_paths )
|
|
rdobuilder |
3e5fd2 |
-
|
|
rdobuilder |
3e5fd2 |
- if isinstance( file_paths, (list, tuple) ):
|
|
rdobuilder |
3e5fd2 |
- self.shape_files.extend( file_paths )
|
|
rdobuilder |
3e5fd2 |
-
|
|
rdobuilder |
3e5fd2 |
-
|
|
rdobuilder |
3e5fd2 |
+
|
|
rdobuilder |
3e5fd2 |
+ if isinstance(file_paths, basestring):
|
|
rdobuilder |
3e5fd2 |
+ self.shape_files.append(file_paths)
|
|
rdobuilder |
3e5fd2 |
+
|
|
rdobuilder |
3e5fd2 |
+ if isinstance(file_paths, (list, tuple)):
|
|
rdobuilder |
3e5fd2 |
+ self.shape_files.extend(file_paths)
|
|
rdobuilder |
3e5fd2 |
+
|
|
rdobuilder |
3e5fd2 |
def set_prog(self, prog):
|
|
rdobuilder |
3e5fd2 |
"""Sets the default program.
|
|
rdobuilder |
3e5fd2 |
-
|
|
rdobuilder |
3e5fd2 |
+
|
|
rdobuilder |
3e5fd2 |
Sets the default program in charge of processing
|
|
rdobuilder |
3e5fd2 |
the dot file into a graph.
|
|
rdobuilder |
3e5fd2 |
"""
|
|
rdobuilder |
3e5fd2 |
self.prog = prog
|
|
rdobuilder |
3e5fd2 |
-
|
|
rdobuilder |
3e5fd2 |
|
|
rdobuilder |
3e5fd2 |
def set_graphviz_executables(self, paths):
|
|
rdobuilder |
3e5fd2 |
"""This method allows to manually specify the location of the GraphViz executables.
|
|
rdobuilder |
3e5fd2 |
-
|
|
rdobuilder |
3e5fd2 |
+
|
|
rdobuilder |
3e5fd2 |
The argument to this method should be a dictionary where the keys are as follows:
|
|
rdobuilder |
3e5fd2 |
-
|
|
rdobuilder |
3e5fd2 |
+
|
|
rdobuilder |
3e5fd2 |
{'dot': '', 'twopi': '', 'neato': '', 'circo': '', 'fdp': ''}
|
|
rdobuilder |
3e5fd2 |
-
|
|
rdobuilder |
3e5fd2 |
+
|
|
rdobuilder |
3e5fd2 |
and the values are the paths to the corresponding executable, including the name
|
|
rdobuilder |
3e5fd2 |
of the executable itself.
|
|
rdobuilder |
3e5fd2 |
"""
|
|
rdobuilder |
3e5fd2 |
-
|
|
rdobuilder |
3e5fd2 |
- self.progs = paths
|
|
rdobuilder |
3e5fd2 |
|
|
rdobuilder |
3e5fd2 |
+ self.progs = paths
|
|
rdobuilder |
3e5fd2 |
|
|
rdobuilder |
3e5fd2 |
def write(self, path, prog=None, format='raw'):
|
|
rdobuilder |
3e5fd2 |
- """Writes a graph to a file.
|
|
rdobuilder |
3e5fd2 |
-
|
|
rdobuilder |
3e5fd2 |
+ """
|
|
rdobuilder |
3e5fd2 |
Given a filename 'path' it will open/create and truncate
|
|
rdobuilder |
3e5fd2 |
such file and write on it a representation of the graph
|
|
rdobuilder |
3e5fd2 |
defined by the dot object and in the format specified by
|
|
rdobuilder |
3e5fd2 |
- 'format'.
|
|
rdobuilder |
3e5fd2 |
+ 'format'. 'path' can also be an open file-like object, such as
|
|
rdobuilder |
3e5fd2 |
+ a StringIO instance.
|
|
rdobuilder |
3e5fd2 |
+
|
|
rdobuilder |
3e5fd2 |
The format 'raw' is used to dump the string representation
|
|
rdobuilder |
3e5fd2 |
of the Dot object, without further processing.
|
|
rdobuilder |
3e5fd2 |
The output can be processed by any of graphviz tools, defined
|
|
rdobuilder |
3e5fd2 |
in 'prog', which defaults to 'dot'
|
|
rdobuilder |
3e5fd2 |
Returns True or False according to the success of the write
|
|
rdobuilder |
3e5fd2 |
operation.
|
|
rdobuilder |
3e5fd2 |
-
|
|
rdobuilder |
3e5fd2 |
+
|
|
rdobuilder |
3e5fd2 |
There's also the preferred possibility of using:
|
|
rdobuilder |
3e5fd2 |
-
|
|
rdobuilder |
3e5fd2 |
+
|
|
rdobuilder |
3e5fd2 |
write_'format'(path, prog='program')
|
|
rdobuilder |
3e5fd2 |
-
|
|
rdobuilder |
3e5fd2 |
+
|
|
rdobuilder |
3e5fd2 |
which are automatically defined for all the supported formats.
|
|
rdobuilder |
3e5fd2 |
[write_ps(), write_gif(), write_dia(), ...]
|
|
rdobuilder |
3e5fd2 |
- """
|
|
rdobuilder |
3e5fd2 |
|
|
rdobuilder |
3e5fd2 |
+ """
|
|
rdobuilder |
3e5fd2 |
if prog is None:
|
|
rdobuilder |
3e5fd2 |
prog = self.prog
|
|
rdobuilder |
3e5fd2 |
-
|
|
rdobuilder |
3e5fd2 |
- dot_fd = file(path, "w+b")
|
|
rdobuilder |
3e5fd2 |
- if format == 'raw':
|
|
rdobuilder |
3e5fd2 |
- data = self.to_string()
|
|
rdobuilder |
3e5fd2 |
- if isinstance(data, basestring):
|
|
rdobuilder |
3e5fd2 |
- if not isinstance(data, unicode):
|
|
rdobuilder |
3e5fd2 |
- try:
|
|
rdobuilder |
3e5fd2 |
- data = unicode(data, 'utf-8')
|
|
rdobuilder |
3e5fd2 |
- except:
|
|
rdobuilder |
3e5fd2 |
- pass
|
|
rdobuilder |
3e5fd2 |
-
|
|
rdobuilder |
3e5fd2 |
- try:
|
|
rdobuilder |
3e5fd2 |
- data = data.encode('utf-8')
|
|
rdobuilder |
3e5fd2 |
- except:
|
|
rdobuilder |
3e5fd2 |
- pass
|
|
rdobuilder |
3e5fd2 |
- dot_fd.write(data)
|
|
rdobuilder |
3e5fd2 |
- else:
|
|
rdobuilder |
3e5fd2 |
- dot_fd.write(self.create(prog, format))
|
|
rdobuilder |
3e5fd2 |
- dot_fd.close()
|
|
rdobuilder |
3e5fd2 |
|
|
rdobuilder |
3e5fd2 |
- return True
|
|
rdobuilder |
3e5fd2 |
-
|
|
rdobuilder |
3e5fd2 |
+ fobj, close = get_fobj(path, 'w+b')
|
|
rdobuilder |
3e5fd2 |
+ try:
|
|
rdobuilder |
3e5fd2 |
+ if format == 'raw':
|
|
rdobuilder |
3e5fd2 |
+ data = self.to_string()
|
|
rdobuilder |
3e5fd2 |
+ if isinstance(data, basestring):
|
|
rdobuilder |
3e5fd2 |
+ if not isinstance(data, unicode):
|
|
rdobuilder |
3e5fd2 |
+ try:
|
|
rdobuilder |
3e5fd2 |
+ data = unicode(data, 'utf-8')
|
|
rdobuilder |
3e5fd2 |
+ except:
|
|
rdobuilder |
3e5fd2 |
+ pass
|
|
rdobuilder |
3e5fd2 |
+
|
|
rdobuilder |
3e5fd2 |
+ try:
|
|
rdobuilder |
3e5fd2 |
+ charset = self.get_charset()
|
|
rdobuilder |
3e5fd2 |
+ if not PY3 or not charset:
|
|
rdobuilder |
3e5fd2 |
+ charset = 'utf-8'
|
|
rdobuilder |
3e5fd2 |
+ data = data.encode(charset)
|
|
rdobuilder |
3e5fd2 |
+ except:
|
|
rdobuilder |
3e5fd2 |
+ if PY3:
|
|
rdobuilder |
3e5fd2 |
+ data = data.encode('utf-8')
|
|
rdobuilder |
3e5fd2 |
+ pass
|
|
rdobuilder |
3e5fd2 |
+
|
|
rdobuilder |
3e5fd2 |
+ fobj.write(data)
|
|
rdobuilder |
3e5fd2 |
+
|
|
rdobuilder |
3e5fd2 |
+ else:
|
|
rdobuilder |
3e5fd2 |
+ fobj.write(self.create(prog, format))
|
|
rdobuilder |
3e5fd2 |
+ finally:
|
|
rdobuilder |
3e5fd2 |
+ if close:
|
|
rdobuilder |
3e5fd2 |
+ fobj.close()
|
|
rdobuilder |
3e5fd2 |
|
|
rdobuilder |
3e5fd2 |
+ return True
|
|
rdobuilder |
3e5fd2 |
|
|
rdobuilder |
3e5fd2 |
def create(self, prog=None, format='ps'):
|
|
rdobuilder |
3e5fd2 |
"""Creates and returns a Postscript representation of the graph.
|
|
rdobuilder |
3e5fd2 |
@@ -1923,75 +1863,71 @@ class Dot(Graph):
|
|
rdobuilder |
3e5fd2 |
reading the Postscript output and returning it as a string is the
|
|
rdobuilder |
3e5fd2 |
operation is successful.
|
|
rdobuilder |
3e5fd2 |
On failure None is returned.
|
|
rdobuilder |
3e5fd2 |
-
|
|
rdobuilder |
3e5fd2 |
+
|
|
rdobuilder |
3e5fd2 |
There's also the preferred possibility of using:
|
|
rdobuilder |
3e5fd2 |
-
|
|
rdobuilder |
3e5fd2 |
+
|
|
rdobuilder |
3e5fd2 |
create_'format'(prog='program')
|
|
rdobuilder |
3e5fd2 |
-
|
|
rdobuilder |
3e5fd2 |
+
|
|
rdobuilder |
3e5fd2 |
which are automatically defined for all the supported formats.
|
|
rdobuilder |
3e5fd2 |
[create_ps(), create_gif(), create_dia(), ...]
|
|
rdobuilder |
3e5fd2 |
-
|
|
rdobuilder |
3e5fd2 |
+
|
|
rdobuilder |
3e5fd2 |
If 'prog' is a list instead of a string the fist item is expected
|
|
rdobuilder |
3e5fd2 |
to be the program name, followed by any optional command-line
|
|
rdobuilder |
3e5fd2 |
arguments for it:
|
|
rdobuilder |
3e5fd2 |
-
|
|
rdobuilder |
3e5fd2 |
- [ 'twopi', '-Tdot', '-s10' ]
|
|
rdobuilder |
3e5fd2 |
+
|
|
rdobuilder |
3e5fd2 |
+ ['twopi', '-Tdot', '-s10']
|
|
rdobuilder |
3e5fd2 |
"""
|
|
rdobuilder |
3e5fd2 |
-
|
|
rdobuilder |
3e5fd2 |
+
|
|
rdobuilder |
3e5fd2 |
if prog is None:
|
|
rdobuilder |
3e5fd2 |
prog = self.prog
|
|
rdobuilder |
3e5fd2 |
-
|
|
rdobuilder |
3e5fd2 |
+
|
|
rdobuilder |
3e5fd2 |
if isinstance(prog, (list, tuple)):
|
|
rdobuilder |
3e5fd2 |
prog, args = prog[0], prog[1:]
|
|
rdobuilder |
3e5fd2 |
else:
|
|
rdobuilder |
3e5fd2 |
args = []
|
|
rdobuilder |
3e5fd2 |
-
|
|
rdobuilder |
3e5fd2 |
+
|
|
rdobuilder |
3e5fd2 |
if self.progs is None:
|
|
rdobuilder |
3e5fd2 |
self.progs = find_graphviz()
|
|
rdobuilder |
3e5fd2 |
if self.progs is None:
|
|
rdobuilder |
3e5fd2 |
raise InvocationException(
|
|
rdobuilder |
3e5fd2 |
- 'GraphViz\'s executables not found' )
|
|
rdobuilder |
3e5fd2 |
-
|
|
rdobuilder |
3e5fd2 |
- if not self.progs.has_key(prog):
|
|
rdobuilder |
3e5fd2 |
+ 'GraphViz\'s executables not found')
|
|
rdobuilder |
3e5fd2 |
+
|
|
rdobuilder |
3e5fd2 |
+ if prog not in self.progs:
|
|
rdobuilder |
3e5fd2 |
raise InvocationException(
|
|
rdobuilder |
3e5fd2 |
- 'GraphViz\'s executable "%s" not found' % prog )
|
|
rdobuilder |
3e5fd2 |
-
|
|
rdobuilder |
3e5fd2 |
- if not os.path.exists( self.progs[prog] ) or not os.path.isfile( self.progs[prog] ):
|
|
rdobuilder |
3e5fd2 |
+ 'GraphViz\'s executable "%s" not found' % prog)
|
|
rdobuilder |
3e5fd2 |
+
|
|
rdobuilder |
3e5fd2 |
+ if not os.path.exists(self.progs[prog]) or not os.path.isfile(self.progs[prog]):
|
|
rdobuilder |
3e5fd2 |
raise InvocationException(
|
|
rdobuilder |
3e5fd2 |
- 'GraphViz\'s executable "%s" is not a file or doesn\'t exist' % self.progs[prog] )
|
|
rdobuilder |
3e5fd2 |
-
|
|
rdobuilder |
3e5fd2 |
-
|
|
rdobuilder |
3e5fd2 |
+ 'GraphViz\'s executable "%s" is not a file or doesn\'t exist' % self.progs[prog])
|
|
rdobuilder |
3e5fd2 |
+
|
|
rdobuilder |
3e5fd2 |
tmp_fd, tmp_name = tempfile.mkstemp()
|
|
rdobuilder |
3e5fd2 |
os.close(tmp_fd)
|
|
rdobuilder |
3e5fd2 |
self.write(tmp_name)
|
|
rdobuilder |
3e5fd2 |
- tmp_dir = os.path.dirname(tmp_name )
|
|
rdobuilder |
3e5fd2 |
-
|
|
rdobuilder |
3e5fd2 |
+ tmp_dir = os.path.dirname(tmp_name)
|
|
rdobuilder |
3e5fd2 |
+
|
|
rdobuilder |
3e5fd2 |
# For each of the image files...
|
|
rdobuilder |
3e5fd2 |
- #
|
|
rdobuilder |
3e5fd2 |
for img in self.shape_files:
|
|
rdobuilder |
3e5fd2 |
-
|
|
rdobuilder |
3e5fd2 |
+
|
|
rdobuilder |
3e5fd2 |
# Get its data
|
|
rdobuilder |
3e5fd2 |
- #
|
|
rdobuilder |
3e5fd2 |
- f = file(img, 'rb')
|
|
rdobuilder |
3e5fd2 |
+ f = open(img, 'rb')
|
|
rdobuilder |
3e5fd2 |
f_data = f.read()
|
|
rdobuilder |
3e5fd2 |
f.close()
|
|
rdobuilder |
3e5fd2 |
-
|
|
rdobuilder |
3e5fd2 |
+
|
|
rdobuilder |
3e5fd2 |
# And copy it under a file with the same name in the temporary directory
|
|
rdobuilder |
3e5fd2 |
- #
|
|
rdobuilder |
3e5fd2 |
- f = file( os.path.join( tmp_dir, os.path.basename(img) ), 'wb' )
|
|
rdobuilder |
3e5fd2 |
+ f = open(os.path.join(tmp_dir, os.path.basename(img)), 'wb')
|
|
rdobuilder |
3e5fd2 |
f.write(f_data)
|
|
rdobuilder |
3e5fd2 |
f.close()
|
|
rdobuilder |
3e5fd2 |
-
|
|
rdobuilder |
3e5fd2 |
- cmdline = [self.progs[prog], '-T'+format, tmp_name] + args
|
|
rdobuilder |
3e5fd2 |
-
|
|
rdobuilder |
3e5fd2 |
+
|
|
rdobuilder |
3e5fd2 |
+ cmdline = [self.progs[prog], '-T' + format, tmp_name] + args
|
|
rdobuilder |
3e5fd2 |
+
|
|
rdobuilder |
3e5fd2 |
p = subprocess.Popen(
|
|
rdobuilder |
3e5fd2 |
cmdline,
|
|
rdobuilder |
3e5fd2 |
cwd=tmp_dir,
|
|
rdobuilder |
3e5fd2 |
stderr=subprocess.PIPE, stdout=subprocess.PIPE)
|
|
rdobuilder |
3e5fd2 |
-
|
|
rdobuilder |
3e5fd2 |
+
|
|
rdobuilder |
3e5fd2 |
stderr = p.stderr
|
|
rdobuilder |
3e5fd2 |
stdout = p.stdout
|
|
rdobuilder |
3e5fd2 |
-
|
|
rdobuilder |
3e5fd2 |
+
|
|
rdobuilder |
3e5fd2 |
stdout_output = list()
|
|
rdobuilder |
3e5fd2 |
while True:
|
|
rdobuilder |
3e5fd2 |
data = stdout.read()
|
|
rdobuilder |
3e5fd2 |
@@ -1999,9 +1935,9 @@ class Dot(Graph):
|
|
rdobuilder |
3e5fd2 |
break
|
|
rdobuilder |
3e5fd2 |
stdout_output.append(data)
|
|
rdobuilder |
3e5fd2 |
stdout.close()
|
|
rdobuilder |
3e5fd2 |
-
|
|
rdobuilder |
3e5fd2 |
- stdout_output = ''.join(stdout_output)
|
|
rdobuilder |
3e5fd2 |
-
|
|
rdobuilder |
3e5fd2 |
+
|
|
rdobuilder |
3e5fd2 |
+ stdout_output = NULL_SEP.join(stdout_output)
|
|
rdobuilder |
3e5fd2 |
+
|
|
rdobuilder |
3e5fd2 |
if not stderr.closed:
|
|
rdobuilder |
3e5fd2 |
stderr_output = list()
|
|
rdobuilder |
3e5fd2 |
while True:
|
|
rdobuilder |
3e5fd2 |
@@ -2010,29 +1946,28 @@ class Dot(Graph):
|
|
rdobuilder |
3e5fd2 |
break
|
|
rdobuilder |
3e5fd2 |
stderr_output.append(data)
|
|
rdobuilder |
3e5fd2 |
stderr.close()
|
|
rdobuilder |
3e5fd2 |
-
|
|
rdobuilder |
3e5fd2 |
+
|
|
rdobuilder |
3e5fd2 |
if stderr_output:
|
|
rdobuilder |
3e5fd2 |
- stderr_output = ''.join(stderr_output)
|
|
rdobuilder |
3e5fd2 |
-
|
|
rdobuilder |
3e5fd2 |
+ stderr_output = NULL_SEP.join(stderr_output)
|
|
rdobuilder |
3e5fd2 |
+ if PY3:
|
|
rdobuilder |
3e5fd2 |
+ stderr_output = stderr_output.decode(sys.stderr.encoding)
|
|
rdobuilder |
3e5fd2 |
+
|
|
rdobuilder |
3e5fd2 |
#pid, status = os.waitpid(p.pid, 0)
|
|
rdobuilder |
3e5fd2 |
status = p.wait()
|
|
rdobuilder |
3e5fd2 |
-
|
|
rdobuilder |
3e5fd2 |
- if status != 0 :
|
|
rdobuilder |
3e5fd2 |
+
|
|
rdobuilder |
3e5fd2 |
+ if status != 0:
|
|
rdobuilder |
3e5fd2 |
raise InvocationException(
|
|
rdobuilder |
3e5fd2 |
'Program terminated with status: %d. stderr follows: %s' % (
|
|
rdobuilder |
3e5fd2 |
- status, stderr_output) )
|
|
rdobuilder |
3e5fd2 |
+ status, stderr_output))
|
|
rdobuilder |
3e5fd2 |
elif stderr_output:
|
|
rdobuilder |
3e5fd2 |
- print stderr_output
|
|
rdobuilder |
3e5fd2 |
-
|
|
rdobuilder |
3e5fd2 |
+ print(stderr_output)
|
|
rdobuilder |
3e5fd2 |
+
|
|
rdobuilder |
3e5fd2 |
# For each of the image files...
|
|
rdobuilder |
3e5fd2 |
- #
|
|
rdobuilder |
3e5fd2 |
for img in self.shape_files:
|
|
rdobuilder |
3e5fd2 |
-
|
|
rdobuilder |
3e5fd2 |
+
|
|
rdobuilder |
3e5fd2 |
# remove it
|
|
rdobuilder |
3e5fd2 |
- #
|
|
rdobuilder |
3e5fd2 |
- os.unlink( os.path.join( tmp_dir, os.path.basename(img) ) )
|
|
rdobuilder |
3e5fd2 |
+ os.unlink(os.path.join(tmp_dir, os.path.basename(img)))
|
|
rdobuilder |
3e5fd2 |
|
|
rdobuilder |
3e5fd2 |
os.unlink(tmp_name)
|
|
rdobuilder |
3e5fd2 |
-
|
|
rdobuilder |
3e5fd2 |
- return stdout_output
|
|
rdobuilder |
3e5fd2 |
|
|
rdobuilder |
3e5fd2 |
+ return stdout_output
|
|
rdobuilder |
3e5fd2 |
diff --git a/setup.py b/setup.py
|
|
rdobuilder |
3e5fd2 |
index 27328d8..92890d7 100644
|
|
rdobuilder |
3e5fd2 |
--- a/setup.py
|
|
rdobuilder |
3e5fd2 |
+++ b/setup.py
|
|
rdobuilder |
3e5fd2 |
@@ -1,10 +1,6 @@
|
|
rdobuilder |
3e5fd2 |
#!/usr/bin/env python
|
|
rdobuilder |
3e5fd2 |
|
|
rdobuilder |
3e5fd2 |
-try:
|
|
rdobuilder |
3e5fd2 |
- from distutils.core import setup
|
|
rdobuilder |
3e5fd2 |
-except ImportError, excp:
|
|
rdobuilder |
3e5fd2 |
- from setuptools import setup
|
|
rdobuilder |
3e5fd2 |
-
|
|
rdobuilder |
3e5fd2 |
+from setuptools import setup
|
|
rdobuilder |
3e5fd2 |
import pydot
|
|
rdobuilder |
3e5fd2 |
import os
|
|
rdobuilder |
3e5fd2 |
|