Source: python-pygraphviz Version: 1.4~rc1-1+b2 Severity: grave Tags: patch Justification: renders package unusable
Hi, steps to reproduce: $ python3 --version Python 3.7.1 $ python3 -c 'import pygraphviz; A=pygraphviz.AGraph(); A.graph_attr.keys()' Traceback (most recent call last): File "/usr/lib/python3/dist-packages/pygraphviz/agraph.py", line 1743, in iteritems ah = gv.agnxtattr(self.handle, self.type, ah) StopIteration: agnxtattr The above exception was the direct cause of the following exception: Traceback (most recent call last): File "<string>", line 1, in <module> File "/usr/lib/python3/dist-packages/pygraphviz/agraph.py", line 1733, in keys return list(self.__iter__()) File "/usr/lib/python3/dist-packages/pygraphviz/agraph.py", line 1736, in __iter__ for (k, v) in self.iteritems(): RuntimeError: generator raised StopIteration This problem does not happen with snapshot 20181121T102052Z but does happen with snapshot 20181121T232318Z. There is only one change between chroots made from these two snapshots, the following packages have been upgraded from version 3.6.7-1 to 3.7.1-1: libpython3-stdlib, libpython3.6-minimal, libpython3.6-stdlib, python3, python3-minimal, python3.6, python3.6-minimal Thus I conclude that this problem was introduced because of the upgrade of Python from 3.6 to 3.7. Upstream has a fix here: https://github.com/pygraphviz/pygraphviz/commit/b5df022700669ae496f65d20dd9cd387d6af948e I backported that commit on top of the version of python-pygraphviz from Debian unstable. Please find the patch attached. I see that this package did not see an upload since January 2017. If you are okay with me NMU-ing the package for this fix, then please tell me. Alternatively, this bug can also be fixed by packaging the latest upstream version 1.5 of pygraphviz which includes the above commit. Thanks! cheers, josch
diff -Nru python-pygraphviz-1.4~rc1/debian/changelog python-pygraphviz-1.4~rc1/debian/changelog --- python-pygraphviz-1.4~rc1/debian/changelog 2017-01-08 21:03:20.000000000 +0100 +++ python-pygraphviz-1.4~rc1/debian/changelog 2018-11-22 19:31:03.000000000 +0100 @@ -1,3 +1,10 @@ +python-pygraphviz (1.4~rc1-1.1) UNRELEASED; urgency=medium + + * Non-maintainer upload. + * Fix StopIteration with Python 3.7 + + -- Johannes 'josch' Schauer <jo...@debian.org> Thu, 22 Nov 2018 19:31:03 +0100 + python-pygraphviz (1.4~rc1-1) unstable; urgency=medium * New upstream release candidate diff -Nru python-pygraphviz-1.4~rc1/debian/patches/catch_stopiterations_created_by_c_code python-pygraphviz-1.4~rc1/debian/patches/catch_stopiterations_created_by_c_code --- python-pygraphviz-1.4~rc1/debian/patches/catch_stopiterations_created_by_c_code 1970-01-01 01:00:00.000000000 +0100 +++ python-pygraphviz-1.4~rc1/debian/patches/catch_stopiterations_created_by_c_code 2018-11-22 19:30:55.000000000 +0100 @@ -0,0 +1,174 @@ +From b5df022700669ae496f65d20dd9cd387d6af948e Mon Sep 17 00:00:00 2001 +From: Dan Schult <dsch...@colgate.edu> +Date: Thu, 2 Aug 2018 21:32:47 -0400 +Subject: [PATCH] catch StopIterations created by C code + +--- a/pygraphviz/agraph.py ++++ b/pygraphviz/agraph.py +@@ -374,8 +374,10 @@ class AGraph(object): + 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 @@ class AGraph(object): + 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 @@ class AGraph(object): + 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 @@ class AGraph(object): + 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 @@ class AGraph(object): + 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 @@ class AGraph(object): + 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 @@ class AGraph(object): + 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 @@ class AGraph(object): + 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 @@ class AGraph(object): + 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,10 @@ class AGraph(object): + 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 +1119,10 @@ class AGraph(object): + 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.""" +@@ -1745,6 +1777,8 @@ class Attribute(MutableMapping): + 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 +1850,8 @@ class ItemAttribute(Attribute): + 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 -Nru python-pygraphviz-1.4~rc1/debian/patches/series python-pygraphviz-1.4~rc1/debian/patches/series --- python-pygraphviz-1.4~rc1/debian/patches/series 2017-01-08 21:03:20.000000000 +0100 +++ python-pygraphviz-1.4~rc1/debian/patches/series 2018-11-22 19:19:32.000000000 +0100 @@ -1 +1,2 @@ dont_install_data.patch +catch_stopiterations_created_by_c_code