Close iterables at the end of iteration
This fixes a bug where if iteration is interrupted, we're stuck until the iterable is garbage collected, which can be a very long time (e.g. if the iterable is held in an exception stack frame). Co-authored-by: Stuart McLaren <stuart.mclaren@hp.com> Change-Id: Ibe9990e8c337c117a978b1cd8ec388c4bc6d3b4b Closes-bug: 1461678
This commit is contained in:
committed by
Stuart McLaren
parent
db6420b447
commit
43621dc1ac
@@ -434,7 +434,11 @@ class IterableWithLength(object):
|
||||
self.length = length
|
||||
|
||||
def __iter__(self):
|
||||
return self.iterable
|
||||
try:
|
||||
for chunk in self.iterable:
|
||||
yield chunk
|
||||
finally:
|
||||
self.iterable.close()
|
||||
|
||||
def next(self):
|
||||
return next(self.iterable)
|
||||
|
||||
@@ -15,6 +15,7 @@
|
||||
|
||||
import sys
|
||||
|
||||
import mock
|
||||
import six
|
||||
# NOTE(jokke): simplified transition to py3, behaves like py2 xrange
|
||||
from six.moves import range
|
||||
@@ -163,3 +164,15 @@ class TestUtils(testtools.TestCase):
|
||||
self.assertIn('--test', arg)
|
||||
self.assertEqual(str, opts['type'])
|
||||
self.assertIn('None, opt-1, opt-2', opts['help'])
|
||||
|
||||
def test_iterable_closes(self):
|
||||
# Regression test for bug 1461678.
|
||||
def _iterate(i):
|
||||
for chunk in i:
|
||||
raise(IOError)
|
||||
|
||||
data = six.moves.StringIO('somestring')
|
||||
data.close = mock.Mock()
|
||||
i = utils.IterableWithLength(data, 10)
|
||||
self.assertRaises(IOError, _iterate, i)
|
||||
data.close.assert_called_with()
|
||||
|
||||
Reference in New Issue
Block a user