• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1# Test iterators.
2
3import sys
4import unittest
5from test.support import run_unittest, TESTFN, unlink, cpython_only
6from test.support import check_free_after_iterating, ALWAYS_EQ, NEVER_EQ
7import pickle
8import collections.abc
9
10# Test result of triple loop (too big to inline)
11TRIPLETS = [(0, 0, 0), (0, 0, 1), (0, 0, 2),
12            (0, 1, 0), (0, 1, 1), (0, 1, 2),
13            (0, 2, 0), (0, 2, 1), (0, 2, 2),
14
15            (1, 0, 0), (1, 0, 1), (1, 0, 2),
16            (1, 1, 0), (1, 1, 1), (1, 1, 2),
17            (1, 2, 0), (1, 2, 1), (1, 2, 2),
18
19            (2, 0, 0), (2, 0, 1), (2, 0, 2),
20            (2, 1, 0), (2, 1, 1), (2, 1, 2),
21            (2, 2, 0), (2, 2, 1), (2, 2, 2)]
22
23# Helper classes
24
25class BasicIterClass:
26    def __init__(self, n):
27        self.n = n
28        self.i = 0
29    def __next__(self):
30        res = self.i
31        if res >= self.n:
32            raise StopIteration
33        self.i = res + 1
34        return res
35    def __iter__(self):
36        return self
37
38class IteratingSequenceClass:
39    def __init__(self, n):
40        self.n = n
41    def __iter__(self):
42        return BasicIterClass(self.n)
43
44class IteratorProxyClass:
45    def __init__(self, i):
46        self.i = i
47    def __next__(self):
48        return next(self.i)
49    def __iter__(self):
50        return self
51
52class SequenceClass:
53    def __init__(self, n):
54        self.n = n
55    def __getitem__(self, i):
56        if 0 <= i < self.n:
57            return i
58        else:
59            raise IndexError
60
61class SequenceProxyClass:
62    def __init__(self, s):
63        self.s = s
64    def __getitem__(self, i):
65        return self.s[i]
66
67class UnlimitedSequenceClass:
68    def __getitem__(self, i):
69        return i
70
71class DefaultIterClass:
72    pass
73
74class NoIterClass:
75    def __getitem__(self, i):
76        return i
77    __iter__ = None
78
79class BadIterableClass:
80    def __iter__(self):
81        raise ZeroDivisionError
82
83# Main test suite
84
85class TestCase(unittest.TestCase):
86
87    # Helper to check that an iterator returns a given sequence
88    def check_iterator(self, it, seq, pickle=True):
89        if pickle:
90            self.check_pickle(it, seq)
91        res = []
92        while 1:
93            try:
94                val = next(it)
95            except StopIteration:
96                break
97            res.append(val)
98        self.assertEqual(res, seq)
99
100    # Helper to check that a for loop generates a given sequence
101    def check_for_loop(self, expr, seq, pickle=True):
102        if pickle:
103            self.check_pickle(iter(expr), seq)
104        res = []
105        for val in expr:
106            res.append(val)
107        self.assertEqual(res, seq)
108
109    # Helper to check picklability
110    def check_pickle(self, itorg, seq):
111        for proto in range(pickle.HIGHEST_PROTOCOL + 1):
112            d = pickle.dumps(itorg, proto)
113            it = pickle.loads(d)
114            # Cannot assert type equality because dict iterators unpickle as list
115            # iterators.
116            # self.assertEqual(type(itorg), type(it))
117            self.assertTrue(isinstance(it, collections.abc.Iterator))
118            self.assertEqual(list(it), seq)
119
120            it = pickle.loads(d)
121            try:
122                next(it)
123            except StopIteration:
124                continue
125            d = pickle.dumps(it, proto)
126            it = pickle.loads(d)
127            self.assertEqual(list(it), seq[1:])
128
129    # Test basic use of iter() function
130    def test_iter_basic(self):
131        self.check_iterator(iter(range(10)), list(range(10)))
132
133    # Test that iter(iter(x)) is the same as iter(x)
134    def test_iter_idempotency(self):
135        seq = list(range(10))
136        it = iter(seq)
137        it2 = iter(it)
138        self.assertTrue(it is it2)
139
140    # Test that for loops over iterators work
141    def test_iter_for_loop(self):
142        self.check_for_loop(iter(range(10)), list(range(10)))
143
144    # Test several independent iterators over the same list
145    def test_iter_independence(self):
146        seq = range(3)
147        res = []
148        for i in iter(seq):
149            for j in iter(seq):
150                for k in iter(seq):
151                    res.append((i, j, k))
152        self.assertEqual(res, TRIPLETS)
153
154    # Test triple list comprehension using iterators
155    def test_nested_comprehensions_iter(self):
156        seq = range(3)
157        res = [(i, j, k)
158               for i in iter(seq) for j in iter(seq) for k in iter(seq)]
159        self.assertEqual(res, TRIPLETS)
160
161    # Test triple list comprehension without iterators
162    def test_nested_comprehensions_for(self):
163        seq = range(3)
164        res = [(i, j, k) for i in seq for j in seq for k in seq]
165        self.assertEqual(res, TRIPLETS)
166
167    # Test a class with __iter__ in a for loop
168    def test_iter_class_for(self):
169        self.check_for_loop(IteratingSequenceClass(10), list(range(10)))
170
171    # Test a class with __iter__ with explicit iter()
172    def test_iter_class_iter(self):
173        self.check_iterator(iter(IteratingSequenceClass(10)), list(range(10)))
174
175    # Test for loop on a sequence class without __iter__
176    def test_seq_class_for(self):
177        self.check_for_loop(SequenceClass(10), list(range(10)))
178
179    # Test iter() on a sequence class without __iter__
180    def test_seq_class_iter(self):
181        self.check_iterator(iter(SequenceClass(10)), list(range(10)))
182
183    def test_mutating_seq_class_iter_pickle(self):
184        orig = SequenceClass(5)
185        for proto in range(pickle.HIGHEST_PROTOCOL + 1):
186            # initial iterator
187            itorig = iter(orig)
188            d = pickle.dumps((itorig, orig), proto)
189            it, seq = pickle.loads(d)
190            seq.n = 7
191            self.assertIs(type(it), type(itorig))
192            self.assertEqual(list(it), list(range(7)))
193
194            # running iterator
195            next(itorig)
196            d = pickle.dumps((itorig, orig), proto)
197            it, seq = pickle.loads(d)
198            seq.n = 7
199            self.assertIs(type(it), type(itorig))
200            self.assertEqual(list(it), list(range(1, 7)))
201
202            # empty iterator
203            for i in range(1, 5):
204                next(itorig)
205            d = pickle.dumps((itorig, orig), proto)
206            it, seq = pickle.loads(d)
207            seq.n = 7
208            self.assertIs(type(it), type(itorig))
209            self.assertEqual(list(it), list(range(5, 7)))
210
211            # exhausted iterator
212            self.assertRaises(StopIteration, next, itorig)
213            d = pickle.dumps((itorig, orig), proto)
214            it, seq = pickle.loads(d)
215            seq.n = 7
216            self.assertTrue(isinstance(it, collections.abc.Iterator))
217            self.assertEqual(list(it), [])
218
219    def test_mutating_seq_class_exhausted_iter(self):
220        a = SequenceClass(5)
221        exhit = iter(a)
222        empit = iter(a)
223        for x in exhit:  # exhaust the iterator
224            next(empit)  # not exhausted
225        a.n = 7
226        self.assertEqual(list(exhit), [])
227        self.assertEqual(list(empit), [5, 6])
228        self.assertEqual(list(a), [0, 1, 2, 3, 4, 5, 6])
229
230    # Test a new_style class with __iter__ but no next() method
231    def test_new_style_iter_class(self):
232        class IterClass(object):
233            def __iter__(self):
234                return self
235        self.assertRaises(TypeError, iter, IterClass())
236
237    # Test two-argument iter() with callable instance
238    def test_iter_callable(self):
239        class C:
240            def __init__(self):
241                self.i = 0
242            def __call__(self):
243                i = self.i
244                self.i = i + 1
245                if i > 100:
246                    raise IndexError # Emergency stop
247                return i
248        self.check_iterator(iter(C(), 10), list(range(10)), pickle=False)
249
250    # Test two-argument iter() with function
251    def test_iter_function(self):
252        def spam(state=[0]):
253            i = state[0]
254            state[0] = i+1
255            return i
256        self.check_iterator(iter(spam, 10), list(range(10)), pickle=False)
257
258    # Test two-argument iter() with function that raises StopIteration
259    def test_iter_function_stop(self):
260        def spam(state=[0]):
261            i = state[0]
262            if i == 10:
263                raise StopIteration
264            state[0] = i+1
265            return i
266        self.check_iterator(iter(spam, 20), list(range(10)), pickle=False)
267
268    # Test exception propagation through function iterator
269    def test_exception_function(self):
270        def spam(state=[0]):
271            i = state[0]
272            state[0] = i+1
273            if i == 10:
274                raise RuntimeError
275            return i
276        res = []
277        try:
278            for x in iter(spam, 20):
279                res.append(x)
280        except RuntimeError:
281            self.assertEqual(res, list(range(10)))
282        else:
283            self.fail("should have raised RuntimeError")
284
285    # Test exception propagation through sequence iterator
286    def test_exception_sequence(self):
287        class MySequenceClass(SequenceClass):
288            def __getitem__(self, i):
289                if i == 10:
290                    raise RuntimeError
291                return SequenceClass.__getitem__(self, i)
292        res = []
293        try:
294            for x in MySequenceClass(20):
295                res.append(x)
296        except RuntimeError:
297            self.assertEqual(res, list(range(10)))
298        else:
299            self.fail("should have raised RuntimeError")
300
301    # Test for StopIteration from __getitem__
302    def test_stop_sequence(self):
303        class MySequenceClass(SequenceClass):
304            def __getitem__(self, i):
305                if i == 10:
306                    raise StopIteration
307                return SequenceClass.__getitem__(self, i)
308        self.check_for_loop(MySequenceClass(20), list(range(10)), pickle=False)
309
310    # Test a big range
311    def test_iter_big_range(self):
312        self.check_for_loop(iter(range(10000)), list(range(10000)))
313
314    # Test an empty list
315    def test_iter_empty(self):
316        self.check_for_loop(iter([]), [])
317
318    # Test a tuple
319    def test_iter_tuple(self):
320        self.check_for_loop(iter((0,1,2,3,4,5,6,7,8,9)), list(range(10)))
321
322    # Test a range
323    def test_iter_range(self):
324        self.check_for_loop(iter(range(10)), list(range(10)))
325
326    # Test a string
327    def test_iter_string(self):
328        self.check_for_loop(iter("abcde"), ["a", "b", "c", "d", "e"])
329
330    # Test a directory
331    def test_iter_dict(self):
332        dict = {}
333        for i in range(10):
334            dict[i] = None
335        self.check_for_loop(dict, list(dict.keys()))
336
337    # Test a file
338    def test_iter_file(self):
339        f = open(TESTFN, "w")
340        try:
341            for i in range(5):
342                f.write("%d\n" % i)
343        finally:
344            f.close()
345        f = open(TESTFN, "r")
346        try:
347            self.check_for_loop(f, ["0\n", "1\n", "2\n", "3\n", "4\n"], pickle=False)
348            self.check_for_loop(f, [], pickle=False)
349        finally:
350            f.close()
351            try:
352                unlink(TESTFN)
353            except OSError:
354                pass
355
356    # Test list()'s use of iterators.
357    def test_builtin_list(self):
358        self.assertEqual(list(SequenceClass(5)), list(range(5)))
359        self.assertEqual(list(SequenceClass(0)), [])
360        self.assertEqual(list(()), [])
361
362        d = {"one": 1, "two": 2, "three": 3}
363        self.assertEqual(list(d), list(d.keys()))
364
365        self.assertRaises(TypeError, list, list)
366        self.assertRaises(TypeError, list, 42)
367
368        f = open(TESTFN, "w")
369        try:
370            for i in range(5):
371                f.write("%d\n" % i)
372        finally:
373            f.close()
374        f = open(TESTFN, "r")
375        try:
376            self.assertEqual(list(f), ["0\n", "1\n", "2\n", "3\n", "4\n"])
377            f.seek(0, 0)
378            self.assertEqual(list(f),
379                             ["0\n", "1\n", "2\n", "3\n", "4\n"])
380        finally:
381            f.close()
382            try:
383                unlink(TESTFN)
384            except OSError:
385                pass
386
387    # Test tuples()'s use of iterators.
388    def test_builtin_tuple(self):
389        self.assertEqual(tuple(SequenceClass(5)), (0, 1, 2, 3, 4))
390        self.assertEqual(tuple(SequenceClass(0)), ())
391        self.assertEqual(tuple([]), ())
392        self.assertEqual(tuple(()), ())
393        self.assertEqual(tuple("abc"), ("a", "b", "c"))
394
395        d = {"one": 1, "two": 2, "three": 3}
396        self.assertEqual(tuple(d), tuple(d.keys()))
397
398        self.assertRaises(TypeError, tuple, list)
399        self.assertRaises(TypeError, tuple, 42)
400
401        f = open(TESTFN, "w")
402        try:
403            for i in range(5):
404                f.write("%d\n" % i)
405        finally:
406            f.close()
407        f = open(TESTFN, "r")
408        try:
409            self.assertEqual(tuple(f), ("0\n", "1\n", "2\n", "3\n", "4\n"))
410            f.seek(0, 0)
411            self.assertEqual(tuple(f),
412                             ("0\n", "1\n", "2\n", "3\n", "4\n"))
413        finally:
414            f.close()
415            try:
416                unlink(TESTFN)
417            except OSError:
418                pass
419
420    # Test filter()'s use of iterators.
421    def test_builtin_filter(self):
422        self.assertEqual(list(filter(None, SequenceClass(5))),
423                         list(range(1, 5)))
424        self.assertEqual(list(filter(None, SequenceClass(0))), [])
425        self.assertEqual(list(filter(None, ())), [])
426        self.assertEqual(list(filter(None, "abc")), ["a", "b", "c"])
427
428        d = {"one": 1, "two": 2, "three": 3}
429        self.assertEqual(list(filter(None, d)), list(d.keys()))
430
431        self.assertRaises(TypeError, filter, None, list)
432        self.assertRaises(TypeError, filter, None, 42)
433
434        class Boolean:
435            def __init__(self, truth):
436                self.truth = truth
437            def __bool__(self):
438                return self.truth
439        bTrue = Boolean(True)
440        bFalse = Boolean(False)
441
442        class Seq:
443            def __init__(self, *args):
444                self.vals = args
445            def __iter__(self):
446                class SeqIter:
447                    def __init__(self, vals):
448                        self.vals = vals
449                        self.i = 0
450                    def __iter__(self):
451                        return self
452                    def __next__(self):
453                        i = self.i
454                        self.i = i + 1
455                        if i < len(self.vals):
456                            return self.vals[i]
457                        else:
458                            raise StopIteration
459                return SeqIter(self.vals)
460
461        seq = Seq(*([bTrue, bFalse] * 25))
462        self.assertEqual(list(filter(lambda x: not x, seq)), [bFalse]*25)
463        self.assertEqual(list(filter(lambda x: not x, iter(seq))), [bFalse]*25)
464
465    # Test max() and min()'s use of iterators.
466    def test_builtin_max_min(self):
467        self.assertEqual(max(SequenceClass(5)), 4)
468        self.assertEqual(min(SequenceClass(5)), 0)
469        self.assertEqual(max(8, -1), 8)
470        self.assertEqual(min(8, -1), -1)
471
472        d = {"one": 1, "two": 2, "three": 3}
473        self.assertEqual(max(d), "two")
474        self.assertEqual(min(d), "one")
475        self.assertEqual(max(d.values()), 3)
476        self.assertEqual(min(iter(d.values())), 1)
477
478        f = open(TESTFN, "w")
479        try:
480            f.write("medium line\n")
481            f.write("xtra large line\n")
482            f.write("itty-bitty line\n")
483        finally:
484            f.close()
485        f = open(TESTFN, "r")
486        try:
487            self.assertEqual(min(f), "itty-bitty line\n")
488            f.seek(0, 0)
489            self.assertEqual(max(f), "xtra large line\n")
490        finally:
491            f.close()
492            try:
493                unlink(TESTFN)
494            except OSError:
495                pass
496
497    # Test map()'s use of iterators.
498    def test_builtin_map(self):
499        self.assertEqual(list(map(lambda x: x+1, SequenceClass(5))),
500                         list(range(1, 6)))
501
502        d = {"one": 1, "two": 2, "three": 3}
503        self.assertEqual(list(map(lambda k, d=d: (k, d[k]), d)),
504                         list(d.items()))
505        dkeys = list(d.keys())
506        expected = [(i < len(d) and dkeys[i] or None,
507                     i,
508                     i < len(d) and dkeys[i] or None)
509                    for i in range(3)]
510
511        f = open(TESTFN, "w")
512        try:
513            for i in range(10):
514                f.write("xy" * i + "\n") # line i has len 2*i+1
515        finally:
516            f.close()
517        f = open(TESTFN, "r")
518        try:
519            self.assertEqual(list(map(len, f)), list(range(1, 21, 2)))
520        finally:
521            f.close()
522            try:
523                unlink(TESTFN)
524            except OSError:
525                pass
526
527    # Test zip()'s use of iterators.
528    def test_builtin_zip(self):
529        self.assertEqual(list(zip()), [])
530        self.assertEqual(list(zip(*[])), [])
531        self.assertEqual(list(zip(*[(1, 2), 'ab'])), [(1, 'a'), (2, 'b')])
532
533        self.assertRaises(TypeError, zip, None)
534        self.assertRaises(TypeError, zip, range(10), 42)
535        self.assertRaises(TypeError, zip, range(10), zip)
536
537        self.assertEqual(list(zip(IteratingSequenceClass(3))),
538                         [(0,), (1,), (2,)])
539        self.assertEqual(list(zip(SequenceClass(3))),
540                         [(0,), (1,), (2,)])
541
542        d = {"one": 1, "two": 2, "three": 3}
543        self.assertEqual(list(d.items()), list(zip(d, d.values())))
544
545        # Generate all ints starting at constructor arg.
546        class IntsFrom:
547            def __init__(self, start):
548                self.i = start
549
550            def __iter__(self):
551                return self
552
553            def __next__(self):
554                i = self.i
555                self.i = i+1
556                return i
557
558        f = open(TESTFN, "w")
559        try:
560            f.write("a\n" "bbb\n" "cc\n")
561        finally:
562            f.close()
563        f = open(TESTFN, "r")
564        try:
565            self.assertEqual(list(zip(IntsFrom(0), f, IntsFrom(-100))),
566                             [(0, "a\n", -100),
567                              (1, "bbb\n", -99),
568                              (2, "cc\n", -98)])
569        finally:
570            f.close()
571            try:
572                unlink(TESTFN)
573            except OSError:
574                pass
575
576        self.assertEqual(list(zip(range(5))), [(i,) for i in range(5)])
577
578        # Classes that lie about their lengths.
579        class NoGuessLen5:
580            def __getitem__(self, i):
581                if i >= 5:
582                    raise IndexError
583                return i
584
585        class Guess3Len5(NoGuessLen5):
586            def __len__(self):
587                return 3
588
589        class Guess30Len5(NoGuessLen5):
590            def __len__(self):
591                return 30
592
593        def lzip(*args):
594            return list(zip(*args))
595
596        self.assertEqual(len(Guess3Len5()), 3)
597        self.assertEqual(len(Guess30Len5()), 30)
598        self.assertEqual(lzip(NoGuessLen5()), lzip(range(5)))
599        self.assertEqual(lzip(Guess3Len5()), lzip(range(5)))
600        self.assertEqual(lzip(Guess30Len5()), lzip(range(5)))
601
602        expected = [(i, i) for i in range(5)]
603        for x in NoGuessLen5(), Guess3Len5(), Guess30Len5():
604            for y in NoGuessLen5(), Guess3Len5(), Guess30Len5():
605                self.assertEqual(lzip(x, y), expected)
606
607    def test_unicode_join_endcase(self):
608
609        # This class inserts a Unicode object into its argument's natural
610        # iteration, in the 3rd position.
611        class OhPhooey:
612            def __init__(self, seq):
613                self.it = iter(seq)
614                self.i = 0
615
616            def __iter__(self):
617                return self
618
619            def __next__(self):
620                i = self.i
621                self.i = i+1
622                if i == 2:
623                    return "fooled you!"
624                return next(self.it)
625
626        f = open(TESTFN, "w")
627        try:
628            f.write("a\n" + "b\n" + "c\n")
629        finally:
630            f.close()
631
632        f = open(TESTFN, "r")
633        # Nasty:  string.join(s) can't know whether unicode.join() is needed
634        # until it's seen all of s's elements.  But in this case, f's
635        # iterator cannot be restarted.  So what we're testing here is
636        # whether string.join() can manage to remember everything it's seen
637        # and pass that on to unicode.join().
638        try:
639            got = " - ".join(OhPhooey(f))
640            self.assertEqual(got, "a\n - b\n - fooled you! - c\n")
641        finally:
642            f.close()
643            try:
644                unlink(TESTFN)
645            except OSError:
646                pass
647
648    # Test iterators with 'x in y' and 'x not in y'.
649    def test_in_and_not_in(self):
650        for sc5 in IteratingSequenceClass(5), SequenceClass(5):
651            for i in range(5):
652                self.assertIn(i, sc5)
653            for i in "abc", -1, 5, 42.42, (3, 4), [], {1: 1}, 3-12j, sc5:
654                self.assertNotIn(i, sc5)
655
656        self.assertIn(ALWAYS_EQ, IteratorProxyClass(iter([1])))
657        self.assertIn(ALWAYS_EQ, SequenceProxyClass([1]))
658        self.assertNotIn(ALWAYS_EQ, IteratorProxyClass(iter([NEVER_EQ])))
659        self.assertNotIn(ALWAYS_EQ, SequenceProxyClass([NEVER_EQ]))
660        self.assertIn(NEVER_EQ, IteratorProxyClass(iter([ALWAYS_EQ])))
661        self.assertIn(NEVER_EQ, SequenceProxyClass([ALWAYS_EQ]))
662
663        self.assertRaises(TypeError, lambda: 3 in 12)
664        self.assertRaises(TypeError, lambda: 3 not in map)
665        self.assertRaises(ZeroDivisionError, lambda: 3 in BadIterableClass())
666
667        d = {"one": 1, "two": 2, "three": 3, 1j: 2j}
668        for k in d:
669            self.assertIn(k, d)
670            self.assertNotIn(k, d.values())
671        for v in d.values():
672            self.assertIn(v, d.values())
673            self.assertNotIn(v, d)
674        for k, v in d.items():
675            self.assertIn((k, v), d.items())
676            self.assertNotIn((v, k), d.items())
677
678        f = open(TESTFN, "w")
679        try:
680            f.write("a\n" "b\n" "c\n")
681        finally:
682            f.close()
683        f = open(TESTFN, "r")
684        try:
685            for chunk in "abc":
686                f.seek(0, 0)
687                self.assertNotIn(chunk, f)
688                f.seek(0, 0)
689                self.assertIn((chunk + "\n"), f)
690        finally:
691            f.close()
692            try:
693                unlink(TESTFN)
694            except OSError:
695                pass
696
697    # Test iterators with operator.countOf (PySequence_Count).
698    def test_countOf(self):
699        from operator import countOf
700        self.assertEqual(countOf([1,2,2,3,2,5], 2), 3)
701        self.assertEqual(countOf((1,2,2,3,2,5), 2), 3)
702        self.assertEqual(countOf("122325", "2"), 3)
703        self.assertEqual(countOf("122325", "6"), 0)
704
705        self.assertRaises(TypeError, countOf, 42, 1)
706        self.assertRaises(TypeError, countOf, countOf, countOf)
707
708        d = {"one": 3, "two": 3, "three": 3, 1j: 2j}
709        for k in d:
710            self.assertEqual(countOf(d, k), 1)
711        self.assertEqual(countOf(d.values(), 3), 3)
712        self.assertEqual(countOf(d.values(), 2j), 1)
713        self.assertEqual(countOf(d.values(), 1j), 0)
714
715        f = open(TESTFN, "w")
716        try:
717            f.write("a\n" "b\n" "c\n" "b\n")
718        finally:
719            f.close()
720        f = open(TESTFN, "r")
721        try:
722            for letter, count in ("a", 1), ("b", 2), ("c", 1), ("d", 0):
723                f.seek(0, 0)
724                self.assertEqual(countOf(f, letter + "\n"), count)
725        finally:
726            f.close()
727            try:
728                unlink(TESTFN)
729            except OSError:
730                pass
731
732    # Test iterators with operator.indexOf (PySequence_Index).
733    def test_indexOf(self):
734        from operator import indexOf
735        self.assertEqual(indexOf([1,2,2,3,2,5], 1), 0)
736        self.assertEqual(indexOf((1,2,2,3,2,5), 2), 1)
737        self.assertEqual(indexOf((1,2,2,3,2,5), 3), 3)
738        self.assertEqual(indexOf((1,2,2,3,2,5), 5), 5)
739        self.assertRaises(ValueError, indexOf, (1,2,2,3,2,5), 0)
740        self.assertRaises(ValueError, indexOf, (1,2,2,3,2,5), 6)
741
742        self.assertEqual(indexOf("122325", "2"), 1)
743        self.assertEqual(indexOf("122325", "5"), 5)
744        self.assertRaises(ValueError, indexOf, "122325", "6")
745
746        self.assertRaises(TypeError, indexOf, 42, 1)
747        self.assertRaises(TypeError, indexOf, indexOf, indexOf)
748        self.assertRaises(ZeroDivisionError, indexOf, BadIterableClass(), 1)
749
750        f = open(TESTFN, "w")
751        try:
752            f.write("a\n" "b\n" "c\n" "d\n" "e\n")
753        finally:
754            f.close()
755        f = open(TESTFN, "r")
756        try:
757            fiter = iter(f)
758            self.assertEqual(indexOf(fiter, "b\n"), 1)
759            self.assertEqual(indexOf(fiter, "d\n"), 1)
760            self.assertEqual(indexOf(fiter, "e\n"), 0)
761            self.assertRaises(ValueError, indexOf, fiter, "a\n")
762        finally:
763            f.close()
764            try:
765                unlink(TESTFN)
766            except OSError:
767                pass
768
769        iclass = IteratingSequenceClass(3)
770        for i in range(3):
771            self.assertEqual(indexOf(iclass, i), i)
772        self.assertRaises(ValueError, indexOf, iclass, -1)
773
774    # Test iterators with file.writelines().
775    def test_writelines(self):
776        f = open(TESTFN, "w")
777
778        try:
779            self.assertRaises(TypeError, f.writelines, None)
780            self.assertRaises(TypeError, f.writelines, 42)
781
782            f.writelines(["1\n", "2\n"])
783            f.writelines(("3\n", "4\n"))
784            f.writelines({'5\n': None})
785            f.writelines({})
786
787            # Try a big chunk too.
788            class Iterator:
789                def __init__(self, start, finish):
790                    self.start = start
791                    self.finish = finish
792                    self.i = self.start
793
794                def __next__(self):
795                    if self.i >= self.finish:
796                        raise StopIteration
797                    result = str(self.i) + '\n'
798                    self.i += 1
799                    return result
800
801                def __iter__(self):
802                    return self
803
804            class Whatever:
805                def __init__(self, start, finish):
806                    self.start = start
807                    self.finish = finish
808
809                def __iter__(self):
810                    return Iterator(self.start, self.finish)
811
812            f.writelines(Whatever(6, 6+2000))
813            f.close()
814
815            f = open(TESTFN)
816            expected = [str(i) + "\n" for i in range(1, 2006)]
817            self.assertEqual(list(f), expected)
818
819        finally:
820            f.close()
821            try:
822                unlink(TESTFN)
823            except OSError:
824                pass
825
826
827    # Test iterators on RHS of unpacking assignments.
828    def test_unpack_iter(self):
829        a, b = 1, 2
830        self.assertEqual((a, b), (1, 2))
831
832        a, b, c = IteratingSequenceClass(3)
833        self.assertEqual((a, b, c), (0, 1, 2))
834
835        try:    # too many values
836            a, b = IteratingSequenceClass(3)
837        except ValueError:
838            pass
839        else:
840            self.fail("should have raised ValueError")
841
842        try:    # not enough values
843            a, b, c = IteratingSequenceClass(2)
844        except ValueError:
845            pass
846        else:
847            self.fail("should have raised ValueError")
848
849        try:    # not iterable
850            a, b, c = len
851        except TypeError:
852            pass
853        else:
854            self.fail("should have raised TypeError")
855
856        a, b, c = {1: 42, 2: 42, 3: 42}.values()
857        self.assertEqual((a, b, c), (42, 42, 42))
858
859        f = open(TESTFN, "w")
860        lines = ("a\n", "bb\n", "ccc\n")
861        try:
862            for line in lines:
863                f.write(line)
864        finally:
865            f.close()
866        f = open(TESTFN, "r")
867        try:
868            a, b, c = f
869            self.assertEqual((a, b, c), lines)
870        finally:
871            f.close()
872            try:
873                unlink(TESTFN)
874            except OSError:
875                pass
876
877        (a, b), (c,) = IteratingSequenceClass(2), {42: 24}
878        self.assertEqual((a, b, c), (0, 1, 42))
879
880
881    @cpython_only
882    def test_ref_counting_behavior(self):
883        class C(object):
884            count = 0
885            def __new__(cls):
886                cls.count += 1
887                return object.__new__(cls)
888            def __del__(self):
889                cls = self.__class__
890                assert cls.count > 0
891                cls.count -= 1
892        x = C()
893        self.assertEqual(C.count, 1)
894        del x
895        self.assertEqual(C.count, 0)
896        l = [C(), C(), C()]
897        self.assertEqual(C.count, 3)
898        try:
899            a, b = iter(l)
900        except ValueError:
901            pass
902        del l
903        self.assertEqual(C.count, 0)
904
905
906    # Make sure StopIteration is a "sink state".
907    # This tests various things that weren't sink states in Python 2.2.1,
908    # plus various things that always were fine.
909
910    def test_sinkstate_list(self):
911        # This used to fail
912        a = list(range(5))
913        b = iter(a)
914        self.assertEqual(list(b), list(range(5)))
915        a.extend(range(5, 10))
916        self.assertEqual(list(b), [])
917
918    def test_sinkstate_tuple(self):
919        a = (0, 1, 2, 3, 4)
920        b = iter(a)
921        self.assertEqual(list(b), list(range(5)))
922        self.assertEqual(list(b), [])
923
924    def test_sinkstate_string(self):
925        a = "abcde"
926        b = iter(a)
927        self.assertEqual(list(b), ['a', 'b', 'c', 'd', 'e'])
928        self.assertEqual(list(b), [])
929
930    def test_sinkstate_sequence(self):
931        # This used to fail
932        a = SequenceClass(5)
933        b = iter(a)
934        self.assertEqual(list(b), list(range(5)))
935        a.n = 10
936        self.assertEqual(list(b), [])
937
938    def test_sinkstate_callable(self):
939        # This used to fail
940        def spam(state=[0]):
941            i = state[0]
942            state[0] = i+1
943            if i == 10:
944                raise AssertionError("shouldn't have gotten this far")
945            return i
946        b = iter(spam, 5)
947        self.assertEqual(list(b), list(range(5)))
948        self.assertEqual(list(b), [])
949
950    def test_sinkstate_dict(self):
951        # XXX For a more thorough test, see towards the end of:
952        # http://mail.python.org/pipermail/python-dev/2002-July/026512.html
953        a = {1:1, 2:2, 0:0, 4:4, 3:3}
954        for b in iter(a), a.keys(), a.items(), a.values():
955            b = iter(a)
956            self.assertEqual(len(list(b)), 5)
957            self.assertEqual(list(b), [])
958
959    def test_sinkstate_yield(self):
960        def gen():
961            for i in range(5):
962                yield i
963        b = gen()
964        self.assertEqual(list(b), list(range(5)))
965        self.assertEqual(list(b), [])
966
967    def test_sinkstate_range(self):
968        a = range(5)
969        b = iter(a)
970        self.assertEqual(list(b), list(range(5)))
971        self.assertEqual(list(b), [])
972
973    def test_sinkstate_enumerate(self):
974        a = range(5)
975        e = enumerate(a)
976        b = iter(e)
977        self.assertEqual(list(b), list(zip(range(5), range(5))))
978        self.assertEqual(list(b), [])
979
980    def test_3720(self):
981        # Avoid a crash, when an iterator deletes its next() method.
982        class BadIterator(object):
983            def __iter__(self):
984                return self
985            def __next__(self):
986                del BadIterator.__next__
987                return 1
988
989        try:
990            for i in BadIterator() :
991                pass
992        except TypeError:
993            pass
994
995    def test_extending_list_with_iterator_does_not_segfault(self):
996        # The code to extend a list with an iterator has a fair
997        # amount of nontrivial logic in terms of guessing how
998        # much memory to allocate in advance, "stealing" refs,
999        # and then shrinking at the end.  This is a basic smoke
1000        # test for that scenario.
1001        def gen():
1002            for i in range(500):
1003                yield i
1004        lst = [0] * 500
1005        for i in range(240):
1006            lst.pop(0)
1007        lst.extend(gen())
1008        self.assertEqual(len(lst), 760)
1009
1010    @cpython_only
1011    def test_iter_overflow(self):
1012        # Test for the issue 22939
1013        it = iter(UnlimitedSequenceClass())
1014        # Manually set `it_index` to PY_SSIZE_T_MAX-2 without a loop
1015        it.__setstate__(sys.maxsize - 2)
1016        self.assertEqual(next(it), sys.maxsize - 2)
1017        self.assertEqual(next(it), sys.maxsize - 1)
1018        with self.assertRaises(OverflowError):
1019            next(it)
1020        # Check that Overflow error is always raised
1021        with self.assertRaises(OverflowError):
1022            next(it)
1023
1024    def test_iter_neg_setstate(self):
1025        it = iter(UnlimitedSequenceClass())
1026        it.__setstate__(-42)
1027        self.assertEqual(next(it), 0)
1028        self.assertEqual(next(it), 1)
1029
1030    def test_free_after_iterating(self):
1031        check_free_after_iterating(self, iter, SequenceClass, (0,))
1032
1033    def test_error_iter(self):
1034        for typ in (DefaultIterClass, NoIterClass):
1035            self.assertRaises(TypeError, iter, typ())
1036        self.assertRaises(ZeroDivisionError, iter, BadIterableClass())
1037
1038
1039def test_main():
1040    run_unittest(TestCase)
1041
1042
1043if __name__ == "__main__":
1044    test_main()
1045