blob: 4495fa1ad726a20a6de3d11dde4d68dfbe98973b [file] [log] [blame]
Guido van Rossum8b48cf92001-04-21 13:33:54 +00001# Test iterators.
2
3import unittest
Florent Xicluna07627882010-03-21 01:14:24 +00004from test.test_support import run_unittest, TESTFN, unlink, have_unicode, \
Serhiy Storchaka14a7d632016-03-30 20:43:06 +03005 check_py3k_warnings, cpython_only, \
6 check_free_after_iterating
Guido van Rossum8b48cf92001-04-21 13:33:54 +00007
8# Test result of triple loop (too big to inline)
9TRIPLETS = [(0, 0, 0), (0, 0, 1), (0, 0, 2),
10 (0, 1, 0), (0, 1, 1), (0, 1, 2),
11 (0, 2, 0), (0, 2, 1), (0, 2, 2),
12
13 (1, 0, 0), (1, 0, 1), (1, 0, 2),
14 (1, 1, 0), (1, 1, 1), (1, 1, 2),
15 (1, 2, 0), (1, 2, 1), (1, 2, 2),
16
17 (2, 0, 0), (2, 0, 1), (2, 0, 2),
18 (2, 1, 0), (2, 1, 1), (2, 1, 2),
19 (2, 2, 0), (2, 2, 1), (2, 2, 2)]
20
21# Helper classes
22
23class BasicIterClass:
24 def __init__(self, n):
25 self.n = n
26 self.i = 0
27 def next(self):
28 res = self.i
29 if res >= self.n:
30 raise StopIteration
31 self.i = res + 1
32 return res
33
34class IteratingSequenceClass:
35 def __init__(self, n):
36 self.n = n
37 def __iter__(self):
38 return BasicIterClass(self.n)
39
40class SequenceClass:
41 def __init__(self, n):
42 self.n = n
43 def __getitem__(self, i):
44 if 0 <= i < self.n:
45 return i
46 else:
47 raise IndexError
48
49# Main test suite
50
51class TestCase(unittest.TestCase):
52
53 # Helper to check that an iterator returns a given sequence
54 def check_iterator(self, it, seq):
55 res = []
56 while 1:
57 try:
58 val = it.next()
59 except StopIteration:
60 break
61 res.append(val)
62 self.assertEqual(res, seq)
63
64 # Helper to check that a for loop generates a given sequence
65 def check_for_loop(self, expr, seq):
66 res = []
67 for val in expr:
68 res.append(val)
69 self.assertEqual(res, seq)
70
71 # Test basic use of iter() function
72 def test_iter_basic(self):
73 self.check_iterator(iter(range(10)), range(10))
74
75 # Test that iter(iter(x)) is the same as iter(x)
76 def test_iter_idempotency(self):
77 seq = range(10)
78 it = iter(seq)
79 it2 = iter(it)
Benjamin Peterson5c8da862009-06-30 22:57:08 +000080 self.assertTrue(it is it2)
Guido van Rossum8b48cf92001-04-21 13:33:54 +000081
82 # Test that for loops over iterators work
83 def test_iter_for_loop(self):
84 self.check_for_loop(iter(range(10)), range(10))
85
86 # Test several independent iterators over the same list
87 def test_iter_independence(self):
88 seq = range(3)
89 res = []
90 for i in iter(seq):
91 for j in iter(seq):
92 for k in iter(seq):
93 res.append((i, j, k))
94 self.assertEqual(res, TRIPLETS)
95
96 # Test triple list comprehension using iterators
97 def test_nested_comprehensions_iter(self):
98 seq = range(3)
99 res = [(i, j, k)
100 for i in iter(seq) for j in iter(seq) for k in iter(seq)]
101 self.assertEqual(res, TRIPLETS)
102
103 # Test triple list comprehension without iterators
104 def test_nested_comprehensions_for(self):
105 seq = range(3)
106 res = [(i, j, k) for i in seq for j in seq for k in seq]
107 self.assertEqual(res, TRIPLETS)
108
109 # Test a class with __iter__ in a for loop
110 def test_iter_class_for(self):
111 self.check_for_loop(IteratingSequenceClass(10), range(10))
112
113 # Test a class with __iter__ with explicit iter()
114 def test_iter_class_iter(self):
115 self.check_iterator(iter(IteratingSequenceClass(10)), range(10))
116
117 # Test for loop on a sequence class without __iter__
118 def test_seq_class_for(self):
119 self.check_for_loop(SequenceClass(10), range(10))
120
121 # Test iter() on a sequence class without __iter__
122 def test_seq_class_iter(self):
123 self.check_iterator(iter(SequenceClass(10)), range(10))
124
Amaury Forgeot d'Arca40d5732009-01-12 23:36:55 +0000125 # Test a new_style class with __iter__ but no next() method
126 def test_new_style_iter_class(self):
127 class IterClass(object):
128 def __iter__(self):
129 return self
130 self.assertRaises(TypeError, iter, IterClass())
131
Guido van Rossum8b48cf92001-04-21 13:33:54 +0000132 # Test two-argument iter() with callable instance
133 def test_iter_callable(self):
134 class C:
135 def __init__(self):
136 self.i = 0
137 def __call__(self):
138 i = self.i
139 self.i = i + 1
140 if i > 100:
141 raise IndexError # Emergency stop
142 return i
143 self.check_iterator(iter(C(), 10), range(10))
144
145 # Test two-argument iter() with function
146 def test_iter_function(self):
147 def spam(state=[0]):
148 i = state[0]
149 state[0] = i+1
150 return i
151 self.check_iterator(iter(spam, 10), range(10))
152
153 # Test two-argument iter() with function that raises StopIteration
154 def test_iter_function_stop(self):
155 def spam(state=[0]):
156 i = state[0]
157 if i == 10:
158 raise StopIteration
159 state[0] = i+1
160 return i
161 self.check_iterator(iter(spam, 20), range(10))
162
163 # Test exception propagation through function iterator
164 def test_exception_function(self):
165 def spam(state=[0]):
166 i = state[0]
167 state[0] = i+1
168 if i == 10:
169 raise RuntimeError
170 return i
171 res = []
172 try:
173 for x in iter(spam, 20):
174 res.append(x)
175 except RuntimeError:
176 self.assertEqual(res, range(10))
177 else:
178 self.fail("should have raised RuntimeError")
179
180 # Test exception propagation through sequence iterator
181 def test_exception_sequence(self):
182 class MySequenceClass(SequenceClass):
183 def __getitem__(self, i):
184 if i == 10:
185 raise RuntimeError
186 return SequenceClass.__getitem__(self, i)
187 res = []
188 try:
189 for x in MySequenceClass(20):
190 res.append(x)
191 except RuntimeError:
192 self.assertEqual(res, range(10))
193 else:
194 self.fail("should have raised RuntimeError")
195
196 # Test for StopIteration from __getitem__
197 def test_stop_sequence(self):
198 class MySequenceClass(SequenceClass):
199 def __getitem__(self, i):
200 if i == 10:
201 raise StopIteration
202 return SequenceClass.__getitem__(self, i)
203 self.check_for_loop(MySequenceClass(20), range(10))
204
205 # Test a big range
206 def test_iter_big_range(self):
207 self.check_for_loop(iter(range(10000)), range(10000))
208
209 # Test an empty list
210 def test_iter_empty(self):
211 self.check_for_loop(iter([]), [])
212
213 # Test a tuple
214 def test_iter_tuple(self):
215 self.check_for_loop(iter((0,1,2,3,4,5,6,7,8,9)), range(10))
216
217 # Test an xrange
218 def test_iter_xrange(self):
219 self.check_for_loop(iter(xrange(10)), range(10))
220
221 # Test a string
222 def test_iter_string(self):
223 self.check_for_loop(iter("abcde"), ["a", "b", "c", "d", "e"])
224
225 # Test a Unicode string
Martin v. Löwis339d0f72001-08-17 18:39:25 +0000226 if have_unicode:
227 def test_iter_unicode(self):
228 self.check_for_loop(iter(unicode("abcde")),
229 [unicode("a"), unicode("b"), unicode("c"),
230 unicode("d"), unicode("e")])
Guido van Rossum8b48cf92001-04-21 13:33:54 +0000231
232 # Test a directory
233 def test_iter_dict(self):
234 dict = {}
235 for i in range(10):
236 dict[i] = None
237 self.check_for_loop(dict, dict.keys())
238
239 # Test a file
240 def test_iter_file(self):
241 f = open(TESTFN, "w")
242 try:
243 for i in range(5):
244 f.write("%d\n" % i)
245 finally:
246 f.close()
247 f = open(TESTFN, "r")
248 try:
249 self.check_for_loop(f, ["0\n", "1\n", "2\n", "3\n", "4\n"])
250 self.check_for_loop(f, [])
251 finally:
252 f.close()
253 try:
254 unlink(TESTFN)
255 except OSError:
256 pass
257
Tim Petersf553f892001-05-01 20:45:31 +0000258 # Test list()'s use of iterators.
259 def test_builtin_list(self):
260 self.assertEqual(list(SequenceClass(5)), range(5))
261 self.assertEqual(list(SequenceClass(0)), [])
262 self.assertEqual(list(()), [])
263 self.assertEqual(list(range(10, -1, -1)), range(10, -1, -1))
264
265 d = {"one": 1, "two": 2, "three": 3}
266 self.assertEqual(list(d), d.keys())
267
268 self.assertRaises(TypeError, list, list)
269 self.assertRaises(TypeError, list, 42)
270
271 f = open(TESTFN, "w")
272 try:
273 for i in range(5):
274 f.write("%d\n" % i)
275 finally:
276 f.close()
277 f = open(TESTFN, "r")
278 try:
279 self.assertEqual(list(f), ["0\n", "1\n", "2\n", "3\n", "4\n"])
280 f.seek(0, 0)
Guido van Rossum8ee52432002-08-06 17:14:04 +0000281 self.assertEqual(list(f),
Tim Petersf553f892001-05-01 20:45:31 +0000282 ["0\n", "1\n", "2\n", "3\n", "4\n"])
283 finally:
284 f.close()
285 try:
286 unlink(TESTFN)
287 except OSError:
288 pass
289
Tim Peters6912d4d2001-05-05 03:56:37 +0000290 # Test tuples()'s use of iterators.
291 def test_builtin_tuple(self):
292 self.assertEqual(tuple(SequenceClass(5)), (0, 1, 2, 3, 4))
293 self.assertEqual(tuple(SequenceClass(0)), ())
294 self.assertEqual(tuple([]), ())
295 self.assertEqual(tuple(()), ())
296 self.assertEqual(tuple("abc"), ("a", "b", "c"))
297
298 d = {"one": 1, "two": 2, "three": 3}
299 self.assertEqual(tuple(d), tuple(d.keys()))
300
301 self.assertRaises(TypeError, tuple, list)
302 self.assertRaises(TypeError, tuple, 42)
303
304 f = open(TESTFN, "w")
305 try:
306 for i in range(5):
307 f.write("%d\n" % i)
308 finally:
309 f.close()
310 f = open(TESTFN, "r")
311 try:
312 self.assertEqual(tuple(f), ("0\n", "1\n", "2\n", "3\n", "4\n"))
313 f.seek(0, 0)
Guido van Rossum8ee52432002-08-06 17:14:04 +0000314 self.assertEqual(tuple(f),
Tim Peters6912d4d2001-05-05 03:56:37 +0000315 ("0\n", "1\n", "2\n", "3\n", "4\n"))
316 finally:
317 f.close()
318 try:
319 unlink(TESTFN)
320 except OSError:
321 pass
322
Tim Peters0e57abf2001-05-02 07:39:38 +0000323 # Test filter()'s use of iterators.
324 def test_builtin_filter(self):
325 self.assertEqual(filter(None, SequenceClass(5)), range(1, 5))
326 self.assertEqual(filter(None, SequenceClass(0)), [])
327 self.assertEqual(filter(None, ()), ())
328 self.assertEqual(filter(None, "abc"), "abc")
329
330 d = {"one": 1, "two": 2, "three": 3}
331 self.assertEqual(filter(None, d), d.keys())
332
333 self.assertRaises(TypeError, filter, None, list)
334 self.assertRaises(TypeError, filter, None, 42)
335
336 class Boolean:
337 def __init__(self, truth):
338 self.truth = truth
339 def __nonzero__(self):
340 return self.truth
Tim Peterscae330e2002-12-23 16:50:58 +0000341 bTrue = Boolean(1)
342 bFalse = Boolean(0)
Tim Peters0e57abf2001-05-02 07:39:38 +0000343
344 class Seq:
345 def __init__(self, *args):
346 self.vals = args
347 def __iter__(self):
348 class SeqIter:
349 def __init__(self, vals):
350 self.vals = vals
351 self.i = 0
352 def __iter__(self):
353 return self
354 def next(self):
355 i = self.i
356 self.i = i + 1
357 if i < len(self.vals):
358 return self.vals[i]
359 else:
360 raise StopIteration
361 return SeqIter(self.vals)
362
Tim Peterscae330e2002-12-23 16:50:58 +0000363 seq = Seq(*([bTrue, bFalse] * 25))
364 self.assertEqual(filter(lambda x: not x, seq), [bFalse]*25)
365 self.assertEqual(filter(lambda x: not x, iter(seq)), [bFalse]*25)
Tim Peters0e57abf2001-05-02 07:39:38 +0000366
Tim Petersc3074532001-05-03 07:00:32 +0000367 # Test max() and min()'s use of iterators.
368 def test_builtin_max_min(self):
369 self.assertEqual(max(SequenceClass(5)), 4)
370 self.assertEqual(min(SequenceClass(5)), 0)
371 self.assertEqual(max(8, -1), 8)
372 self.assertEqual(min(8, -1), -1)
373
374 d = {"one": 1, "two": 2, "three": 3}
375 self.assertEqual(max(d), "two")
376 self.assertEqual(min(d), "one")
377 self.assertEqual(max(d.itervalues()), 3)
378 self.assertEqual(min(iter(d.itervalues())), 1)
379
Tim Petersc3074532001-05-03 07:00:32 +0000380 f = open(TESTFN, "w")
381 try:
382 f.write("medium line\n")
383 f.write("xtra large line\n")
384 f.write("itty-bitty line\n")
385 finally:
386 f.close()
387 f = open(TESTFN, "r")
388 try:
389 self.assertEqual(min(f), "itty-bitty line\n")
390 f.seek(0, 0)
391 self.assertEqual(max(f), "xtra large line\n")
392 finally:
393 f.close()
394 try:
395 unlink(TESTFN)
396 except OSError:
397 pass
398
Tim Peters4e9afdc2001-05-03 23:54:49 +0000399 # Test map()'s use of iterators.
Senthil Kumarance8e33a2010-01-08 19:04:16 +0000400 def test_builtin_map(self):
Tim Peters4e9afdc2001-05-03 23:54:49 +0000401 self.assertEqual(map(lambda x: x+1, SequenceClass(5)), range(1, 6))
402
403 d = {"one": 1, "two": 2, "three": 3}
Tim Peters4e9afdc2001-05-03 23:54:49 +0000404 self.assertEqual(map(lambda k, d=d: (k, d[k]), d), d.items())
405 dkeys = d.keys()
406 expected = [(i < len(d) and dkeys[i] or None,
407 i,
408 i < len(d) and dkeys[i] or None)
409 for i in range(5)]
Florent Xicluna07627882010-03-21 01:14:24 +0000410
411 # Deprecated map(None, ...)
412 with check_py3k_warnings():
413 self.assertEqual(map(None, SequenceClass(5)), range(5))
414 self.assertEqual(map(None, d), d.keys())
415 self.assertEqual(map(None, d,
416 SequenceClass(5),
417 iter(d.iterkeys())),
418 expected)
Tim Peters4e9afdc2001-05-03 23:54:49 +0000419
420 f = open(TESTFN, "w")
421 try:
422 for i in range(10):
423 f.write("xy" * i + "\n") # line i has len 2*i+1
424 finally:
425 f.close()
426 f = open(TESTFN, "r")
427 try:
428 self.assertEqual(map(len, f), range(1, 21, 2))
Tim Peters4e9afdc2001-05-03 23:54:49 +0000429 finally:
430 f.close()
431 try:
432 unlink(TESTFN)
433 except OSError:
434 pass
435
Tim Peters8572b4f2001-05-06 01:05:02 +0000436 # Test zip()'s use of iterators.
437 def test_builtin_zip(self):
Raymond Hettingereaef6152003-08-02 07:42:57 +0000438 self.assertEqual(zip(), [])
439 self.assertEqual(zip(*[]), [])
440 self.assertEqual(zip(*[(1, 2), 'ab']), [(1, 'a'), (2, 'b')])
441
Tim Peters8572b4f2001-05-06 01:05:02 +0000442 self.assertRaises(TypeError, zip, None)
443 self.assertRaises(TypeError, zip, range(10), 42)
444 self.assertRaises(TypeError, zip, range(10), zip)
445
446 self.assertEqual(zip(IteratingSequenceClass(3)),
447 [(0,), (1,), (2,)])
448 self.assertEqual(zip(SequenceClass(3)),
449 [(0,), (1,), (2,)])
450
451 d = {"one": 1, "two": 2, "three": 3}
452 self.assertEqual(d.items(), zip(d, d.itervalues()))
453
454 # Generate all ints starting at constructor arg.
455 class IntsFrom:
456 def __init__(self, start):
457 self.i = start
458
459 def __iter__(self):
460 return self
461
462 def next(self):
463 i = self.i
464 self.i = i+1
465 return i
466
467 f = open(TESTFN, "w")
468 try:
469 f.write("a\n" "bbb\n" "cc\n")
470 finally:
471 f.close()
472 f = open(TESTFN, "r")
473 try:
474 self.assertEqual(zip(IntsFrom(0), f, IntsFrom(-100)),
475 [(0, "a\n", -100),
476 (1, "bbb\n", -99),
477 (2, "cc\n", -98)])
478 finally:
479 f.close()
480 try:
481 unlink(TESTFN)
482 except OSError:
483 pass
484
Tim Peters67d687a2002-04-29 21:27:32 +0000485 self.assertEqual(zip(xrange(5)), [(i,) for i in range(5)])
486
487 # Classes that lie about their lengths.
488 class NoGuessLen5:
489 def __getitem__(self, i):
490 if i >= 5:
491 raise IndexError
492 return i
493
494 class Guess3Len5(NoGuessLen5):
495 def __len__(self):
496 return 3
497
498 class Guess30Len5(NoGuessLen5):
499 def __len__(self):
500 return 30
501
502 self.assertEqual(len(Guess3Len5()), 3)
503 self.assertEqual(len(Guess30Len5()), 30)
504 self.assertEqual(zip(NoGuessLen5()), zip(range(5)))
505 self.assertEqual(zip(Guess3Len5()), zip(range(5)))
506 self.assertEqual(zip(Guess30Len5()), zip(range(5)))
507
508 expected = [(i, i) for i in range(5)]
509 for x in NoGuessLen5(), Guess3Len5(), Guess30Len5():
510 for y in NoGuessLen5(), Guess3Len5(), Guess30Len5():
511 self.assertEqual(zip(x, y), expected)
512
Tim Peters15d81ef2001-05-04 04:39:21 +0000513 # Test reduces()'s use of iterators.
Florent Xicluna07627882010-03-21 01:14:24 +0000514 def test_deprecated_builtin_reduce(self):
515 with check_py3k_warnings():
516 self._test_builtin_reduce()
517
518 def _test_builtin_reduce(self):
Tim Peters15d81ef2001-05-04 04:39:21 +0000519 from operator import add
520 self.assertEqual(reduce(add, SequenceClass(5)), 10)
521 self.assertEqual(reduce(add, SequenceClass(5), 42), 52)
522 self.assertRaises(TypeError, reduce, add, SequenceClass(0))
523 self.assertEqual(reduce(add, SequenceClass(0), 42), 42)
524 self.assertEqual(reduce(add, SequenceClass(1)), 0)
525 self.assertEqual(reduce(add, SequenceClass(1), 42), 42)
526
527 d = {"one": 1, "two": 2, "three": 3}
528 self.assertEqual(reduce(add, d), "".join(d.keys()))
529
Zachary Ware1f702212013-12-10 14:09:20 -0600530 @unittest.skipUnless(have_unicode, 'needs unicode support')
Tim Peters2cfe3682001-05-05 05:36:48 +0000531 def test_unicode_join_endcase(self):
532
533 # This class inserts a Unicode object into its argument's natural
534 # iteration, in the 3rd position.
535 class OhPhooey:
536 def __init__(self, seq):
537 self.it = iter(seq)
538 self.i = 0
539
540 def __iter__(self):
541 return self
542
543 def next(self):
544 i = self.i
545 self.i = i+1
546 if i == 2:
Martin v. Löwis339d0f72001-08-17 18:39:25 +0000547 return unicode("fooled you!")
Tim Peters2cfe3682001-05-05 05:36:48 +0000548 return self.it.next()
549
550 f = open(TESTFN, "w")
551 try:
552 f.write("a\n" + "b\n" + "c\n")
553 finally:
554 f.close()
555
556 f = open(TESTFN, "r")
557 # Nasty: string.join(s) can't know whether unicode.join() is needed
558 # until it's seen all of s's elements. But in this case, f's
559 # iterator cannot be restarted. So what we're testing here is
560 # whether string.join() can manage to remember everything it's seen
561 # and pass that on to unicode.join().
562 try:
563 got = " - ".join(OhPhooey(f))
Martin v. Löwis339d0f72001-08-17 18:39:25 +0000564 self.assertEqual(got, unicode("a\n - b\n - fooled you! - c\n"))
Tim Peters2cfe3682001-05-05 05:36:48 +0000565 finally:
566 f.close()
567 try:
568 unlink(TESTFN)
569 except OSError:
570 pass
571
Tim Petersde9725f2001-05-05 10:06:17 +0000572 # Test iterators with 'x in y' and 'x not in y'.
573 def test_in_and_not_in(self):
Tim Peterscb8d3682001-05-05 21:05:01 +0000574 for sc5 in IteratingSequenceClass(5), SequenceClass(5):
575 for i in range(5):
Ezio Melottiaa980582010-01-23 23:04:36 +0000576 self.assertIn(i, sc5)
Tim Peterscb8d3682001-05-05 21:05:01 +0000577 for i in "abc", -1, 5, 42.42, (3, 4), [], {1: 1}, 3-12j, sc5:
Ezio Melottiaa980582010-01-23 23:04:36 +0000578 self.assertNotIn(i, sc5)
Tim Petersde9725f2001-05-05 10:06:17 +0000579
580 self.assertRaises(TypeError, lambda: 3 in 12)
581 self.assertRaises(TypeError, lambda: 3 not in map)
582
583 d = {"one": 1, "two": 2, "three": 3, 1j: 2j}
584 for k in d:
Ezio Melottiaa980582010-01-23 23:04:36 +0000585 self.assertIn(k, d)
586 self.assertNotIn(k, d.itervalues())
Tim Petersde9725f2001-05-05 10:06:17 +0000587 for v in d.values():
Ezio Melottiaa980582010-01-23 23:04:36 +0000588 self.assertIn(v, d.itervalues())
589 self.assertNotIn(v, d)
Tim Petersde9725f2001-05-05 10:06:17 +0000590 for k, v in d.iteritems():
Ezio Melottiaa980582010-01-23 23:04:36 +0000591 self.assertIn((k, v), d.iteritems())
592 self.assertNotIn((v, k), d.iteritems())
Tim Petersde9725f2001-05-05 10:06:17 +0000593
594 f = open(TESTFN, "w")
595 try:
596 f.write("a\n" "b\n" "c\n")
597 finally:
598 f.close()
599 f = open(TESTFN, "r")
600 try:
601 for chunk in "abc":
602 f.seek(0, 0)
Ezio Melottiaa980582010-01-23 23:04:36 +0000603 self.assertNotIn(chunk, f)
Tim Petersde9725f2001-05-05 10:06:17 +0000604 f.seek(0, 0)
Ezio Melottiaa980582010-01-23 23:04:36 +0000605 self.assertIn((chunk + "\n"), f)
Tim Petersde9725f2001-05-05 10:06:17 +0000606 finally:
607 f.close()
608 try:
609 unlink(TESTFN)
610 except OSError:
611 pass
612
Tim Peters75f8e352001-05-05 11:33:43 +0000613 # Test iterators with operator.countOf (PySequence_Count).
614 def test_countOf(self):
615 from operator import countOf
616 self.assertEqual(countOf([1,2,2,3,2,5], 2), 3)
617 self.assertEqual(countOf((1,2,2,3,2,5), 2), 3)
618 self.assertEqual(countOf("122325", "2"), 3)
619 self.assertEqual(countOf("122325", "6"), 0)
620
621 self.assertRaises(TypeError, countOf, 42, 1)
622 self.assertRaises(TypeError, countOf, countOf, countOf)
623
624 d = {"one": 3, "two": 3, "three": 3, 1j: 2j}
625 for k in d:
626 self.assertEqual(countOf(d, k), 1)
627 self.assertEqual(countOf(d.itervalues(), 3), 3)
628 self.assertEqual(countOf(d.itervalues(), 2j), 1)
629 self.assertEqual(countOf(d.itervalues(), 1j), 0)
630
631 f = open(TESTFN, "w")
632 try:
633 f.write("a\n" "b\n" "c\n" "b\n")
634 finally:
635 f.close()
636 f = open(TESTFN, "r")
637 try:
638 for letter, count in ("a", 1), ("b", 2), ("c", 1), ("d", 0):
639 f.seek(0, 0)
640 self.assertEqual(countOf(f, letter + "\n"), count)
641 finally:
642 f.close()
643 try:
644 unlink(TESTFN)
645 except OSError:
646 pass
647
Tim Peters16a77ad2001-09-08 04:00:12 +0000648 # Test iterators with operator.indexOf (PySequence_Index).
649 def test_indexOf(self):
650 from operator import indexOf
651 self.assertEqual(indexOf([1,2,2,3,2,5], 1), 0)
652 self.assertEqual(indexOf((1,2,2,3,2,5), 2), 1)
653 self.assertEqual(indexOf((1,2,2,3,2,5), 3), 3)
654 self.assertEqual(indexOf((1,2,2,3,2,5), 5), 5)
655 self.assertRaises(ValueError, indexOf, (1,2,2,3,2,5), 0)
656 self.assertRaises(ValueError, indexOf, (1,2,2,3,2,5), 6)
657
658 self.assertEqual(indexOf("122325", "2"), 1)
659 self.assertEqual(indexOf("122325", "5"), 5)
660 self.assertRaises(ValueError, indexOf, "122325", "6")
661
662 self.assertRaises(TypeError, indexOf, 42, 1)
663 self.assertRaises(TypeError, indexOf, indexOf, indexOf)
664
665 f = open(TESTFN, "w")
666 try:
667 f.write("a\n" "b\n" "c\n" "d\n" "e\n")
668 finally:
669 f.close()
670 f = open(TESTFN, "r")
671 try:
672 fiter = iter(f)
673 self.assertEqual(indexOf(fiter, "b\n"), 1)
674 self.assertEqual(indexOf(fiter, "d\n"), 1)
675 self.assertEqual(indexOf(fiter, "e\n"), 0)
676 self.assertRaises(ValueError, indexOf, fiter, "a\n")
677 finally:
678 f.close()
679 try:
680 unlink(TESTFN)
681 except OSError:
682 pass
683
684 iclass = IteratingSequenceClass(3)
685 for i in range(3):
686 self.assertEqual(indexOf(iclass, i), i)
687 self.assertRaises(ValueError, indexOf, iclass, -1)
688
Tim Peters2c9aa5e2001-09-23 04:06:05 +0000689 # Test iterators with file.writelines().
690 def test_writelines(self):
691 f = file(TESTFN, "w")
692
693 try:
694 self.assertRaises(TypeError, f.writelines, None)
695 self.assertRaises(TypeError, f.writelines, 42)
Tim Peters527e64f2001-10-04 05:36:56 +0000696
Tim Peters2c9aa5e2001-09-23 04:06:05 +0000697 f.writelines(["1\n", "2\n"])
698 f.writelines(("3\n", "4\n"))
699 f.writelines({'5\n': None})
700 f.writelines({})
701
702 # Try a big chunk too.
703 class Iterator:
704 def __init__(self, start, finish):
705 self.start = start
706 self.finish = finish
707 self.i = self.start
708
709 def next(self):
710 if self.i >= self.finish:
711 raise StopIteration
712 result = str(self.i) + '\n'
713 self.i += 1
714 return result
715
716 def __iter__(self):
717 return self
718
719 class Whatever:
720 def __init__(self, start, finish):
721 self.start = start
722 self.finish = finish
723
724 def __iter__(self):
725 return Iterator(self.start, self.finish)
Tim Peters527e64f2001-10-04 05:36:56 +0000726
727 f.writelines(Whatever(6, 6+2000))
Tim Peters2c9aa5e2001-09-23 04:06:05 +0000728 f.close()
729
730 f = file(TESTFN)
731 expected = [str(i) + "\n" for i in range(1, 2006)]
732 self.assertEqual(list(f), expected)
Tim Peters527e64f2001-10-04 05:36:56 +0000733
Tim Peters2c9aa5e2001-09-23 04:06:05 +0000734 finally:
735 f.close()
736 try:
737 unlink(TESTFN)
738 except OSError:
739 pass
740
741
Tim Petersd6d010b2001-06-21 02:49:55 +0000742 # Test iterators on RHS of unpacking assignments.
743 def test_unpack_iter(self):
744 a, b = 1, 2
745 self.assertEqual((a, b), (1, 2))
746
747 a, b, c = IteratingSequenceClass(3)
748 self.assertEqual((a, b, c), (0, 1, 2))
749
750 try: # too many values
751 a, b = IteratingSequenceClass(3)
752 except ValueError:
753 pass
754 else:
755 self.fail("should have raised ValueError")
756
757 try: # not enough values
758 a, b, c = IteratingSequenceClass(2)
759 except ValueError:
760 pass
761 else:
762 self.fail("should have raised ValueError")
763
764 try: # not iterable
765 a, b, c = len
766 except TypeError:
767 pass
768 else:
769 self.fail("should have raised TypeError")
770
771 a, b, c = {1: 42, 2: 42, 3: 42}.itervalues()
772 self.assertEqual((a, b, c), (42, 42, 42))
773
774 f = open(TESTFN, "w")
775 lines = ("a\n", "bb\n", "ccc\n")
776 try:
777 for line in lines:
778 f.write(line)
779 finally:
780 f.close()
781 f = open(TESTFN, "r")
782 try:
783 a, b, c = f
784 self.assertEqual((a, b, c), lines)
785 finally:
786 f.close()
787 try:
788 unlink(TESTFN)
789 except OSError:
790 pass
791
792 (a, b), (c,) = IteratingSequenceClass(2), {42: 24}
793 self.assertEqual((a, b, c), (0, 1, 42))
794
Guido van Rossumbb8f59a2001-12-03 19:33:25 +0000795
Benjamin Peterson7f8ede42010-06-22 20:32:02 +0000796 @cpython_only
797 def test_ref_counting_behavior(self):
Guido van Rossumbb8f59a2001-12-03 19:33:25 +0000798 class C(object):
799 count = 0
800 def __new__(cls):
801 cls.count += 1
802 return object.__new__(cls)
803 def __del__(self):
804 cls = self.__class__
805 assert cls.count > 0
806 cls.count -= 1
807 x = C()
808 self.assertEqual(C.count, 1)
809 del x
810 self.assertEqual(C.count, 0)
811 l = [C(), C(), C()]
812 self.assertEqual(C.count, 3)
813 try:
814 a, b = iter(l)
815 except ValueError:
816 pass
817 del l
818 self.assertEqual(C.count, 0)
Fred Drake2e2be372001-09-20 21:33:42 +0000819
Guido van Rossum674eae62002-07-16 21:48:11 +0000820
821 # Make sure StopIteration is a "sink state".
822 # This tests various things that weren't sink states in Python 2.2.1,
823 # plus various things that always were fine.
824
825 def test_sinkstate_list(self):
826 # This used to fail
827 a = range(5)
828 b = iter(a)
829 self.assertEqual(list(b), range(5))
830 a.extend(range(5, 10))
831 self.assertEqual(list(b), [])
832
833 def test_sinkstate_tuple(self):
834 a = (0, 1, 2, 3, 4)
835 b = iter(a)
836 self.assertEqual(list(b), range(5))
837 self.assertEqual(list(b), [])
838
839 def test_sinkstate_string(self):
840 a = "abcde"
841 b = iter(a)
842 self.assertEqual(list(b), ['a', 'b', 'c', 'd', 'e'])
843 self.assertEqual(list(b), [])
844
845 def test_sinkstate_sequence(self):
846 # This used to fail
847 a = SequenceClass(5)
848 b = iter(a)
849 self.assertEqual(list(b), range(5))
850 a.n = 10
851 self.assertEqual(list(b), [])
852
853 def test_sinkstate_callable(self):
854 # This used to fail
855 def spam(state=[0]):
856 i = state[0]
857 state[0] = i+1
858 if i == 10:
859 raise AssertionError, "shouldn't have gotten this far"
860 return i
861 b = iter(spam, 5)
862 self.assertEqual(list(b), range(5))
863 self.assertEqual(list(b), [])
864
865 def test_sinkstate_dict(self):
866 # XXX For a more thorough test, see towards the end of:
867 # http://mail.python.org/pipermail/python-dev/2002-July/026512.html
868 a = {1:1, 2:2, 0:0, 4:4, 3:3}
869 for b in iter(a), a.iterkeys(), a.iteritems(), a.itervalues():
870 b = iter(a)
871 self.assertEqual(len(list(b)), 5)
872 self.assertEqual(list(b), [])
873
874 def test_sinkstate_yield(self):
875 def gen():
876 for i in range(5):
877 yield i
878 b = gen()
879 self.assertEqual(list(b), range(5))
880 self.assertEqual(list(b), [])
881
882 def test_sinkstate_range(self):
883 a = xrange(5)
884 b = iter(a)
885 self.assertEqual(list(b), range(5))
886 self.assertEqual(list(b), [])
887
888 def test_sinkstate_enumerate(self):
889 a = range(5)
890 e = enumerate(a)
891 b = iter(e)
892 self.assertEqual(list(b), zip(range(5), range(5)))
893 self.assertEqual(list(b), [])
894
Amaury Forgeot d'Arca40d5732009-01-12 23:36:55 +0000895 def test_3720(self):
896 # Avoid a crash, when an iterator deletes its next() method.
897 class BadIterator(object):
898 def __iter__(self):
899 return self
900 def next(self):
901 del BadIterator.next
902 return 1
903
904 try:
905 for i in BadIterator() :
906 pass
907 except TypeError:
908 pass
909
Ezio Melotti64514972012-11-18 23:14:42 +0200910 def test_extending_list_with_iterator_does_not_segfault(self):
911 # The code to extend a list with an iterator has a fair
912 # amount of nontrivial logic in terms of guessing how
913 # much memory to allocate in advance, "stealing" refs,
914 # and then shrinking at the end. This is a basic smoke
915 # test for that scenario.
916 def gen():
917 for i in range(500):
918 yield i
919 lst = [0] * 500
920 for i in range(240):
921 lst.pop(0)
922 lst.extend(gen())
923 self.assertEqual(len(lst), 760)
924
Serhiy Storchaka14a7d632016-03-30 20:43:06 +0300925 def test_free_after_iterating(self):
926 check_free_after_iterating(self, iter, SequenceClass, (0,))
927
Guido van Rossum674eae62002-07-16 21:48:11 +0000928
Fred Drake2e2be372001-09-20 21:33:42 +0000929def test_main():
930 run_unittest(TestCase)
931
932
933if __name__ == "__main__":
934 test_main()