py2/3 compatibility
This commit is contained in:
parent
4504fce247
commit
687eb7e18c
|
@ -10,10 +10,11 @@ Author: Michael Krause <michael@krause-software.de>
|
|||
Fixes by: Ero Carrera <ero@dkbza.org>
|
||||
"""
|
||||
|
||||
from __future__ import division, print_function
|
||||
|
||||
__author__ = ['Michael Krause', 'Ero Carrera']
|
||||
__license__ = 'MIT'
|
||||
|
||||
|
||||
import sys
|
||||
import glob
|
||||
import pydot
|
||||
|
@ -25,7 +26,13 @@ from pyparsing import __version__ as pyparsing_version
|
|||
from pyparsing import ( nestedExpr, Literal, CaselessLiteral, Word, Upcase, OneOrMore, ZeroOrMore,
|
||||
Forward, NotAny, delimitedList, oneOf, Group, Optional, Combine, alphas, nums,
|
||||
restOfLine, cStyleComment, nums, alphanums, printables, empty, quotedString,
|
||||
ParseException, ParseResults, CharsNotIn, _noncomma, dblQuotedString, QuotedString, ParserElement )
|
||||
ParseException, ParseResults, CharsNotIn, dblQuotedString, QuotedString, ParserElement )
|
||||
|
||||
|
||||
PY3 = not sys.version_info < (3, 0, 0)
|
||||
|
||||
if PY3:
|
||||
basestring = str
|
||||
|
||||
|
||||
class P_AttrList:
|
||||
|
@ -111,7 +118,7 @@ def push_top_graph_stmt(str, loc, toks):
|
|||
add_elements(g, element)
|
||||
|
||||
else:
|
||||
raise ValueError, "Unknown element statement: %r " % element
|
||||
raise ValueError("Unknown element statement: %r " % element)
|
||||
|
||||
|
||||
for g in top_graphs:
|
||||
|
@ -136,7 +143,7 @@ def update_parent_graph_hierarchy(g, parent_graph=None, level=0):
|
|||
else:
|
||||
item_dict = g.obj_dict
|
||||
|
||||
if not item_dict.has_key( key_name ):
|
||||
if key_name not in item_dict:
|
||||
continue
|
||||
|
||||
for key, objs in item_dict[key_name].items():
|
||||
|
@ -218,14 +225,14 @@ def add_elements(g, toks, defaults_graph=None, defaults_node=None, defaults_edge
|
|||
defaults_edge.update(element.attrs)
|
||||
|
||||
else:
|
||||
raise ValueError, "Unknown DefaultStatement: %s " % element.default_type
|
||||
raise ValueError("Unknown DefaultStatement: %s " % element.default_type)
|
||||
|
||||
elif isinstance(element, P_AttrList):
|
||||
|
||||
g.obj_dict['attributes'].update(element.attrs)
|
||||
|
||||
else:
|
||||
raise ValueError, "Unknown element statement: %r" % element
|
||||
raise ValueError("Unknown element statement: %r" % element)
|
||||
|
||||
|
||||
def push_graph_stmt(str, loc, toks):
|
||||
|
@ -267,7 +274,7 @@ def push_default_stmt(str, loc, toks):
|
|||
if default_type in ['graph', 'node', 'edge']:
|
||||
return DefaultStatement(default_type, attrs)
|
||||
else:
|
||||
raise ValueError, "Unknown default statement: %r " % toks
|
||||
raise ValueError("Unknown default statement: %r " % toks)
|
||||
|
||||
|
||||
def push_attr_list(str, loc, toks):
|
||||
|
@ -414,7 +421,8 @@ def graph_definition():
|
|||
|
||||
double_quoted_string = QuotedString('"', multiline=True, unquoteResults=False) # dblQuotedString
|
||||
|
||||
alphastring_ = OneOrMore(CharsNotIn(_noncomma + ' '))
|
||||
noncomma_ = "".join([c for c in printables if c != ","])
|
||||
alphastring_ = OneOrMore(CharsNotIn(noncomma_ + ' '))
|
||||
|
||||
def parse_html(s, loc, toks):
|
||||
return '<%s>' % ''.join(toks[0])
|
||||
|
@ -506,8 +514,23 @@ def parse_dot_data(data):
|
|||
|
||||
top_graphs = list()
|
||||
|
||||
if data.startswith(codecs.BOM_UTF8):
|
||||
data = data.decode( 'utf-8' )
|
||||
if PY3:
|
||||
if isinstance(data, bytes):
|
||||
# this is extremely hackish
|
||||
try:
|
||||
idx = data.index(b'charset') + 7
|
||||
while data[idx] in b' \t\n\r=':
|
||||
idx += 1
|
||||
fst = idx
|
||||
while data[idx] not in b' \t\n\r];,':
|
||||
idx += 1
|
||||
charset = data[fst:idx].strip(b'"\'').decode('ascii')
|
||||
data = data.decode(charset)
|
||||
except:
|
||||
data = data.decode('utf-8')
|
||||
else:
|
||||
if data.startswith(codecs.BOM_UTF8):
|
||||
data = data.decode('utf-8')
|
||||
|
||||
try:
|
||||
|
||||
|
@ -523,9 +546,9 @@ def parse_dot_data(data):
|
|||
else:
|
||||
return [g for g in tokens]
|
||||
|
||||
except ParseException, err:
|
||||
|
||||
print err.line
|
||||
print " "*(err.column-1) + "^"
|
||||
print err
|
||||
except ParseException:
|
||||
err = sys.exc_info()[1]
|
||||
print(err.line)
|
||||
print(" "*(err.column-1) + "^")
|
||||
print(err)
|
||||
return None
|
||||
|
|
142
pydot.py
142
pydot.py
|
@ -17,22 +17,37 @@ Copyright (c) 2005-2011 Ero Carrera <ero.carrera@gmail.com>
|
|||
Distributed under MIT license [http://opensource.org/licenses/mit-license.html].
|
||||
"""
|
||||
|
||||
__revision__ = "$LastChangedRevision$"
|
||||
from __future__ import division, print_function
|
||||
|
||||
__author__ = 'Ero Carrera'
|
||||
__version__ = '1.0.%d' % int( __revision__[21:-2] )
|
||||
__version__ = '1.0.29'
|
||||
__license__ = 'MIT'
|
||||
|
||||
import os
|
||||
import re
|
||||
import subprocess
|
||||
import sys
|
||||
import tempfile
|
||||
import copy
|
||||
|
||||
from operator import itemgetter
|
||||
|
||||
try:
|
||||
import dot_parser
|
||||
except Exception, e:
|
||||
print "Couldn't import dot_parser, loading of dot files will not be possible."
|
||||
except Exception:
|
||||
print("Couldn't import dot_parser, loading of dot files will not be possible.")
|
||||
|
||||
|
||||
PY3 = not sys.version_info < (3, 0, 0)
|
||||
|
||||
if PY3:
|
||||
NULL_SEP = b''
|
||||
basestring = str
|
||||
long = int
|
||||
unicode = str
|
||||
else:
|
||||
NULL_SEP = ''
|
||||
|
||||
|
||||
GRAPH_ATTRIBUTES = set( ['Damping', 'K', 'URL', 'aspect', 'bb', 'bgcolor',
|
||||
'center', 'charset', 'clusterrank', 'colorscheme', 'comment', 'compound',
|
||||
|
@ -92,7 +107,7 @@ CLUSTER_ATTRIBUTES = set( ['K', 'URL', 'bgcolor', 'color', 'colorscheme',
|
|||
#
|
||||
class frozendict(dict):
|
||||
def _blocked_attribute(obj):
|
||||
raise AttributeError, "A frozendict cannot be modified."
|
||||
raise AttributeError("A frozendict cannot be modified.")
|
||||
_blocked_attribute = property(_blocked_attribute)
|
||||
|
||||
__delitem__ = __setitem__ = clear = _blocked_attribute
|
||||
|
@ -105,7 +120,7 @@ class frozendict(dict):
|
|||
for arg in args:
|
||||
if isinstance(arg, dict):
|
||||
arg = copy.copy(arg)
|
||||
for k, v in arg.iteritems():
|
||||
for k, v in arg.items():
|
||||
if isinstance(v, frozendict):
|
||||
arg[k] = v
|
||||
elif isinstance(v, dict):
|
||||
|
@ -132,7 +147,7 @@ class frozendict(dict):
|
|||
try:
|
||||
return self._cached_hash
|
||||
except AttributeError:
|
||||
h = self._cached_hash = hash(tuple(sorted(self.iteritems())))
|
||||
h = self._cached_hash = hash(tuple(sorted(self.items())))
|
||||
return h
|
||||
|
||||
def __repr__(self):
|
||||
|
@ -228,7 +243,7 @@ def graph_from_dot_file(path):
|
|||
representing the graph.
|
||||
"""
|
||||
|
||||
fd = file(path, 'rb')
|
||||
fd = open(path, 'rb')
|
||||
data = fd.read()
|
||||
fd.close()
|
||||
|
||||
|
@ -369,7 +384,7 @@ def __find_executables(path):
|
|||
|
||||
if os.path.isdir(path) :
|
||||
|
||||
for prg in progs.iterkeys():
|
||||
for prg in progs.keys():
|
||||
|
||||
if progs[prg]:
|
||||
continue
|
||||
|
@ -503,11 +518,11 @@ def find_graphviz():
|
|||
path = os.path.join(path, "bin")
|
||||
progs = __find_executables(path)
|
||||
if progs is not None :
|
||||
#print "Used Windows registry"
|
||||
#print("Used Windows registry")
|
||||
return progs
|
||||
|
||||
except Exception, excp:
|
||||
#raise excp
|
||||
except Exception:
|
||||
#raise
|
||||
pass
|
||||
else:
|
||||
break
|
||||
|
@ -516,12 +531,12 @@ def find_graphviz():
|
|||
|
||||
# Method 2 (Linux, Windows etc)
|
||||
#
|
||||
if os.environ.has_key('PATH'):
|
||||
if 'PATH' in os.environ:
|
||||
|
||||
for path in os.environ['PATH'].split(os.pathsep):
|
||||
progs = __find_executables(path)
|
||||
if progs is not None :
|
||||
#print "Used path"
|
||||
#print("Used path")
|
||||
return progs
|
||||
|
||||
# Method 3 (Windows only)
|
||||
|
@ -532,7 +547,7 @@ def find_graphviz():
|
|||
# machine (might be on drive D:, or in a different language)
|
||||
#
|
||||
|
||||
if os.environ.has_key('PROGRAMFILES'):
|
||||
if 'PROGRAMFILES' in os.environ:
|
||||
|
||||
# Note, we could also use the win32api to get this
|
||||
# information, but win32api may not be installed.
|
||||
|
@ -548,7 +563,7 @@ def find_graphviz():
|
|||
|
||||
if progs is not None :
|
||||
|
||||
#print "Used default install location"
|
||||
#print("Used default install location")
|
||||
return progs
|
||||
|
||||
|
||||
|
@ -560,7 +575,7 @@ def find_graphviz():
|
|||
|
||||
progs = __find_executables(path)
|
||||
if progs is not None :
|
||||
#print "Used path"
|
||||
#print("Used path")
|
||||
return progs
|
||||
|
||||
# Failed to find GraphViz
|
||||
|
@ -568,7 +583,7 @@ def find_graphviz():
|
|||
return None
|
||||
|
||||
|
||||
class Common:
|
||||
class Common(object):
|
||||
"""Common information to several classes.
|
||||
|
||||
Should not be directly used, several classes are derived from
|
||||
|
@ -717,7 +732,7 @@ class InvocationException(Exception):
|
|||
|
||||
|
||||
|
||||
class Node(object, Common):
|
||||
class Node(Common):
|
||||
"""A graph node.
|
||||
|
||||
This class represents a graph's node with all its attributes.
|
||||
|
@ -812,7 +827,7 @@ class Node(object, Common):
|
|||
|
||||
node_attr = list()
|
||||
|
||||
for attr, value in self.obj_dict['attributes'].iteritems():
|
||||
for attr, value in sorted(self.obj_dict['attributes'].items(), key=itemgetter(0)):
|
||||
if value is not None:
|
||||
node_attr.append( '%s=%s' % (attr, quote_if_necessary(value) ) )
|
||||
else:
|
||||
|
@ -834,7 +849,7 @@ class Node(object, Common):
|
|||
|
||||
|
||||
|
||||
class Edge(object, Common ):
|
||||
class Edge(Common):
|
||||
"""A graph edge.
|
||||
|
||||
This class represents a graph's edge with all its attributes.
|
||||
|
@ -847,7 +862,7 @@ class Edge(object, Common ):
|
|||
All the attributes defined in the Graphviz dot language should
|
||||
be supported.
|
||||
|
||||
Attributes can be set through the dynamically generated methods:
|
||||
Attributes can be set through the dynamically generated methods:
|
||||
|
||||
set_[attribute name], i.e. set_label, set_fontname
|
||||
|
||||
|
@ -925,7 +940,7 @@ class Edge(object, Common ):
|
|||
"""
|
||||
|
||||
if not isinstance(edge, Edge):
|
||||
raise Error, "Can't compare and edge to a non-edge object."
|
||||
raise Error("Can't compare and edge to a non-edge object.")
|
||||
|
||||
if self.get_parent_graph().get_top_graph_type() == 'graph':
|
||||
|
||||
|
@ -1007,7 +1022,7 @@ class Edge(object, Common ):
|
|||
|
||||
edge_attr = list()
|
||||
|
||||
for attr, value in self.obj_dict['attributes'].iteritems():
|
||||
for attr, value in sorted(self.obj_dict['attributes'].items(), key=itemgetter(0)):
|
||||
|
||||
if value is not None:
|
||||
edge_attr.append( '%s=%s' % (attr, quote_if_necessary(value) ) )
|
||||
|
@ -1025,7 +1040,7 @@ class Edge(object, Common ):
|
|||
|
||||
|
||||
|
||||
class Graph(object, Common):
|
||||
class Graph(Common):
|
||||
"""Class representing a graph in Graphviz's dot language.
|
||||
|
||||
This class implements the methods to work on a representation
|
||||
|
@ -1075,7 +1090,7 @@ class Graph(object, Common):
|
|||
self.obj_dict['attributes'] = dict(attrs)
|
||||
|
||||
if graph_type not in ['graph', 'digraph']:
|
||||
raise Error, 'Invalid type "%s". Accepted graph types are: graph, digraph, subgraph' % graph_type
|
||||
raise Error('Invalid type "%s". Accepted graph types are: graph, digraph, subgraph' % graph_type)
|
||||
|
||||
|
||||
self.obj_dict['name'] = quote_if_necessary(graph_name)
|
||||
|
@ -1311,7 +1326,7 @@ class Graph(object, Common):
|
|||
if isinstance(name, Node):
|
||||
name = name.get_name()
|
||||
|
||||
if self.obj_dict['nodes'].has_key(name):
|
||||
if name in self.obj_dict['nodes']:
|
||||
|
||||
if index is not None and index < len(self.obj_dict['nodes'][name]):
|
||||
del self.obj_dict['nodes'][name][index]
|
||||
|
@ -1336,7 +1351,7 @@ class Graph(object, Common):
|
|||
|
||||
match = list()
|
||||
|
||||
if self.obj_dict['nodes'].has_key(name):
|
||||
if name in self.obj_dict['nodes']:
|
||||
|
||||
match.extend( [ Node( obj_dict = obj_dict ) for obj_dict in self.obj_dict['nodes'][name] ])
|
||||
|
||||
|
@ -1358,7 +1373,7 @@ class Graph(object, Common):
|
|||
|
||||
node_objs = list()
|
||||
|
||||
for node, obj_dict_list in self.obj_dict['nodes'].iteritems():
|
||||
for node, obj_dict_list in self.obj_dict['nodes'].items():
|
||||
node_objs.extend( [ Node( obj_dict = obj_d ) for obj_d in obj_dict_list ] )
|
||||
|
||||
return node_objs
|
||||
|
@ -1377,7 +1392,7 @@ class Graph(object, Common):
|
|||
|
||||
edge_points = ( graph_edge.get_source(), graph_edge.get_destination() )
|
||||
|
||||
if self.obj_dict['edges'].has_key(edge_points):
|
||||
if edge_points in self.obj_dict['edges']:
|
||||
|
||||
edge_list = self.obj_dict['edges'][edge_points]
|
||||
edge_list.append(graph_edge.obj_dict)
|
||||
|
@ -1423,7 +1438,7 @@ class Graph(object, Common):
|
|||
if isinstance(dst, Node):
|
||||
dst = dst.get_name()
|
||||
|
||||
if self.obj_dict['edges'].has_key( (src, dst) ):
|
||||
if (src, dst) in self.obj_dict['edges']:
|
||||
|
||||
if index is not None and index < len(self.obj_dict['edges'][(src, dst)]):
|
||||
del self.obj_dict['edges'][(src, dst)][index]
|
||||
|
@ -1455,8 +1470,8 @@ class Graph(object, Common):
|
|||
|
||||
match = list()
|
||||
|
||||
if self.obj_dict['edges'].has_key( edge_points ) or (
|
||||
self.get_top_graph_type() == 'graph' and self.obj_dict['edges'].has_key( edge_points_reverse )):
|
||||
if edge_points in self.obj_dict['edges'] or (
|
||||
self.get_top_graph_type() == 'graph' and edge_points_reverse in self.obj_dict['edges']):
|
||||
|
||||
edges_obj_dict = self.obj_dict['edges'].get(
|
||||
edge_points,
|
||||
|
@ -1481,7 +1496,7 @@ class Graph(object, Common):
|
|||
|
||||
edge_objs = list()
|
||||
|
||||
for edge, obj_dict_list in self.obj_dict['edges'].iteritems():
|
||||
for edge, obj_dict_list in self.obj_dict['edges'].items():
|
||||
edge_objs.extend( [ Edge( obj_dict = obj_d ) for obj_d in obj_dict_list ] )
|
||||
|
||||
return edge_objs
|
||||
|
@ -1498,7 +1513,7 @@ class Graph(object, Common):
|
|||
if not isinstance(sgraph, Subgraph) and not isinstance(sgraph, Cluster):
|
||||
raise TypeError('add_subgraph() received a non subgraph class object:' + str(sgraph))
|
||||
|
||||
if self.obj_dict['subgraphs'].has_key(sgraph.get_name()):
|
||||
if sgraph.get_name() in self.obj_dict['subgraphs']:
|
||||
|
||||
sgraph_list = self.obj_dict['subgraphs'][ sgraph.get_name() ]
|
||||
sgraph_list.append( sgraph.obj_dict )
|
||||
|
@ -1526,7 +1541,7 @@ class Graph(object, Common):
|
|||
|
||||
match = list()
|
||||
|
||||
if self.obj_dict['subgraphs'].has_key( name ):
|
||||
if name in self.obj_dict['subgraphs']:
|
||||
|
||||
sgraphs_obj_dict = self.obj_dict['subgraphs'].get( name )
|
||||
|
||||
|
@ -1551,7 +1566,7 @@ class Graph(object, Common):
|
|||
|
||||
sgraph_objs = list()
|
||||
|
||||
for sgraph, obj_dict_list in self.obj_dict['subgraphs'].iteritems():
|
||||
for sgraph, obj_dict_list in self.obj_dict['subgraphs'].items():
|
||||
sgraph_objs.extend( [ Subgraph( obj_dict = obj_d ) for obj_d in obj_dict_list ] )
|
||||
|
||||
return sgraph_objs
|
||||
|
@ -1562,15 +1577,15 @@ class Graph(object, Common):
|
|||
|
||||
self.obj_dict['parent_graph'] = parent_graph
|
||||
|
||||
for obj_list in self.obj_dict['nodes'].itervalues():
|
||||
for obj_list in self.obj_dict['nodes'].values():
|
||||
for obj in obj_list:
|
||||
obj['parent_graph'] = parent_graph
|
||||
|
||||
for obj_list in self.obj_dict['edges'].itervalues():
|
||||
for obj_list in self.obj_dict['edges'].values():
|
||||
for obj in obj_list:
|
||||
obj['parent_graph'] = parent_graph
|
||||
|
||||
for obj_list in self.obj_dict['subgraphs'].itervalues():
|
||||
for obj_list in self.obj_dict['subgraphs'].values():
|
||||
for obj in obj_list:
|
||||
Graph(obj_dict=obj).set_parent_graph(parent_graph)
|
||||
|
||||
|
@ -1600,37 +1615,33 @@ class Graph(object, Common):
|
|||
graph.append( '%s %s {\n' % (self.obj_dict['type'], self.obj_dict['name']) )
|
||||
|
||||
|
||||
for attr in self.obj_dict['attributes'].iterkeys():
|
||||
for attr, value in sorted(self.obj_dict['attributes'].items(), key=itemgetter(0)):
|
||||
if value is not None:
|
||||
graph.append('%s=%s' % (attr, quote_if_necessary(value)))
|
||||
else:
|
||||
graph.append(attr)
|
||||
|
||||
if self.obj_dict['attributes'].get(attr, None) is not None:
|
||||
|
||||
val = self.obj_dict['attributes'].get(attr)
|
||||
if val is not None:
|
||||
graph.append( '%s=%s' % (attr, quote_if_necessary(val)) )
|
||||
else:
|
||||
graph.append( attr )
|
||||
|
||||
graph.append( ';\n' )
|
||||
graph.append( ';\n' )
|
||||
|
||||
|
||||
edges_done = set()
|
||||
|
||||
edge_obj_dicts = list()
|
||||
for e in self.obj_dict['edges'].itervalues():
|
||||
for e in self.obj_dict['edges'].values():
|
||||
edge_obj_dicts.extend(e)
|
||||
|
||||
if edge_obj_dicts:
|
||||
edge_src_set, edge_dst_set = zip( *[obj['points'] for obj in edge_obj_dicts] )
|
||||
edge_src_set, edge_dst_set = list(zip( *[obj['points'] for obj in edge_obj_dicts] ))
|
||||
edge_src_set, edge_dst_set = set(edge_src_set), set(edge_dst_set)
|
||||
else:
|
||||
edge_src_set, edge_dst_set = set(), set()
|
||||
|
||||
node_obj_dicts = list()
|
||||
for e in self.obj_dict['nodes'].itervalues():
|
||||
for e in self.obj_dict['nodes'].values():
|
||||
node_obj_dicts.extend(e)
|
||||
|
||||
sgraph_obj_dicts = list()
|
||||
for sg in self.obj_dict['subgraphs'].itervalues():
|
||||
for sg in self.obj_dict['subgraphs'].values():
|
||||
sgraph_obj_dicts.extend(sg)
|
||||
|
||||
|
||||
|
@ -1892,7 +1903,7 @@ class Dot(Graph):
|
|||
if prog is None:
|
||||
prog = self.prog
|
||||
|
||||
dot_fd = file(path, "w+b")
|
||||
dot_fd = open(path, "w+b")
|
||||
if format == 'raw':
|
||||
data = self.to_string()
|
||||
if isinstance(data, basestring):
|
||||
|
@ -1903,8 +1914,13 @@ class Dot(Graph):
|
|||
pass
|
||||
|
||||
try:
|
||||
data = data.encode('utf-8')
|
||||
charset = self.get_charset()
|
||||
if not PY3 or not charset:
|
||||
charset = 'utf-8'
|
||||
data = data.encode(charset)
|
||||
except:
|
||||
if PY3:
|
||||
data = data.encode('utf-8')
|
||||
pass
|
||||
dot_fd.write(data)
|
||||
else:
|
||||
|
@ -1952,7 +1968,7 @@ class Dot(Graph):
|
|||
raise InvocationException(
|
||||
'GraphViz\'s executables not found' )
|
||||
|
||||
if not self.progs.has_key(prog):
|
||||
if prog not in self.progs:
|
||||
raise InvocationException(
|
||||
'GraphViz\'s executable "%s" not found' % prog )
|
||||
|
||||
|
@ -1972,13 +1988,13 @@ class Dot(Graph):
|
|||
|
||||
# Get its data
|
||||
#
|
||||
f = file(img, 'rb')
|
||||
f = open(img, 'rb')
|
||||
f_data = f.read()
|
||||
f.close()
|
||||
|
||||
# And copy it under a file with the same name in the temporary directory
|
||||
#
|
||||
f = file( os.path.join( tmp_dir, os.path.basename(img) ), 'wb' )
|
||||
f = open( os.path.join( tmp_dir, os.path.basename(img) ), 'wb' )
|
||||
f.write(f_data)
|
||||
f.close()
|
||||
|
||||
|
@ -2000,7 +2016,7 @@ class Dot(Graph):
|
|||
stdout_output.append(data)
|
||||
stdout.close()
|
||||
|
||||
stdout_output = ''.join(stdout_output)
|
||||
stdout_output = NULL_SEP.join(stdout_output)
|
||||
|
||||
if not stderr.closed:
|
||||
stderr_output = list()
|
||||
|
@ -2012,7 +2028,9 @@ class Dot(Graph):
|
|||
stderr.close()
|
||||
|
||||
if stderr_output:
|
||||
stderr_output = ''.join(stderr_output)
|
||||
stderr_output = NULL_SEP.join(stderr_output)
|
||||
if PY3:
|
||||
stderr_output = stderr_output.decode(sys.stderr.encoding)
|
||||
|
||||
#pid, status = os.waitpid(p.pid, 0)
|
||||
status = p.wait()
|
||||
|
@ -2022,7 +2040,7 @@ class Dot(Graph):
|
|||
'Program terminated with status: %d. stderr follows: %s' % (
|
||||
status, stderr_output) )
|
||||
elif stderr_output:
|
||||
print stderr_output
|
||||
print(stderr_output)
|
||||
|
||||
# For each of the image files...
|
||||
#
|
||||
|
|
4
setup.py
4
setup.py
|
@ -2,7 +2,7 @@
|
|||
|
||||
try:
|
||||
from distutils.core import setup
|
||||
except ImportError, excp:
|
||||
except ImportError:
|
||||
from setuptools import setup
|
||||
|
||||
import pydot
|
||||
|
@ -31,5 +31,5 @@ setup( name = 'pydot',
|
|||
'Topic :: Software Development :: Libraries :: Python Modules'],
|
||||
long_description = "\n".join(pydot.__doc__.split('\n')),
|
||||
py_modules = ['pydot', 'dot_parser'],
|
||||
install_requires = ['pyparsing', 'setuptools'],
|
||||
install_requires = ['pyparsing'],
|
||||
data_files = [('.', ['LICENSE', 'README'])] )
|
||||
|
|
|
@ -5,6 +5,7 @@
|
|||
# -test del_node, del_edge methods
|
||||
# -test Common.set method
|
||||
|
||||
from __future__ import division, print_function
|
||||
|
||||
import os
|
||||
try:
|
||||
|
@ -13,12 +14,22 @@ except ImportError:
|
|||
import sha
|
||||
sha256 = sha.new
|
||||
import subprocess
|
||||
import sys
|
||||
|
||||
import pydot
|
||||
import dot_parser
|
||||
import unittest
|
||||
|
||||
|
||||
PY3 = not sys.version_info < (3, 0, 0)
|
||||
|
||||
if PY3:
|
||||
NULL_SEP = b''
|
||||
xrange = range
|
||||
else:
|
||||
NULL_SEP = ''
|
||||
bytes = str
|
||||
|
||||
DOT_BINARY_PATH = pydot.find_graphviz()['dot']
|
||||
TEST_DIR = './'
|
||||
REGRESSION_TESTS_DIR = os.path.join(TEST_DIR, 'graphs')
|
||||
|
@ -71,7 +82,7 @@ class TestGraphAPI(unittest.TestCase):
|
|||
g.add_node(node)
|
||||
node.set('label','mine')
|
||||
|
||||
self.assertEqual( g.to_string(), 'digraph G {\nlegend [shape=box, label=mine];\n}\n' )
|
||||
self.assertEqual( g.to_string(), 'digraph G {\nlegend [label=mine, shape=box];\n}\n' )
|
||||
|
||||
|
||||
def test_attribute_with_implicit_value(self):
|
||||
|
@ -109,7 +120,7 @@ class TestGraphAPI(unittest.TestCase):
|
|||
g.add_edge( pydot.Edge( ('D','E') ) )
|
||||
g.add_node( pydot.Node( 'node!' ) )
|
||||
|
||||
self.assertEqual( type(pickle.dumps(g)), str )
|
||||
self.assertEqual( type(pickle.dumps(g)), bytes )
|
||||
|
||||
|
||||
|
||||
|
@ -149,7 +160,7 @@ class TestGraphAPI(unittest.TestCase):
|
|||
pngs = dot_files = [ os.path.join(shapefile_dir, fname) for
|
||||
fname in os.listdir(shapefile_dir) if fname.endswith('.png') ]
|
||||
|
||||
f = file( dot_file, 'rt' )
|
||||
f = open( dot_file, 'rt' )
|
||||
graph_data = f.read()
|
||||
f.close()
|
||||
|
||||
|
@ -183,8 +194,8 @@ class TestGraphAPI(unittest.TestCase):
|
|||
|
||||
p = subprocess.Popen(
|
||||
( DOT_BINARY_PATH , '-Tjpe', ),
|
||||
cwd = os.path.dirname(filename),
|
||||
stdin=file(filename, 'rt'),
|
||||
cwd=os.path.dirname(filename),
|
||||
stdin=open(filename, 'rt'),
|
||||
stderr=subprocess.PIPE, stdout=subprocess.PIPE)
|
||||
|
||||
stdout = p.stdout
|
||||
|
@ -198,18 +209,17 @@ class TestGraphAPI(unittest.TestCase):
|
|||
stdout.close()
|
||||
|
||||
if stdout_output:
|
||||
stdout_output = ''.join(stdout_output)
|
||||
stdout_output = NULL_SEP.join(stdout_output)
|
||||
|
||||
#pid, status = os.waitpid(p.pid, 0)
|
||||
status = p.wait()
|
||||
|
||||
|
||||
return sha256(stdout_output).hexdigest()
|
||||
|
||||
|
||||
def _render_with_pydot(self, filename):
|
||||
|
||||
#f = file(filename, 'rt')
|
||||
#f = open(filename, 'rt')
|
||||
#graph_data = f.read()
|
||||
#f.close()
|
||||
|
||||
|
@ -220,7 +230,7 @@ class TestGraphAPI(unittest.TestCase):
|
|||
if not isinstance( g, list ):
|
||||
g = [g]
|
||||
|
||||
jpe_data = ''.join( [ _g.create( format='jpe' ) for _g in g ] )
|
||||
jpe_data = NULL_SEP.join( [ _g.create( format='jpe' ) for _g in g ] )
|
||||
|
||||
return sha256(jpe_data).hexdigest()
|
||||
|
||||
|
@ -253,13 +263,13 @@ class TestGraphAPI(unittest.TestCase):
|
|||
parsed_data_hexdigest = self._render_with_pydot(fname)
|
||||
|
||||
original_data_hexdigest = self._render_with_graphviz(fname)
|
||||
except Exception, excp:
|
||||
print 'Failed redering BAD(%s)' % dot
|
||||
except Exception:
|
||||
print('Failed rendering BAD(%s)' % dot)
|
||||
#print 'Error:', str(excp)
|
||||
raise excp
|
||||
raise
|
||||
|
||||
if parsed_data_hexdigest != original_data_hexdigest:
|
||||
print 'BAD(%s)' % dot
|
||||
print('BAD(%s)' % dot)
|
||||
|
||||
self.assertEqual( parsed_data_hexdigest, original_data_hexdigest )
|
||||
|
||||
|
|
Loading…
Reference in New Issue