new: dev: Added Tox and CI integration.

This commit is contained in:
Carlos Miguel Jenkins Perez 2014-12-01 17:55:57 -06:00
parent fa561ada17
commit b074bb2298
9 changed files with 163 additions and 87 deletions

7
.travis.yml Normal file
View File

@ -0,0 +1,7 @@
language: python
install:
- pip install tox coveralls
script:
- tox
after_success:
- coveralls

View File

@ -28,4 +28,4 @@ PyDotPlus module entry.
"""
from .parser import * # noqa
from .graph import * # noqa
from .graphviz import * # noqa

View File

@ -596,11 +596,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:
#raise
# raise
pass
else:
break
@ -610,7 +610,7 @@ def find_graphviz():
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)
@ -625,14 +625,14 @@ def find_graphviz():
os.environ['PROGRAMFILES'], 'ATT', 'GraphViz', 'bin'
)
else:
#Just in case, try the default...
# Just in case, try the default...
path = r"C:\Program Files\att\Graphviz\bin"
progs = __find_executables(path)
if progs is not None:
#print("Used default install location")
# print("Used default install location")
return progs
for path in (
@ -643,7 +643,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
@ -756,7 +756,7 @@ class Common(object):
def create_attribute_methods(self, obj_attributes):
#for attr in self.obj_dict['attributes']:
# for attr in self.obj_dict['attributes']:
for attr in obj_attributes:
# Generate all the Setter methods.
@ -1296,7 +1296,7 @@ class Graph(Common):
graph_node.obj_dict
]
#self.node_dict[graph_node.get_name()] = graph_node.attributes
# self.node_dict[graph_node.get_name()] = graph_node.attributes
graph_node.set_parent_graph(self.get_parent_graph())
else:
self.obj_dict['nodes'][graph_node.get_name()].append(
@ -2033,7 +2033,7 @@ class Dot(Graph):
if PY3:
stderr_output = stderr_output.decode(sys.stderr.encoding)
#pid, status = os.waitpid(p.pid, 0)
# pid, status = os.waitpid(p.pid, 0)
status = p.wait()
if status != 0:

View File

@ -27,13 +27,13 @@
Graphviz's dot language parser.
The dotparser parses graphviz files in dot and dot files and transforms them
into a class representation defined by pydot.
into a class representation defined by pydotplus.
"""
from __future__ import division, print_function
import sys
import pydot
import pydotplus
import codecs
from pyparsing import __version__ as pyparsing_version
@ -104,7 +104,7 @@ def push_top_graph_stmt(str, loc, toks):
elif element in ['graph', 'digraph']:
attrs = {}
g = pydot.Dot(graph_type=element, **attrs)
g = pydotplus.Dot(graph_type=element, **attrs)
attrs['type'] = element
top_graphs.append(g)
@ -112,7 +112,7 @@ def push_top_graph_stmt(str, loc, toks):
elif isinstance(element, basestring):
g.set_name(element)
elif isinstance(element, pydot.Subgraph):
elif isinstance(element, pydotplus.Subgraph):
g.obj_dict['attributes'].update(element.obj_dict['attributes'])
g.obj_dict['edges'].update(element.obj_dict['edges'])
g.obj_dict['nodes'].update(element.obj_dict['nodes'])
@ -142,7 +142,7 @@ def update_parent_graph_hierarchy(g, parent_graph=None, level=0):
parent_graph = g
for key_name in ('edges',):
if isinstance(g, pydot.frozendict):
if isinstance(g, pydotplus.frozendict):
item_dict = g
else:
item_dict = g.obj_dict
@ -163,10 +163,14 @@ def update_parent_graph_hierarchy(g, parent_graph=None, level=0):
for idx, vertex in enumerate(obj['points']):
if isinstance(
vertex,
(pydot.Graph, pydot.Subgraph, pydot.Cluster)
(
pydotplus.Graph,
pydotplus.Subgraph,
pydotplus.Cluster
)
):
vertex.set_parent_graph(parent_graph)
if isinstance(vertex, pydot.frozendict):
if isinstance(vertex, pydotplus.frozendict):
if vertex['parent_graph'] is g:
pass
else:
@ -194,15 +198,15 @@ def add_elements(g, toks,
defaults_edge = {}
for elm_idx, element in enumerate(toks):
if isinstance(element, (pydot.Subgraph, pydot.Cluster)):
if isinstance(element, (pydotplus.Subgraph, pydotplus.Cluster)):
add_defaults(element, defaults_graph)
g.add_subgraph(element)
elif isinstance(element, pydot.Node):
elif isinstance(element, pydotplus.Node):
add_defaults(element, defaults_node)
g.add_node(element)
elif isinstance(element, pydot.Edge):
elif isinstance(element, pydotplus.Edge):
add_defaults(element, defaults_edge)
g.add_edge(element)
@ -214,15 +218,15 @@ def add_elements(g, toks,
elif isinstance(element, DefaultStatement):
if element.default_type == 'graph':
default_graph_attrs = pydot.Node('graph', **element.attrs)
default_graph_attrs = pydotplus.Node('graph', **element.attrs)
g.add_node(default_graph_attrs)
elif element.default_type == 'node':
default_node_attrs = pydot.Node('node', **element.attrs)
default_node_attrs = pydotplus.Node('node', **element.attrs)
g.add_node(default_node_attrs)
elif element.default_type == 'edge':
default_edge_attrs = pydot.Node('edge', **element.attrs)
default_edge_attrs = pydotplus.Node('edge', **element.attrs)
g.add_node(default_edge_attrs)
defaults_edge.update(element.attrs)
@ -239,13 +243,13 @@ def add_elements(g, toks,
def push_graph_stmt(str, loc, toks):
g = pydot.Subgraph('')
g = pydotplus.Subgraph('')
add_elements(g, toks)
return g
def push_subgraph_stmt(str, loc, toks):
g = pydot.Subgraph('')
g = pydotplus.Subgraph('')
for e in toks:
if len(e) == 3:
@ -309,8 +313,8 @@ def push_edge_stmt(str, loc, toks):
e = []
if isinstance(toks[0][0], pydot.Graph):
n_prev = pydot.frozendict(toks[0][0].obj_dict)
if isinstance(toks[0][0], pydotplus.Graph):
n_prev = pydotplus.frozendict(toks[0][0].obj_dict)
else:
n_prev = toks[0][0] + do_node_ports(toks[0])
@ -318,14 +322,18 @@ def push_edge_stmt(str, loc, toks):
n_next_list = [[n.get_name()] for n in toks[2][0]]
for n_next in [n for n in n_next_list]:
n_next_port = do_node_ports(n_next)
e.append(pydot.Edge(n_prev, n_next[0] + n_next_port, **attrs))
e.append(pydotplus.Edge(n_prev, n_next[0] + n_next_port, **attrs))
elif isinstance(toks[2][0], pydot.Graph):
elif isinstance(toks[2][0], pydotplus.Graph):
e.append(
pydot.Edge(n_prev, pydot.frozendict(toks[2][0].obj_dict), **attrs)
pydotplus.Edge(
n_prev,
pydotplus.frozendict(toks[2][0].obj_dict),
**attrs
)
)
elif isinstance(toks[2][0], pydot.Node):
elif isinstance(toks[2][0], pydotplus.Node):
node = toks[2][0]
if node.get_port() is not None:
@ -333,7 +341,7 @@ def push_edge_stmt(str, loc, toks):
else:
name_port = node.get_name()
e.append(pydot.Edge(n_prev, name_port, **attrs))
e.append(pydotplus.Edge(n_prev, name_port, **attrs))
elif isinstance(toks[2][0], type('')):
for n_next in [n for n in tuple(toks)[2::2]]:
@ -342,7 +350,7 @@ def push_edge_stmt(str, loc, toks):
continue
n_next_port = do_node_ports(n_next)
e.append(pydot.Edge(n_prev, n_next[0] + n_next_port, **attrs))
e.append(pydotplus.Edge(n_prev, n_next[0] + n_next_port, **attrs))
n_prev = n_next[0] + n_next_port
@ -365,7 +373,7 @@ def push_node_stmt(s, loc, toks):
if len(node_name) > 0:
node_name = node_name[0]
n = pydot.Node(str(node_name), **attrs)
n = pydotplus.Node(str(node_name), **attrs)
return n

8
requirements.dev.txt Normal file
View File

@ -0,0 +1,8 @@
tox
flake8
pytest
pytest-cov
coverage
coveralls
sphinx
sphinx_rtd_theme

1
requirements.txt Normal file
View File

@ -0,0 +1 @@
pyparsing>=2.0.1

View File

@ -44,7 +44,7 @@ def find_version(filename):
setup(
name='pydotplus',
version=find_version('lib/pydotplus/version.py'),
package_dir={'' : 'lib'},
package_dir={'': 'lib'},
packages=find_packages('lib'),
# Metadata

View File

@ -16,7 +16,7 @@ except ImportError:
import subprocess
import sys
import pydot
import pydotplus
import unittest
@ -30,7 +30,7 @@ else:
bytes = str
DOT_BINARY_PATH = pydot.find_graphviz()['dot']
DOT_BINARY_PATH = pydotplus.find_graphviz()['dot']
TEST_DIR = './'
REGRESSION_TESTS_DIR = os.path.join(TEST_DIR, 'graphs')
MY_REGRESSION_TESTS_DIR = os.path.join(TEST_DIR, 'my_tests')
@ -44,21 +44,23 @@ class TestGraphAPI(unittest.TestCase):
def _reset_graphs(self):
self.graph_directed = pydot.Graph('testgraph', graph_type='digraph')
self.graph_directed = pydotplus.Graph(
'testgraph', graph_type='digraph'
)
def test_keep_graph_type(self):
g = pydot.Dot(graph_name='Test', graph_type='graph')
g = pydotplus.Dot(graph_name='Test', graph_type='graph')
self.assertEqual(g.get_type(), 'graph')
g = pydot.Dot(graph_name='Test', graph_type='digraph')
g = pydotplus.Dot(graph_name='Test', graph_type='digraph')
self.assertEqual(g.get_type(), 'digraph')
def test_add_style(self):
node = pydot.Node('mynode')
node = pydotplus.Node('mynode')
node.add_style('abc')
self.assertEqual(node.get_style(), 'abc')
node.add_style('def')
@ -68,27 +70,30 @@ class TestGraphAPI(unittest.TestCase):
def test_create_simple_graph_with_node(self):
g = pydot.Dot()
g = pydotplus.Dot()
g.set_type('digraph')
node = pydot.Node('legend')
node = pydotplus.Node('legend')
node.set("shape", 'box')
g.add_node(node)
node.set('label', 'mine')
self.assertEqual(g.to_string(), 'digraph G {\nlegend [label=mine, shape=box];\n}\n')
self.assertEqual(
g.to_string(),
'digraph G {\nlegend [label=mine, shape=box];\n}\n'
)
def test_attribute_with_implicit_value(self):
d = 'digraph {\na -> b[label="hi", decorate];\n}'
g = pydot.graph_from_dot_data(d)
g = pydotplus.graph_from_dot_data(d)
attrs = g.get_edges()[0].get_attributes()
self.assertEqual('decorate' in attrs, True)
def test_subgraphs(self):
g = pydot.Graph()
s = pydot.Subgraph("foo")
g = pydotplus.Graph()
s = pydotplus.Subgraph("foo")
self.assertEqual(g.get_subgraphs(), [])
self.assertEqual(g.get_subgraph_list(), [])
@ -102,13 +107,13 @@ class TestGraphAPI(unittest.TestCase):
import pickle
g = pydot.Graph()
s = pydot.Subgraph("foo")
g = pydotplus.Graph()
s = pydotplus.Subgraph("foo")
g.add_subgraph(s)
g.add_edge(pydot.Edge('A', 'B'))
g.add_edge(pydot.Edge('A', 'C'))
g.add_edge(pydot.Edge(('D', 'E')))
g.add_node(pydot.Node('node!'))
g.add_edge(pydotplus.Edge('A', 'B'))
g.add_edge(pydotplus.Edge('A', 'C'))
g.add_edge(pydotplus.Edge(('D', 'E')))
g.add_node(pydotplus.Node('node!'))
self.assertEqual(type(pickle.dumps(g)), bytes)
@ -117,11 +122,11 @@ class TestGraphAPI(unittest.TestCase):
node1 = '"aánñoöüé€"'
node2 = '"îôø®çßΩ"'
g = pydot.Dot()
g = pydotplus.Dot()
g.set_charset('latin1')
g.add_node(pydot.Node(node1))
g.add_node(pydot.Node(node2))
g.add_edge(pydot.Edge(node1, node2))
g.add_node(pydotplus.Node(node1))
g.add_node(pydotplus.Node(node2))
g.add_edge(pydotplus.Edge(node1, node2))
self.assertEqual(g.get_node(node1)[0].get_name(), node1)
self.assertEqual(g.get_node(node2)[0].get_name(), node2)
@ -129,7 +134,7 @@ class TestGraphAPI(unittest.TestCase):
self.assertEqual(g.get_edges()[0].get_source(), node1)
self.assertEqual(g.get_edges()[0].get_destination(), node2)
g2 = pydot.graph_from_dot_data(g.to_string())
g2 = pydotplus.graph_from_dot_data(g.to_string())
self.assertEqual(g2.get_node(node1)[0].get_name(), node1)
self.assertEqual(g2.get_node(node2)[0].get_name(), node2)
@ -146,13 +151,13 @@ class TestGraphAPI(unittest.TestCase):
os.path.join(shapefile_dir, fname)
for fname in os.listdir(shapefile_dir)
if fname.endswith('.png')
]
]
f = open(dot_file, 'rt')
graph_data = f.read()
f.close()
g = pydot.graph_from_dot_data(graph_data)
g = pydotplus.graph_from_dot_data(graph_data)
g.set_shape_files(pngs)
@ -168,7 +173,7 @@ class TestGraphAPI(unittest.TestCase):
graph_data = 'graph A { a->b };\ngraph B {c->d}'
graphs = pydot.graph_from_dot_data(graph_data)
graphs = pydotplus.graph_from_dot_data(graph_data)
self.assertEqual(len(graphs), 2)
@ -181,7 +186,7 @@ class TestGraphAPI(unittest.TestCase):
cwd=os.path.dirname(filename),
stdin=open(filename, 'rt'),
stderr=subprocess.PIPE, stdout=subprocess.PIPE
)
)
stdout = p.stdout
@ -196,19 +201,19 @@ class TestGraphAPI(unittest.TestCase):
if stdout_output:
stdout_output = NULL_SEP.join(stdout_output)
#pid, status = os.waitpid(p.pid, 0)
# pid, status = os.waitpid(p.pid, 0)
# this returns a status code we should check
p.wait()
return sha256(stdout_output).hexdigest()
def _render_with_pydot(self, filename):
#f = open(filename, 'rt')
#graph_data = f.read()
#f.close()
# f = open(filename, 'rt')
# graph_data = f.read()
# f.close()
#g = pydot.parse_from_dot_data(graph_data)
g = pydot.graph_from_dot_file(filename)
# g = pydotplus.parse_from_dot_data(graph_data)
g = pydotplus.graph_from_dot_file(filename)
if not isinstance(g, list):
g = [g]
@ -228,10 +233,9 @@ class TestGraphAPI(unittest.TestCase):
dot_files = [
fname for fname in os.listdir(directory)
if fname.endswith('.dot')
] # and fname.startswith('')]
] # and fname.startswith('')]
for dot in dot_files:
#print 'Processing: %s' % dot
os.sys.stdout.write('#')
os.sys.stdout.flush()
@ -242,7 +246,6 @@ class TestGraphAPI(unittest.TestCase):
original_data_hexdigest = self._render_with_graphviz(fname)
except Exception:
print('Failed rendering BAD(%s)' % dot)
#print 'Error:', str(excp)
raise
if parsed_data_hexdigest != original_data_hexdigest:
@ -254,7 +257,7 @@ class TestGraphAPI(unittest.TestCase):
self._reset_graphs()
self.graph_directed.add_node(pydot.Node(1))
self.graph_directed.add_node(pydotplus.Node(1))
self.assertEqual(self.graph_directed.get_nodes()[0].get_name(), '1')
@ -262,23 +265,27 @@ class TestGraphAPI(unittest.TestCase):
self._reset_graphs()
self.graph_directed.add_node(pydot.Node('"node"'))
self.graph_directed.add_node(pydotplus.Node('"node"'))
self.assertEqual(self.graph_directed.get_nodes()[0].get_name(), '"node"')
self.assertEqual(
self.graph_directed.get_nodes()[0].get_name(), '"node"'
)
def test_quoted_node_id_to_string_no_attributes(self):
self._reset_graphs()
self.graph_directed.add_node(pydot.Node('"node"'))
self.graph_directed.add_node(pydotplus.Node('"node"'))
self.assertEqual(self.graph_directed.get_nodes()[0].to_string(), '"node";')
self.assertEqual(
self.graph_directed.get_nodes()[0].to_string(), '"node";'
)
def test_keyword_node_id(self):
self._reset_graphs()
self.graph_directed.add_node(pydot.Node('node'))
self.graph_directed.add_node(pydotplus.Node('node'))
self.assertEqual(self.graph_directed.get_nodes()[0].get_name(), 'node')
@ -286,7 +293,7 @@ class TestGraphAPI(unittest.TestCase):
self._reset_graphs()
self.graph_directed.add_node(pydot.Node('node'))
self.graph_directed.add_node(pydotplus.Node('node'))
self.assertEqual(self.graph_directed.get_nodes()[0].to_string(), '')
@ -294,9 +301,11 @@ class TestGraphAPI(unittest.TestCase):
self._reset_graphs()
self.graph_directed.add_node(pydot.Node('node', shape='box'))
self.graph_directed.add_node(pydotplus.Node('node', shape='box'))
self.assertEqual(self.graph_directed.get_nodes()[0].to_string(), 'node [shape=box];')
self.assertEqual(
self.graph_directed.get_nodes()[0].to_string(), 'node [shape=box];'
)
def test_names_of_a_thousand_nodes(self):
@ -306,18 +315,20 @@ class TestGraphAPI(unittest.TestCase):
for name in names:
self.graph_directed.add_node(pydot.Node(name, label=name))
self.graph_directed.add_node(pydotplus.Node(name, label=name))
self.assertEqual(set([n.get_name() for n in self.graph_directed.get_nodes()]), names)
self.assertEqual(
set([n.get_name() for n in self.graph_directed.get_nodes()]), names
)
def test_executable_not_found_exception(self):
paths = {'dot': 'invalid_executable_path'}
graph = pydot.Dot('graphname', graph_type='digraph')
graph = pydotplus.Dot('graphname', graph_type='digraph')
graph.set_graphviz_executables(paths)
self.assertRaises(pydot.InvocationException, graph.create)
self.assertRaises(pydotplus.InvocationException, graph.create)
def test_graph_add_node_argument_type(self):
@ -342,9 +353,8 @@ class TestGraphAPI(unittest.TestCase):
def test_quoting(self):
import string
g = pydot.Dot()
g.add_node(pydot.Node("test", label=string.printable))
#print g.to_string()
g = pydotplus.Dot()
g.add_node(pydotplus.Node("test", label=string.printable))
data = g.create(format='jpe')
self.assertEqual(len(data) > 0, True)

42
tox.ini Normal file
View File

@ -0,0 +1,42 @@
[tox]
envlist = py27, py34, coverage, docs
[testenv]
deps=
-rrequirements.txt
flake8
pytest
setenv=
PYTHONPATH=lib/
commands=
flake8
py.test
[testenv:coverage]
deps=
-rrequirements.txt
pytest-cov
coveralls
setenv=
PYTHONPATH=lib/
commands=
py.test --cov pydotplus
[testenv:docs]
basepython=python
changedir=doc
whitelist_externals=
make
dot
deps=
-rrequirements.txt
sphinx
sphinx_rtd_theme
commands=
make html
[flake8]
exclude = ./doc/*,.tox/*,.git/*
[pytest]
addopts = --doctest-modules --ignore=setup.py --ignore=doc/conf.py