summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorRaymond Hettinger <python@rcn.com>2009-11-01 20:55:33 (GMT)
committerRaymond Hettinger <python@rcn.com>2009-11-01 20:55:33 (GMT)
commitfc438518a0a3b471a187f0473b62a0dcaefd539e (patch)
tree45467853125d73333ccd7752ab80010dc00aa229
parentcafc22f0b82c93f8e905bb78f0b36c6bcdbd3a60 (diff)
downloadcpython-fc438518a0a3b471a187f0473b62a0dcaefd539e.zip
cpython-fc438518a0a3b471a187f0473b62a0dcaefd539e.tar.gz
cpython-fc438518a0a3b471a187f0473b62a0dcaefd539e.tar.bz2
Fix exception handling in itertools.izip_longest().
-rw-r--r--Lib/test/test_itertools.py40
-rw-r--r--Misc/NEWS3
-rw-r--r--Modules/itertoolsmodule.c72
3 files changed, 80 insertions, 35 deletions
diff --git a/Lib/test/test_itertools.py b/Lib/test/test_itertools.py
index d917262..2f449da 100644
--- a/Lib/test/test_itertools.py
+++ b/Lib/test/test_itertools.py
@@ -581,6 +581,46 @@ class TestBasicOps(unittest.TestCase):
ids = list(map(id, list(zip_longest('abc', 'def'))))
self.assertEqual(len(dict.fromkeys(ids)), len(ids))
+ def test_bug_7244(self):
+
+ class Repeater:
+ # this class is similar to itertools.repeat
+ def __init__(self, o, t, e):
+ self.o = o
+ self.t = int(t)
+ self.e = e
+ def __iter__(self): # its iterator is itself
+ return self
+ def __next__(self):
+ if self.t > 0:
+ self.t -= 1
+ return self.o
+ else:
+ raise self.e
+
+ # Formerly this code in would fail in debug mode
+ # with Undetected Error and Stop Iteration
+ r1 = Repeater(1, 3, StopIteration)
+ r2 = Repeater(2, 4, StopIteration)
+ def run(r1, r2):
+ result = []
+ for i, j in zip_longest(r1, r2, fillvalue=0):
+ with support.captured_output('stdout'):
+ print((i, j))
+ result.append((i, j))
+ return result
+ self.assertEqual(run(r1, r2), [(1,2), (1,2), (1,2), (0,2)])
+
+ # Formerly, the RuntimeError would be lost
+ # and StopIteration would stop as expected
+ r1 = Repeater(1, 3, RuntimeError)
+ r2 = Repeater(2, 4, StopIteration)
+ it = zip_longest(r1, r2, fillvalue=0)
+ self.assertEqual(next(it), (1, 2))
+ self.assertEqual(next(it), (1, 2))
+ self.assertEqual(next(it), (1, 2))
+ self.assertRaises(RuntimeError, next, it)
+
def test_product(self):
for args, result in [
([], [()]), # zero iterables
diff --git a/Misc/NEWS b/Misc/NEWS
index e979137..eda10c8 100644
--- a/Misc/NEWS
+++ b/Misc/NEWS
@@ -12,6 +12,9 @@ What's New in Python 3.2 Alpha 1?
Core and Builtins
-----------------
+- Issue #7244: itertools.izip_longest() no longer ignores exceptions
+ raised during the formation of an output tuple.
+
- Issue #3297: On wide unicode builds, do not split unicode characters into
surrogates.
diff --git a/Modules/itertoolsmodule.c b/Modules/itertoolsmodule.c
index 12144d0..1df9782 100644
--- a/Modules/itertoolsmodule.c
+++ b/Modules/itertoolsmodule.c
@@ -3344,71 +3344,73 @@ zip_longest_traverse(ziplongestobject *lz, visitproc visit, void *arg)
static PyObject *
zip_longest_next(ziplongestobject *lz)
{
- Py_ssize_t i;
- Py_ssize_t tuplesize = lz->tuplesize;
- PyObject *result = lz->result;
- PyObject *it;
- PyObject *item;
- PyObject *olditem;
-
- if (tuplesize == 0)
- return NULL;
+ Py_ssize_t i;
+ Py_ssize_t tuplesize = lz->tuplesize;
+ PyObject *result = lz->result;
+ PyObject *it;
+ PyObject *item;
+ PyObject *olditem;
+
+ if (tuplesize == 0)
+ return NULL;
if (lz->numactive == 0)
return NULL;
- if (Py_REFCNT(result) == 1) {
- Py_INCREF(result);
- for (i=0 ; i < tuplesize ; i++) {
- it = PyTuple_GET_ITEM(lz->ittuple, i);
+ if (Py_REFCNT(result) == 1) {
+ Py_INCREF(result);
+ for (i=0 ; i < tuplesize ; i++) {
+ it = PyTuple_GET_ITEM(lz->ittuple, i);
if (it == NULL) {
Py_INCREF(lz->fillvalue);
item = lz->fillvalue;
} else {
- item = (*Py_TYPE(it)->tp_iternext)(it);
+ item = PyIter_Next(it);
if (item == NULL) {
- lz->numactive -= 1;
- if (lz->numactive == 0) {
+ lz->numactive -= 1;
+ if (lz->numactive == 0 || PyErr_Occurred()) {
+ lz->numactive = 0;
Py_DECREF(result);
return NULL;
} else {
Py_INCREF(lz->fillvalue);
- item = lz->fillvalue;
+ item = lz->fillvalue;
PyTuple_SET_ITEM(lz->ittuple, i, NULL);
Py_DECREF(it);
}
}
}
- olditem = PyTuple_GET_ITEM(result, i);
- PyTuple_SET_ITEM(result, i, item);
- Py_DECREF(olditem);
- }
- } else {
- result = PyTuple_New(tuplesize);
- if (result == NULL)
- return NULL;
- for (i=0 ; i < tuplesize ; i++) {
- it = PyTuple_GET_ITEM(lz->ittuple, i);
+ olditem = PyTuple_GET_ITEM(result, i);
+ PyTuple_SET_ITEM(result, i, item);
+ Py_DECREF(olditem);
+ }
+ } else {
+ result = PyTuple_New(tuplesize);
+ if (result == NULL)
+ return NULL;
+ for (i=0 ; i < tuplesize ; i++) {
+ it = PyTuple_GET_ITEM(lz->ittuple, i);
if (it == NULL) {
Py_INCREF(lz->fillvalue);
item = lz->fillvalue;
} else {
- item = (*Py_TYPE(it)->tp_iternext)(it);
+ item = PyIter_Next(it);
if (item == NULL) {
- lz->numactive -= 1;
- if (lz->numactive == 0) {
+ lz->numactive -= 1;
+ if (lz->numactive == 0 || PyErr_Occurred()) {
+ lz->numactive = 0;
Py_DECREF(result);
return NULL;
} else {
Py_INCREF(lz->fillvalue);
- item = lz->fillvalue;
+ item = lz->fillvalue;
PyTuple_SET_ITEM(lz->ittuple, i, NULL);
Py_DECREF(it);
}
}
}
- PyTuple_SET_ITEM(result, i, item);
- }
- }
- return result;
+ PyTuple_SET_ITEM(result, i, item);
+ }
+ }
+ return result;
}
PyDoc_STRVAR(zip_longest_doc,