Skip to content

Commit ab0d198

Browse files
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.
1 parent f39c0ac commit ab0d198

File tree

3 files changed

+41
-6
lines changed

3 files changed

+41
-6
lines changed

Lib/test/test_array.py

Lines changed: 19 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -318,8 +318,19 @@ def test_iterator_pickle(self):
318318
d = pickle.dumps((itorig, orig), proto)
319319
it, a = pickle.loads(d)
320320
a.fromlist(data2)
321-
self.assertEqual(type(it), type(itorig))
322-
self.assertEqual(list(it), data2)
321+
self.assertEqual(list(it), [])
322+
323+
def test_exhausted_iterator(self):
324+
a = array.array(self.typecode, self.example)
325+
self.assertEqual(list(a), list(self.example))
326+
exhit = iter(a)
327+
empit = iter(a)
328+
for x in exhit: # exhaust the iterator
329+
next(empit) # not exhausted
330+
a.append(self.outside)
331+
self.assertEqual(list(exhit), [])
332+
self.assertEqual(list(empit), [self.outside])
333+
self.assertEqual(list(a), list(self.example) + [self.outside])
323334

324335
def test_insert(self):
325336
a = array.array(self.typecode, self.example)
@@ -1070,6 +1081,12 @@ def test_obsolete_write_lock(self):
10701081
a = array.array('B', b"")
10711082
self.assertRaises(BufferError, getbuffer_with_null_view, a)
10721083

1084+
def test_free_after_iterating(self):
1085+
support.check_free_after_iterating(self, iter, array.array,
1086+
(self.typecode,))
1087+
support.check_free_after_iterating(self, reversed, array.array,
1088+
(self.typecode,))
1089+
10731090
class StringTest(BaseTest):
10741091

10751092
def test_setitem(self):

Misc/NEWS

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -237,6 +237,10 @@ Core and Builtins
237237
Library
238238
-------
239239

240+
- Issue #26492: Exhausted iterator of array.array now conforms with the behavior
241+
of iterators of other mutable sequences: it lefts exhausted even if iterated
242+
array is extended.
243+
240244
- Issue #26641: doctest.DocFileTest and doctest.testfile() now support
241245
packages (module splitted into multiple directories) for the package
242246
parameter.

Modules/arraymodule.c

Lines changed: 18 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -2875,9 +2875,20 @@ array_iter(arrayobject *ao)
28752875
static PyObject *
28762876
arrayiter_next(arrayiterobject *it)
28772877
{
2878+
arrayobject *ao;
2879+
2880+
assert(it != NULL);
28782881
assert(PyArrayIter_Check(it));
2879-
if (it->index < Py_SIZE(it->ao))
2880-
return (*it->getitem)(it->ao, it->index++);
2882+
ao = it->ao;
2883+
if (ao == NULL) {
2884+
return NULL;
2885+
}
2886+
assert(array_Check(ao));
2887+
if (it->index < Py_SIZE(ao)) {
2888+
return (*it->getitem)(ao, it->index++);
2889+
}
2890+
it->ao = NULL;
2891+
Py_DECREF(ao);
28812892
return NULL;
28822893
}
28832894

@@ -2906,8 +2917,11 @@ static PyObject *
29062917
array_arrayiterator___reduce___impl(arrayiterobject *self)
29072918
/*[clinic end generated code: output=7898a52e8e66e016 input=a062ea1e9951417a]*/
29082919
{
2909-
return Py_BuildValue("N(O)n", _PyObject_GetBuiltin("iter"),
2910-
self->ao, self->index);
2920+
PyObject *func = _PyObject_GetBuiltin("iter");
2921+
if (self->ao == NULL) {
2922+
return Py_BuildValue("N(())", func);
2923+
}
2924+
return Py_BuildValue("N(O)n", func, self->ao, self->index);
29112925
}
29122926

29132927
/*[clinic input]

0 commit comments

Comments
 (0)