]> granicus.if.org Git - python/commitdiff
Issue #26492: Exhausted iterator of array.array now conforms with the behavior
authorSerhiy Storchaka <storchaka@gmail.com>
Wed, 30 Mar 2016 18:11:16 +0000 (21:11 +0300)
committerSerhiy Storchaka <storchaka@gmail.com>
Wed, 30 Mar 2016 18:11:16 +0000 (21:11 +0300)
of iterators of other mutable sequences: it lefts exhausted even if iterated
array is extended.

Lib/test/test_array.py
Misc/NEWS
Modules/arraymodule.c

index 482526eec1e08017c973120fe464f995adabf8c6..b4f2bf868c2cbd56a1937134dba7f62fe02768e0 100644 (file)
@@ -318,8 +318,19 @@ class BaseTest:
             d = pickle.dumps((itorig, orig), proto)
             it, a = pickle.loads(d)
             a.fromlist(data2)
-            self.assertEqual(type(it), type(itorig))
-            self.assertEqual(list(it), data2)
+            self.assertEqual(list(it), [])
+
+    def test_exhausted_iterator(self):
+        a = array.array(self.typecode, self.example)
+        self.assertEqual(list(a), list(self.example))
+        exhit = iter(a)
+        empit = iter(a)
+        for x in exhit:  # exhaust the iterator
+            next(empit)  # not exhausted
+        a.append(self.outside)
+        self.assertEqual(list(exhit), [])
+        self.assertEqual(list(empit), [self.outside])
+        self.assertEqual(list(a), list(self.example) + [self.outside])
 
     def test_insert(self):
         a = array.array(self.typecode, self.example)
@@ -1070,6 +1081,12 @@ class BaseTest:
         a = array.array('B', b"")
         self.assertRaises(BufferError, getbuffer_with_null_view, a)
 
+    def test_free_after_iterating(self):
+        support.check_free_after_iterating(self, iter, array.array,
+                                           (self.typecode,))
+        support.check_free_after_iterating(self, reversed, array.array,
+                                           (self.typecode,))
+
 class StringTest(BaseTest):
 
     def test_setitem(self):
index 6fb0fc4fdda0b5d4b182daf61baa8c43eebc6153..6b6d11caa39912be3d0f2f86d0043de3a521894d 100644 (file)
--- a/Misc/NEWS
+++ b/Misc/NEWS
@@ -237,6 +237,10 @@ Core and Builtins
 Library
 -------
 
+- Issue #26492: Exhausted iterator of array.array now conforms with the behavior
+  of iterators of other mutable sequences: it lefts exhausted even if iterated
+  array is extended.
+
 - Issue #26641: doctest.DocFileTest and doctest.testfile() now support
   packages (module splitted into multiple directories) for the package
   parameter.
index 1b0a2823a1f08d08cda0a762597226ff87b5590e..323e0c1fff5b6abed9cded30d2a645a5ea7ca265 100644 (file)
@@ -2875,9 +2875,20 @@ array_iter(arrayobject *ao)
 static PyObject *
 arrayiter_next(arrayiterobject *it)
 {
+    arrayobject *ao;
+
+    assert(it != NULL);
     assert(PyArrayIter_Check(it));
-    if (it->index < Py_SIZE(it->ao))
-        return (*it->getitem)(it->ao, it->index++);
+    ao = it->ao;
+    if (ao == NULL) {
+        return NULL;
+    }
+    assert(array_Check(ao));
+    if (it->index < Py_SIZE(ao)) {
+        return (*it->getitem)(ao, it->index++);
+    }
+    it->ao = NULL;
+    Py_DECREF(ao);
     return NULL;
 }
 
@@ -2906,8 +2917,11 @@ static PyObject *
 array_arrayiterator___reduce___impl(arrayiterobject *self)
 /*[clinic end generated code: output=7898a52e8e66e016 input=a062ea1e9951417a]*/
 {
-    return Py_BuildValue("N(O)n", _PyObject_GetBuiltin("iter"),
-                         self->ao, self->index);
+    PyObject *func = _PyObject_GetBuiltin("iter");
+    if (self->ao == NULL) {
+        return Py_BuildValue("N(())", func);
+    }
+    return Py_BuildValue("N(O)n", func, self->ao, self->index);
 }
 
 /*[clinic input]