summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--glanceclient/common/utils.py6
-rw-r--r--glanceclient/tests/unit/test_utils.py13
2 files changed, 18 insertions, 1 deletions
diff --git a/glanceclient/common/utils.py b/glanceclient/common/utils.py
index 9016860..7410b3b 100644
--- a/glanceclient/common/utils.py
+++ b/glanceclient/common/utils.py
@@ -442,7 +442,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)
diff --git a/glanceclient/tests/unit/test_utils.py b/glanceclient/tests/unit/test_utils.py
index 564d7f6..e2c1780 100644
--- a/glanceclient/tests/unit/test_utils.py
+++ b/glanceclient/tests/unit/test_utils.py
@@ -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()