Issue 7244: fix exception handling in itertools.izip_longest().

This commit is contained in:
Raymond Hettinger 2009-11-01 08:53:21 +00:00
parent e2670af08b
commit 80d49b33b1
3 changed files with 47 additions and 5 deletions

View file

@ -398,6 +398,42 @@ class TestBasicOps(unittest.TestCase):
ids = map(id, list(izip_longest('abc', 'def'))) ids = map(id, list(izip_longest('abc', 'def')))
self.assertEqual(len(dict.fromkeys(ids)), len(ids)) self.assertEqual(len(dict.fromkeys(ids)), len(ids))
def test_bug_7244(self):
class Repeater(object):
# 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 izip_longest(r1, r2, fillvalue=0):
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)
mylist = lambda it: [v for v in it]
self.assertRaises(RuntimeError, mylist, izip_longest(r1, r2, fillvalue=0))
def test_product(self): def test_product(self):
for args, result in [ for args, result in [
([], [()]), # zero iterables ([], [()]), # zero iterables
@ -687,6 +723,7 @@ class TestBasicOps(unittest.TestCase):
self.assertRaises(StopIteration, f(lambda x:x, []).next) self.assertRaises(StopIteration, f(lambda x:x, []).next)
self.assertRaises(StopIteration, f(lambda x:x, StopNow()).next) self.assertRaises(StopIteration, f(lambda x:x, StopNow()).next)
class TestExamples(unittest.TestCase): class TestExamples(unittest.TestCase):
def test_chain(self): def test_chain(self):

View file

@ -24,6 +24,9 @@ Core and Builtins
Library Library
------- -------
- Issue #7244: itertools.izip_longest() no longer ignores exceptions
raised during the formation of an output tuple.
- Issue #7233: Fix a number of two-argument Decimal methods to make - Issue #7233: Fix a number of two-argument Decimal methods to make
sure that they accept an int or long as the second argument. Also sure that they accept an int or long as the second argument. Also
fix buggy handling of large arguments (those with coefficient longer fix buggy handling of large arguments (those with coefficient longer

View file

@ -3412,10 +3412,11 @@ izip_longest_next(iziplongestobject *lz)
item = lz->fillvalue; item = lz->fillvalue;
} else { } else {
assert(PyIter_Check(it)); assert(PyIter_Check(it));
item = (*Py_TYPE(it)->tp_iternext)(it); item = PyIter_Next(it);
if (item == NULL) { if (item == NULL) {
lz->numactive -= 1; lz->numactive -= 1;
if (lz->numactive == 0) { if (lz->numactive == 0 || PyErr_Occurred()) {
lz->numactive = 0;
Py_DECREF(result); Py_DECREF(result);
return NULL; return NULL;
} else { } else {
@ -3441,10 +3442,11 @@ izip_longest_next(iziplongestobject *lz)
item = lz->fillvalue; item = lz->fillvalue;
} else { } else {
assert(PyIter_Check(it)); assert(PyIter_Check(it));
item = (*Py_TYPE(it)->tp_iternext)(it); item = PyIter_Next(it);
if (item == NULL) { if (item == NULL) {
lz->numactive -= 1; lz->numactive -= 1;
if (lz->numactive == 0) { if (lz->numactive == 0 || PyErr_Occurred()) {
lz->numactive = 0;
Py_DECREF(result); Py_DECREF(result);
return NULL; return NULL;
} else { } else {