diff -r 60430bdcb426 Lib/test/list_tests.py --- a/Lib/test/list_tests.py Tue Mar 08 01:11:14 2016 -0500 +++ b/Lib/test/list_tests.py Tue Mar 08 11:38:22 2016 +0200 @@ -593,3 +593,14 @@ class CommonTest(seq_tests.CommonTest): def __iter__(self): raise KeyboardInterrupt self.assertRaises(KeyboardInterrupt, list, F()) + + def test_exhausted_iterator(self): + a = self.type2test([1, 2, 3]) + exhit = iter(a) + empit = iter(a) + for x in exhit: # exhaust the iterator + next(empit) # not exhausted + a.append(9) + self.assertEqual(list(exhit), []) + self.assertEqual(list(empit), [9]) + self.assertEqual(a, self.type2test([1, 2, 3, 9])) diff -r 60430bdcb426 Lib/test/test_array.py --- a/Lib/test/test_array.py Tue Mar 08 01:11:14 2016 -0500 +++ b/Lib/test/test_array.py Tue Mar 08 11:38:22 2016 +0200 @@ -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) diff -r 60430bdcb426 Lib/test/test_bytes.py --- a/Lib/test/test_bytes.py Tue Mar 08 01:11:14 2016 -0500 +++ b/Lib/test/test_bytes.py Tue Mar 08 11:38:22 2016 +0200 @@ -17,6 +17,7 @@ import unittest import test.support import test.string_tests import test.buffer_tests +import test.list_tests from test.support import bigaddrspacetest, MAX_Py_ssize_t @@ -1414,6 +1415,7 @@ class ByteArrayTest(BaseBytesTest, unitt b[:] = data self.assertEqual(list(it), []) + test_exhausted_iterator = test.list_tests.CommonTest.test_exhausted_iterator class AssortedBytesTest(unittest.TestCase): # diff -r 60430bdcb426 Lib/test/test_iter.py --- a/Lib/test/test_iter.py Tue Mar 08 01:11:14 2016 -0500 +++ b/Lib/test/test_iter.py Tue Mar 08 11:38:22 2016 +0200 @@ -189,6 +189,17 @@ class TestCase(unittest.TestCase): self.assertTrue(isinstance(it, collections.abc.Iterator)) self.assertEqual(list(it), []) + def test_mutating_seq_class_exhausted_iter(self): + a = SequenceClass(5) + exhit = iter(a) + empit = iter(a) + for x in exhit: # exhaust the iterator + next(empit) # not exhausted + a.n = 7 + self.assertEqual(list(exhit), []) + self.assertEqual(list(empit), [5, 6]) + self.assertEqual(list(a), [0, 1, 2, 3, 4, 5, 6]) + # Test a new_style class with __iter__ but no next() method def test_new_style_iter_class(self): class IterClass(object): diff -r 60430bdcb426 Modules/arraymodule.c --- a/Modules/arraymodule.c Tue Mar 08 01:11:14 2016 -0500 +++ b/Modules/arraymodule.c Tue Mar 08 11:38:22 2016 +0200 @@ -2875,9 +2875,19 @@ 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 +2916,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]