~ubuntu-branches/ubuntu/maverick/python3.1/maverick

« back to all changes in this revision

Viewing changes to Lib/test/test_iter.py

  • Committer: Bazaar Package Importer
  • Author(s): Matthias Klose
  • Date: 2009-03-23 00:01:27 UTC
  • Revision ID: james.westby@ubuntu.com-20090323000127-5fstfxju4ufrhthq
Tags: upstream-3.1~a1+20090322
ImportĀ upstreamĀ versionĀ 3.1~a1+20090322

Show diffs side-by-side

added added

removed removed

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