diff --git a/.travis.yml b/.travis.yml index 8a5c645b..ffbb2300 100644 --- a/.travis.yml +++ b/.travis.yml @@ -3,7 +3,7 @@ python: - "2.7" - "3.4" - "3.5" - - "3.6-dev" + - "3.6" - "pypy" addons: apt: @@ -11,6 +11,10 @@ addons: - graphviz matrix: include: + - os: linux + python: 3.7 + dist: xenial + sudo: true - os: osx language: generic before_install: brew install graphviz diff --git a/pygraphviz/agraph.py b/pygraphviz/agraph.py index 4cb8fc24..2ceaf4ee 100644 --- a/pygraphviz/agraph.py +++ b/pygraphviz/agraph.py @@ -374,8 +374,10 @@ def nodes_iter(self): nh = gv.agfstnode(self.handle) while nh is not None: yield Node(self, nh=nh) - nh = gv.agnxtnode(self.handle, nh) - raise StopIteration + try: + nh = gv.agnxtnode(self.handle, nh) + except StopIteration: + return iternodes = nodes_iter @@ -597,8 +599,10 @@ def neighbors_iter(self, n): yield Node(self, t) else: yield Node(self, s) - eh = gv.agnxtedge(self.handle, eh, nh) - raise StopIteration + try: + eh = gv.agnxtedge(self.handle, eh, nh) + except StopIteration: + return def neighbors(self, n): """Return a list of the nodes attached to n.""" @@ -627,8 +631,14 @@ def out_edges_iter(self, nbunch=None, keys=False): yield (e[0], e[1], e.name) else: yield e - eh = gv.agnxtout(self.handle, eh) - nh = gv.agnxtnode(self.handle, nh) + try: + eh = gv.agnxtout(self.handle, eh) + except StopIteration: + break + try: + nh = gv.agnxtnode(self.handle, nh) + except StopIteration: + return elif nbunch in self: # if nbunch is a single node n = Node(self, nbunch) nh = n.handle @@ -639,7 +649,10 @@ def out_edges_iter(self, nbunch=None, keys=False): yield (e[0], e[1], e.name) else: yield e - eh = gv.agnxtout(self.handle, eh) + try: + eh = gv.agnxtout(self.handle, eh) + except StopIteration: + return else: # if nbunch is a sequence of nodes try: bunch = [n for n in nbunch if n in self] @@ -657,8 +670,10 @@ def out_edges_iter(self, nbunch=None, keys=False): yield (e[0], e[1], e.name) else: yield e - eh = gv.agnxtout(self.handle, eh) - raise StopIteration + try: + eh = gv.agnxtout(self.handle, eh) + except StopIteration: + break iteroutedges = out_edges_iter @@ -683,8 +698,14 @@ def in_edges_iter(self, nbunch=None, keys=False): yield (e[0], e[1], e.name) else: yield e - eh = gv.agnxtin(self.handle, eh) - nh = gv.agnxtnode(self.handle, nh) + try: + eh = gv.agnxtin(self.handle, eh) + except StopIteration: + break + try: + nh = gv.agnxtnode(self.handle, nh) + except StopIteration: + return elif nbunch in self: # if nbunch is a single node n = Node(self, nbunch) nh = n.handle @@ -695,7 +716,10 @@ def in_edges_iter(self, nbunch=None, keys=False): yield (e[0], e[1], e.name) else: yield e - eh = gv.agnxtin(self.handle, eh) + try: + eh = gv.agnxtin(self.handle, eh) + except StopIteration: + break else: # if nbunch is a sequence of nodes try: bunch = [n for n in nbunch if n in self] @@ -713,8 +737,10 @@ def in_edges_iter(self, nbunch=None, keys=False): yield (e[0], e[1], e.name) else: yield e - eh = gv.agnxtin(self.handle, eh) - raise StopIteration + try: + eh = gv.agnxtin(self.handle, eh) + except StopIteration: + break def edges_iter(self, nbunch=None, keys=False): """Return iterator over edges in the graph. @@ -780,8 +806,10 @@ def predecessors_iter(self, n): yield Node(self, t) else: yield Node(self, s) - eh = gv.agnxtin(self.handle, eh) - raise StopIteration + try: + eh = gv.agnxtin(self.handle, eh) + except StopIteration: + return iterpred = predecessors_iter @@ -802,8 +830,11 @@ def successors_iter(self, n): yield Node(self, t) else: yield Node(self, s) - eh = gv.agnxtout(self.handle, eh) - raise StopIteration + try: + eh = gv.agnxtout(self.handle, eh) + except StopIteration: + return + itersucc = successors_iter @@ -1089,8 +1120,10 @@ def subgraphs_iter(self): yield self.__class__(strict=self.strict, directed=self.directed, handle=handle) - handle = gv.agnxtsubg(handle) - raise StopIteration + try: + handle = gv.agnxtsubg(handle) + except StopIteration: + return def subgraphs(self): """Return a list of all subgraphs in the graph.""" @@ -1194,7 +1227,7 @@ def read(self, path): try: self.handle = gv.agread(fh, None) except ValueError: - raise DotError + raise DotError("Invalid Input") except IOError: print("IO error reading file") @@ -1745,6 +1778,8 @@ def iteritems(self): gv.agattrdefval(ah).decode(self.encoding)) except KeyError: # gv.agattrdefval returned KeyError, skip continue + except StopIteration: # gv.agnxtattr is done, as are we + return class ItemAttribute(Attribute): @@ -1816,6 +1851,8 @@ def iteritems(self): value.decode(self.encoding)) except KeyError: # gv.agxget returned KeyError, skip continue + except StopIteration: # gv.agnxtattr is done, as are we + return def _test_suite(): import doctest diff --git a/pygraphviz/tests/test_graph.py b/pygraphviz/tests/test_graph.py index a6550647..53aed06c 100644 --- a/pygraphviz/tests/test_graph.py +++ b/pygraphviz/tests/test_graph.py @@ -291,9 +291,14 @@ def test_edges(self): [('1', '2'), ('2', '3')]) assert_equal(sorted([tuple(sorted(e)) for e in A.in_edges_iter()]), [('1', '2'), ('2', '3')]) + assert_equal(sorted(A.edges(1)), [('1', '2')]) + assert_equal(sorted(A.edges([1, 2])), [('1', '2'), ('2', '3')]) + assert_equal(sorted(A.edges_iter(1)), [('1', '2')]) assert_equal(sorted(A.out_edges(1)), [('1', '2')]) + assert_equal(sorted(A.out_edges([1, 2])), [('1', '2'), ('2', '3')]) assert_equal(sorted(A.out_edges_iter(1)), [('1', '2')]) assert_equal(sorted(A.in_edges(2)), [('1', '2')]) + assert_equal(sorted(A.in_edges([1, 2])), [('1', '2')]) assert_equal(sorted(A.in_edges_iter(2)), [('1', '2')]) assert_equal(A.predecessors(1), []) assert_equal(list(A.predecessors_iter(1)),[])