blob: cc20865df18317f94ef8b116f475822478bbcb82 [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
Serhiy Storchaka0ed38912016-03-30 21:02:00 +0300125 def test_mutating_seq_class_exhausted_iter(self):
126 a = SequenceClass(5)
127 exhit = iter(a)
128 empit = iter(a)
129 for x in exhit: # exhaust the iterator
130 next(empit) # not exhausted
131 a.n = 7
132 self.assertEqual(list(exhit), [])
133 self.assertEqual(list(empit), [5, 6])
134 self.assertEqual(list(a), [0, 1, 2, 3, 4, 5, 6])
135
Amaury Forgeot d'Arca40d5732009-01-12 23:36:55 +0000136 # Test a new_style class with __iter__ but no next() method
137 def test_new_style_iter_class(self):
138 class IterClass(object):
139 def __iter__(self):
140 return self
141 self.assertRaises(TypeError, iter, IterClass())
142
Guido van Rossum8b48cf92001-04-21 13:33:54 +0000143 # Test two-argument iter() with callable instance
144 def test_iter_callable(self):
145 class C:
146 def __init__(self):
147 self.i = 0
148 def __call__(self):
149 i = self.i
150 self.i = i + 1
151 if i > 100:
152 raise IndexError # Emergency stop
153 return i
154 self.check_iterator(iter(C(), 10), range(10))
155
156 # Test two-argument iter() with function
157 def test_iter_function(self):
158 def spam(state=[0]):
159 i = state[0]
160 state[0] = i+1
161 return i
162 self.check_iterator(iter(spam, 10), range(10))
163
164 # Test two-argument iter() with function that raises StopIteration
165 def test_iter_function_stop(self):
166 def spam(state=[0]):
167 i = state[0]
168 if i == 10:
169 raise StopIteration
170 state[0] = i+1
171 return i
172 self.check_iterator(iter(spam, 20), range(10))
173
174 # Test exception propagation through function iterator
175 def test_exception_function(self):
176 def spam(state=[0]):
177 i = state[0]
178 state[0] = i+1
179 if i == 10:
180 raise RuntimeError
181 return i
182 res = []
183 try:
184 for x in iter(spam, 20):
185 res.append(x)
186 except RuntimeError:
187 self.assertEqual(res, range(10))
188 else:
189 self.fail("should have raised RuntimeError")
190
191 # Test exception propagation through sequence iterator
192 def test_exception_sequence(self):
193 class MySequenceClass(SequenceClass):
194 def __getitem__(self, i):
195 if i == 10:
196 raise RuntimeError
197 return SequenceClass.__getitem__(self, i)
198 res = []
199 try:
200 for x in MySequenceClass(20):
201 res.append(x)
202 except RuntimeError:
203 self.assertEqual(res, range(10))
204 else:
205 self.fail("should have raised RuntimeError")
206
207 # Test for StopIteration from __getitem__
208 def test_stop_sequence(self):
209 class MySequenceClass(SequenceClass):
210 def __getitem__(self, i):
211 if i == 10:
212 raise StopIteration
213 return SequenceClass.__getitem__(self, i)
214 self.check_for_loop(MySequenceClass(20), range(10))
215
216 # Test a big range
217 def test_iter_big_range(self):
218 self.check_for_loop(iter(range(10000)), range(10000))
219
220 # Test an empty list
221 def test_iter_empty(self):
222 self.check_for_loop(iter([]), [])
223
224 # Test a tuple
225 def test_iter_tuple(self):
226 self.check_for_loop(iter((0,1,2,3,4,5,6,7,8,9)), range(10))
227
228 # Test an xrange
229 def test_iter_xrange(self):
230 self.check_for_loop(iter(xrange(10)), range(10))
231
232 # Test a string
233 def test_iter_string(self):
234 self.check_for_loop(iter("abcde"), ["a", "b", "c", "d", "e"])
235
236 # Test a Unicode string
Martin v. Löwis339d0f72001-08-17 18:39:25 +0000237 if have_unicode:
238 def test_iter_unicode(self):
239 self.check_for_loop(iter(unicode("abcde")),
240 [unicode("a"), unicode("b"), unicode("c"),
241 unicode("d"), unicode("e")])
Guido van Rossum8b48cf92001-04-21 13:33:54 +0000242
243 # Test a directory
244 def test_iter_dict(self):
245 dict = {}
246 for i in range(10):
247 dict[i] = None
248 self.check_for_loop(dict, dict.keys())
249
250 # Test a file
251 def test_iter_file(self):
252 f = open(TESTFN, "w")
253 try:
254 for i in range(5):
255 f.write("%d\n" % i)
256 finally:
257 f.close()
258 f = open(TESTFN, "r")
259 try:
260 self.check_for_loop(f, ["0\n", "1\n", "2\n", "3\n", "4\n"])
261 self.check_for_loop(f, [])
262 finally:
263 f.close()
264 try:
265 unlink(TESTFN)
266 except OSError:
267 pass
268
Tim Petersf553f892001-05-01 20:45:31 +0000269 # Test list()'s use of iterators.
270 def test_builtin_list(self):
271 self.assertEqual(list(SequenceClass(5)), range(5))
272 self.assertEqual(list(SequenceClass(0)), [])
273 self.assertEqual(list(()), [])
274 self.assertEqual(list(range(10, -1, -1)), range(10, -1, -1))
275
276 d = {"one": 1, "two": 2, "three": 3}
277 self.assertEqual(list(d), d.keys())
278
279 self.assertRaises(TypeError, list, list)
280 self.assertRaises(TypeError, list, 42)
281
282 f = open(TESTFN, "w")
283 try:
284 for i in range(5):
285 f.write("%d\n" % i)
286 finally:
287 f.close()
288 f = open(TESTFN, "r")
289 try:
290 self.assertEqual(list(f), ["0\n", "1\n", "2\n", "3\n", "4\n"])
291 f.seek(0, 0)
Guido van Rossum8ee52432002-08-06 17:14:04 +0000292 self.assertEqual(list(f),
Tim Petersf553f892001-05-01 20:45:31 +0000293 ["0\n", "1\n", "2\n", "3\n", "4\n"])
294 finally:
295 f.close()
296 try:
297 unlink(TESTFN)
298 except OSError:
299 pass
300
Tim Peters6912d4d2001-05-05 03:56:37 +0000301 # Test tuples()'s use of iterators.
302 def test_builtin_tuple(self):
303 self.assertEqual(tuple(SequenceClass(5)), (0, 1, 2, 3, 4))
304 self.assertEqual(tuple(SequenceClass(0)), ())
305 self.assertEqual(tuple([]), ())
306 self.assertEqual(tuple(()), ())
307 self.assertEqual(tuple("abc"), ("a", "b", "c"))
308
309 d = {"one": 1, "two": 2, "three": 3}
310 self.assertEqual(tuple(d), tuple(d.keys()))
311
312 self.assertRaises(TypeError, tuple, list)
313 self.assertRaises(TypeError, tuple, 42)
314
315 f = open(TESTFN, "w")
316 try:
317 for i in range(5):
318 f.write("%d\n" % i)
319 finally:
320 f.close()
321 f = open(TESTFN, "r")
322 try:
323 self.assertEqual(tuple(f), ("0\n", "1\n", "2\n", "3\n", "4\n"))
324 f.seek(0, 0)
Guido van Rossum8ee52432002-08-06 17:14:04 +0000325 self.assertEqual(tuple(f),
Tim Peters6912d4d2001-05-05 03:56:37 +0000326 ("0\n", "1\n", "2\n", "3\n", "4\n"))
327 finally:
328 f.close()
329 try:
330 unlink(TESTFN)
331 except OSError:
332 pass
333
Tim Peters0e57abf2001-05-02 07:39:38 +0000334 # Test filter()'s use of iterators.
335 def test_builtin_filter(self):
336 self.assertEqual(filter(None, SequenceClass(5)), range(1, 5))
337 self.assertEqual(filter(None, SequenceClass(0)), [])
338 self.assertEqual(filter(None, ()), ())
339 self.assertEqual(filter(None, "abc"), "abc")
340
341 d = {"one": 1, "two": 2, "three": 3}
342 self.assertEqual(filter(None, d), d.keys())
343
344 self.assertRaises(TypeError, filter, None, list)
345 self.assertRaises(TypeError, filter, None, 42)
346
347 class Boolean:
348 def __init__(self, truth):
349 self.truth = truth
350 def __nonzero__(self):
351 return self.truth
Tim Peterscae330e2002-12-23 16:50:58 +0000352 bTrue = Boolean(1)
353 bFalse = Boolean(0)
Tim Peters0e57abf2001-05-02 07:39:38 +0000354
355 class Seq:
356 def __init__(self, *args):
357 self.vals = args
358 def __iter__(self):
359 class SeqIter:
360 def __init__(self, vals):
361 self.vals = vals
362 self.i = 0
363 def __iter__(self):
364 return self
365 def next(self):
366 i = self.i
367 self.i = i + 1
368 if i < len(self.vals):
369 return self.vals[i]
370 else:
371 raise StopIteration
372 return SeqIter(self.vals)
373
Tim Peterscae330e2002-12-23 16:50:58 +0000374 seq = Seq(*([bTrue, bFalse] * 25))
375 self.assertEqual(filter(lambda x: not x, seq), [bFalse]*25)
376 self.assertEqual(filter(lambda x: not x, iter(seq)), [bFalse]*25)
Tim Peters0e57abf2001-05-02 07:39:38 +0000377
Tim Petersc3074532001-05-03 07:00:32 +0000378 # Test max() and min()'s use of iterators.
379 def test_builtin_max_min(self):
380 self.assertEqual(max(SequenceClass(5)), 4)
381 self.assertEqual(min(SequenceClass(5)), 0)
382 self.assertEqual(max(8, -1), 8)
383 self.assertEqual(min(8, -1), -1)
384
385 d = {"one": 1, "two": 2, "three": 3}
386 self.assertEqual(max(d), "two")
387 self.assertEqual(min(d), "one")
388 self.assertEqual(max(d.itervalues()), 3)
389 self.assertEqual(min(iter(d.itervalues())), 1)
390
Tim Petersc3074532001-05-03 07:00:32 +0000391 f = open(TESTFN, "w")
392 try:
393 f.write("medium line\n")
394 f.write("xtra large line\n")
395 f.write("itty-bitty line\n")
396 finally:
397 f.close()
398 f = open(TESTFN, "r")
399 try:
400 self.assertEqual(min(f), "itty-bitty line\n")
401 f.seek(0, 0)
402 self.assertEqual(max(f), "xtra large line\n")
403 finally:
404 f.close()
405 try:
406 unlink(TESTFN)
407 except OSError:
408 pass
409
Tim Peters4e9afdc2001-05-03 23:54:49 +0000410 # Test map()'s use of iterators.
Senthil Kumarance8e33a2010-01-08 19:04:16 +0000411 def test_builtin_map(self):
Tim Peters4e9afdc2001-05-03 23:54:49 +0000412 self.assertEqual(map(lambda x: x+1, SequenceClass(5)), range(1, 6))
413
414 d = {"one": 1, "two": 2, "three": 3}
Tim Peters4e9afdc2001-05-03 23:54:49 +0000415 self.assertEqual(map(lambda k, d=d: (k, d[k]), d), d.items())
416 dkeys = d.keys()
417 expected = [(i < len(d) and dkeys[i] or None,
418 i,
419 i < len(d) and dkeys[i] or None)
420 for i in range(5)]
Florent Xicluna07627882010-03-21 01:14:24 +0000421
422 # Deprecated map(None, ...)
423 with check_py3k_warnings():
424 self.assertEqual(map(None, SequenceClass(5)), range(5))
425 self.assertEqual(map(None, d), d.keys())
426 self.assertEqual(map(None, d,
427 SequenceClass(5),
428 iter(d.iterkeys())),
429 expected)
Tim Peters4e9afdc2001-05-03 23:54:49 +0000430
431 f = open(TESTFN, "w")
432 try:
433 for i in range(10):
434 f.write("xy" * i + "\n") # line i has len 2*i+1
435 finally:
436 f.close()
437 f = open(TESTFN, "r")
438 try:
439 self.assertEqual(map(len, f), range(1, 21, 2))
Tim Peters4e9afdc2001-05-03 23:54:49 +0000440 finally:
441 f.close()
442 try:
443 unlink(TESTFN)
444 except OSError:
445 pass
446
Tim Peters8572b4f2001-05-06 01:05:02 +0000447 # Test zip()'s use of iterators.
448 def test_builtin_zip(self):
Raymond Hettingereaef6152003-08-02 07:42:57 +0000449 self.assertEqual(zip(), [])
450 self.assertEqual(zip(*[]), [])
451 self.assertEqual(zip(*[(1, 2), 'ab']), [(1, 'a'), (2, 'b')])
452
Tim Peters8572b4f2001-05-06 01:05:02 +0000453 self.assertRaises(TypeError, zip, None)
454 self.assertRaises(TypeError, zip, range(10), 42)
455 self.assertRaises(TypeError, zip, range(10), zip)
456
457 self.assertEqual(zip(IteratingSequenceClass(3)),
458 [(0,), (1,), (2,)])
459 self.assertEqual(zip(SequenceClass(3)),
460 [(0,), (1,), (2,)])
461
462 d = {"one": 1, "two": 2, "three": 3}
463 self.assertEqual(d.items(), zip(d, d.itervalues()))
464
465 # Generate all ints starting at constructor arg.
466 class IntsFrom:
467 def __init__(self, start):
468 self.i = start
469
470 def __iter__(self):
471 return self
472
473 def next(self):
474 i = self.i
475 self.i = i+1
476 return i
477
478 f = open(TESTFN, "w")
479 try:
480 f.write("a\n" "bbb\n" "cc\n")
481 finally:
482 f.close()
483 f = open(TESTFN, "r")
484 try:
485 self.assertEqual(zip(IntsFrom(0), f, IntsFrom(-100)),
486 [(0, "a\n", -100),
487 (1, "bbb\n", -99),
488 (2, "cc\n", -98)])
489 finally:
490 f.close()
491 try:
492 unlink(TESTFN)
493 except OSError:
494 pass
495
Tim Peters67d687a2002-04-29 21:27:32 +0000496 self.assertEqual(zip(xrange(5)), [(i,) for i in range(5)])
497
498 # Classes that lie about their lengths.
499 class NoGuessLen5:
500 def __getitem__(self, i):
501 if i >= 5:
502 raise IndexError
503 return i
504
505 class Guess3Len5(NoGuessLen5):
506 def __len__(self):
507 return 3
508
509 class Guess30Len5(NoGuessLen5):
510 def __len__(self):
511 return 30
512
513 self.assertEqual(len(Guess3Len5()), 3)
514 self.assertEqual(len(Guess30Len5()), 30)
515 self.assertEqual(zip(NoGuessLen5()), zip(range(5)))
516 self.assertEqual(zip(Guess3Len5()), zip(range(5)))
517 self.assertEqual(zip(Guess30Len5()), zip(range(5)))
518
519 expected = [(i, i) for i in range(5)]
520 for x in NoGuessLen5(), Guess3Len5(), Guess30Len5():
521 for y in NoGuessLen5(), Guess3Len5(), Guess30Len5():
522 self.assertEqual(zip(x, y), expected)
523
Tim Peters15d81ef2001-05-04 04:39:21 +0000524 # Test reduces()'s use of iterators.
Florent Xicluna07627882010-03-21 01:14:24 +0000525 def test_deprecated_builtin_reduce(self):
526 with check_py3k_warnings():
527 self._test_builtin_reduce()
528
529 def _test_builtin_reduce(self):
Tim Peters15d81ef2001-05-04 04:39:21 +0000530 from operator import add
531 self.assertEqual(reduce(add, SequenceClass(5)), 10)
532 self.assertEqual(reduce(add, SequenceClass(5), 42), 52)
533 self.assertRaises(TypeError, reduce, add, SequenceClass(0))
534 self.assertEqual(reduce(add, SequenceClass(0), 42), 42)
535 self.assertEqual(reduce(add, SequenceClass(1)), 0)
536 self.assertEqual(reduce(add, SequenceClass(1), 42), 42)
537
538 d = {"one": 1, "two": 2, "three": 3}
539 self.assertEqual(reduce(add, d), "".join(d.keys()))
540
Zachary Ware1f702212013-12-10 14:09:20 -0600541 @unittest.skipUnless(have_unicode, 'needs unicode support')
Tim Peters2cfe3682001-05-05 05:36:48 +0000542 def test_unicode_join_endcase(self):
543
544 # This class inserts a Unicode object into its argument's natural
545 # iteration, in the 3rd position.
546 class OhPhooey:
547 def __init__(self, seq):
548 self.it = iter(seq)
549 self.i = 0
550
551 def __iter__(self):
552 return self
553
554 def next(self):
555 i = self.i
556 self.i = i+1
557 if i == 2:
Martin v. Löwis339d0f72001-08-17 18:39:25 +0000558 return unicode("fooled you!")
Tim Peters2cfe3682001-05-05 05:36:48 +0000559 return self.it.next()
560
561 f = open(TESTFN, "w")
562 try:
563 f.write("a\n" + "b\n" + "c\n")
564 finally:
565 f.close()
566
567 f = open(TESTFN, "r")
568 # Nasty: string.join(s) can't know whether unicode.join() is needed
569 # until it's seen all of s's elements. But in this case, f's
570 # iterator cannot be restarted. So what we're testing here is
571 # whether string.join() can manage to remember everything it's seen
572 # and pass that on to unicode.join().
573 try:
574 got = " - ".join(OhPhooey(f))
Martin v. Löwis339d0f72001-08-17 18:39:25 +0000575 self.assertEqual(got, unicode("a\n - b\n - fooled you! - c\n"))
Tim Peters2cfe3682001-05-05 05:36:48 +0000576 finally:
577 f.close()
578 try:
579 unlink(TESTFN)
580 except OSError:
581 pass
582
Tim Petersde9725f2001-05-05 10:06:17 +0000583 # Test iterators with 'x in y' and 'x not in y'.
584 def test_in_and_not_in(self):
Tim Peterscb8d3682001-05-05 21:05:01 +0000585 for sc5 in IteratingSequenceClass(5), SequenceClass(5):
586 for i in range(5):
Ezio Melottiaa980582010-01-23 23:04:36 +0000587 self.assertIn(i, sc5)
Tim Peterscb8d3682001-05-05 21:05:01 +0000588 for i in "abc", -1, 5, 42.42, (3, 4), [], {1: 1}, 3-12j, sc5:
Ezio Melottiaa980582010-01-23 23:04:36 +0000589 self.assertNotIn(i, sc5)
Tim Petersde9725f2001-05-05 10:06:17 +0000590
591 self.assertRaises(TypeError, lambda: 3 in 12)
592 self.assertRaises(TypeError, lambda: 3 not in map)
593
594 d = {"one": 1, "two": 2, "three": 3, 1j: 2j}
595 for k in d:
Ezio Melottiaa980582010-01-23 23:04:36 +0000596 self.assertIn(k, d)
597 self.assertNotIn(k, d.itervalues())
Tim Petersde9725f2001-05-05 10:06:17 +0000598 for v in d.values():
Ezio Melottiaa980582010-01-23 23:04:36 +0000599 self.assertIn(v, d.itervalues())
600 self.assertNotIn(v, d)
Tim Petersde9725f2001-05-05 10:06:17 +0000601 for k, v in d.iteritems():
Ezio Melottiaa980582010-01-23 23:04:36 +0000602 self.assertIn((k, v), d.iteritems())
603 self.assertNotIn((v, k), d.iteritems())
Tim Petersde9725f2001-05-05 10:06:17 +0000604
605 f = open(TESTFN, "w")
606 try:
607 f.write("a\n" "b\n" "c\n")
608 finally:
609 f.close()
610 f = open(TESTFN, "r")
611 try:
612 for chunk in "abc":
613 f.seek(0, 0)
Ezio Melottiaa980582010-01-23 23:04:36 +0000614 self.assertNotIn(chunk, f)
Tim Petersde9725f2001-05-05 10:06:17 +0000615 f.seek(0, 0)
Ezio Melottiaa980582010-01-23 23:04:36 +0000616 self.assertIn((chunk + "\n"), f)
Tim Petersde9725f2001-05-05 10:06:17 +0000617 finally:
618 f.close()
619 try:
620 unlink(TESTFN)
621 except OSError:
622 pass
623
Tim Peters75f8e352001-05-05 11:33:43 +0000624 # Test iterators with operator.countOf (PySequence_Count).
625 def test_countOf(self):
626 from operator import countOf
627 self.assertEqual(countOf([1,2,2,3,2,5], 2), 3)
628 self.assertEqual(countOf((1,2,2,3,2,5), 2), 3)
629 self.assertEqual(countOf("122325", "2"), 3)
630 self.assertEqual(countOf("122325", "6"), 0)
631
632 self.assertRaises(TypeError, countOf, 42, 1)
633 self.assertRaises(TypeError, countOf, countOf, countOf)
634
635 d = {"one": 3, "two": 3, "three": 3, 1j: 2j}
636 for k in d:
637 self.assertEqual(countOf(d, k), 1)
638 self.assertEqual(countOf(d.itervalues(), 3), 3)
639 self.assertEqual(countOf(d.itervalues(), 2j), 1)
640 self.assertEqual(countOf(d.itervalues(), 1j), 0)
641
642 f = open(TESTFN, "w")
643 try:
644 f.write("a\n" "b\n" "c\n" "b\n")
645 finally:
646 f.close()
647 f = open(TESTFN, "r")
648 try:
649 for letter, count in ("a", 1), ("b", 2), ("c", 1), ("d", 0):
650 f.seek(0, 0)
651 self.assertEqual(countOf(f, letter + "\n"), count)
652 finally:
653 f.close()
654 try:
655 unlink(TESTFN)
656 except OSError:
657 pass
658
Tim Peters16a77ad2001-09-08 04:00:12 +0000659 # Test iterators with operator.indexOf (PySequence_Index).
660 def test_indexOf(self):
661 from operator import indexOf
662 self.assertEqual(indexOf([1,2,2,3,2,5], 1), 0)
663 self.assertEqual(indexOf((1,2,2,3,2,5), 2), 1)
664 self.assertEqual(indexOf((1,2,2,3,2,5), 3), 3)
665 self.assertEqual(indexOf((1,2,2,3,2,5), 5), 5)
666 self.assertRaises(ValueError, indexOf, (1,2,2,3,2,5), 0)
667 self.assertRaises(ValueError, indexOf, (1,2,2,3,2,5), 6)
668
669 self.assertEqual(indexOf("122325", "2"), 1)
670 self.assertEqual(indexOf("122325", "5"), 5)
671 self.assertRaises(ValueError, indexOf, "122325", "6")
672
673 self.assertRaises(TypeError, indexOf, 42, 1)
674 self.assertRaises(TypeError, indexOf, indexOf, indexOf)
675
676 f = open(TESTFN, "w")
677 try:
678 f.write("a\n" "b\n" "c\n" "d\n" "e\n")
679 finally:
680 f.close()
681 f = open(TESTFN, "r")
682 try:
683 fiter = iter(f)
684 self.assertEqual(indexOf(fiter, "b\n"), 1)
685 self.assertEqual(indexOf(fiter, "d\n"), 1)
686 self.assertEqual(indexOf(fiter, "e\n"), 0)
687 self.assertRaises(ValueError, indexOf, fiter, "a\n")
688 finally:
689 f.close()
690 try:
691 unlink(TESTFN)
692 except OSError:
693 pass
694
695 iclass = IteratingSequenceClass(3)
696 for i in range(3):
697 self.assertEqual(indexOf(iclass, i), i)
698 self.assertRaises(ValueError, indexOf, iclass, -1)
699
Tim Peters2c9aa5e2001-09-23 04:06:05 +0000700 # Test iterators with file.writelines().
701 def test_writelines(self):
702 f = file(TESTFN, "w")
703
704 try:
705 self.assertRaises(TypeError, f.writelines, None)
706 self.assertRaises(TypeError, f.writelines, 42)
Tim Peters527e64f2001-10-04 05:36:56 +0000707
Tim Peters2c9aa5e2001-09-23 04:06:05 +0000708 f.writelines(["1\n", "2\n"])
709 f.writelines(("3\n", "4\n"))
710 f.writelines({'5\n': None})
711 f.writelines({})
712
713 # Try a big chunk too.
714 class Iterator:
715 def __init__(self, start, finish):
716 self.start = start
717 self.finish = finish
718 self.i = self.start
719
720 def next(self):
721 if self.i >= self.finish:
722 raise StopIteration
723 result = str(self.i) + '\n'
724 self.i += 1
725 return result
726
727 def __iter__(self):
728 return self
729
730 class Whatever:
731 def __init__(self, start, finish):
732 self.start = start
733 self.finish = finish
734
735 def __iter__(self):
736 return Iterator(self.start, self.finish)
Tim Peters527e64f2001-10-04 05:36:56 +0000737
738 f.writelines(Whatever(6, 6+2000))
Tim Peters2c9aa5e2001-09-23 04:06:05 +0000739 f.close()
740
741 f = file(TESTFN)
742 expected = [str(i) + "\n" for i in range(1, 2006)]
743 self.assertEqual(list(f), expected)
Tim Peters527e64f2001-10-04 05:36:56 +0000744
Tim Peters2c9aa5e2001-09-23 04:06:05 +0000745 finally:
746 f.close()
747 try:
748 unlink(TESTFN)
749 except OSError:
750 pass
751
752
Tim Petersd6d010b2001-06-21 02:49:55 +0000753 # Test iterators on RHS of unpacking assignments.
754 def test_unpack_iter(self):
755 a, b = 1, 2
756 self.assertEqual((a, b), (1, 2))
757
758 a, b, c = IteratingSequenceClass(3)
759 self.assertEqual((a, b, c), (0, 1, 2))
760
761 try: # too many values
762 a, b = IteratingSequenceClass(3)
763 except ValueError:
764 pass
765 else:
766 self.fail("should have raised ValueError")
767
768 try: # not enough values
769 a, b, c = IteratingSequenceClass(2)
770 except ValueError:
771 pass
772 else:
773 self.fail("should have raised ValueError")
774
775 try: # not iterable
776 a, b, c = len
777 except TypeError:
778 pass
779 else:
780 self.fail("should have raised TypeError")
781
782 a, b, c = {1: 42, 2: 42, 3: 42}.itervalues()
783 self.assertEqual((a, b, c), (42, 42, 42))
784
785 f = open(TESTFN, "w")
786 lines = ("a\n", "bb\n", "ccc\n")
787 try:
788 for line in lines:
789 f.write(line)
790 finally:
791 f.close()
792 f = open(TESTFN, "r")
793 try:
794 a, b, c = f
795 self.assertEqual((a, b, c), lines)
796 finally:
797 f.close()
798 try:
799 unlink(TESTFN)
800 except OSError:
801 pass
802
803 (a, b), (c,) = IteratingSequenceClass(2), {42: 24}
804 self.assertEqual((a, b, c), (0, 1, 42))
805
Guido van Rossumbb8f59a2001-12-03 19:33:25 +0000806
Benjamin Peterson7f8ede42010-06-22 20:32:02 +0000807 @cpython_only
808 def test_ref_counting_behavior(self):
Guido van Rossumbb8f59a2001-12-03 19:33:25 +0000809 class C(object):
810 count = 0
811 def __new__(cls):
812 cls.count += 1
813 return object.__new__(cls)
814 def __del__(self):
815 cls = self.__class__
816 assert cls.count > 0
817 cls.count -= 1
818 x = C()
819 self.assertEqual(C.count, 1)
820 del x
821 self.assertEqual(C.count, 0)
822 l = [C(), C(), C()]
823 self.assertEqual(C.count, 3)
824 try:
825 a, b = iter(l)
826 except ValueError:
827 pass
828 del l
829 self.assertEqual(C.count, 0)
Fred Drake2e2be372001-09-20 21:33:42 +0000830
Guido van Rossum674eae62002-07-16 21:48:11 +0000831
832 # Make sure StopIteration is a "sink state".
833 # This tests various things that weren't sink states in Python 2.2.1,
834 # plus various things that always were fine.
835
836 def test_sinkstate_list(self):
837 # This used to fail
838 a = range(5)
839 b = iter(a)
840 self.assertEqual(list(b), range(5))
841 a.extend(range(5, 10))
842 self.assertEqual(list(b), [])
843
844 def test_sinkstate_tuple(self):
845 a = (0, 1, 2, 3, 4)
846 b = iter(a)
847 self.assertEqual(list(b), range(5))
848 self.assertEqual(list(b), [])
849
850 def test_sinkstate_string(self):
851 a = "abcde"
852 b = iter(a)
853 self.assertEqual(list(b), ['a', 'b', 'c', 'd', 'e'])
854 self.assertEqual(list(b), [])
855
856 def test_sinkstate_sequence(self):
857 # This used to fail
858 a = SequenceClass(5)
859 b = iter(a)
860 self.assertEqual(list(b), range(5))
861 a.n = 10
862 self.assertEqual(list(b), [])
863
864 def test_sinkstate_callable(self):
865 # This used to fail
866 def spam(state=[0]):
867 i = state[0]
868 state[0] = i+1
869 if i == 10:
870 raise AssertionError, "shouldn't have gotten this far"
871 return i
872 b = iter(spam, 5)
873 self.assertEqual(list(b), range(5))
874 self.assertEqual(list(b), [])
875
876 def test_sinkstate_dict(self):
877 # XXX For a more thorough test, see towards the end of:
878 # http://mail.python.org/pipermail/python-dev/2002-July/026512.html
879 a = {1:1, 2:2, 0:0, 4:4, 3:3}
880 for b in iter(a), a.iterkeys(), a.iteritems(), a.itervalues():
881 b = iter(a)
882 self.assertEqual(len(list(b)), 5)
883 self.assertEqual(list(b), [])
884
885 def test_sinkstate_yield(self):
886 def gen():
887 for i in range(5):
888 yield i
889 b = gen()
890 self.assertEqual(list(b), range(5))
891 self.assertEqual(list(b), [])
892
893 def test_sinkstate_range(self):
894 a = xrange(5)
895 b = iter(a)
896 self.assertEqual(list(b), range(5))
897 self.assertEqual(list(b), [])
898
899 def test_sinkstate_enumerate(self):
900 a = range(5)
901 e = enumerate(a)
902 b = iter(e)
903 self.assertEqual(list(b), zip(range(5), range(5)))
904 self.assertEqual(list(b), [])
905
Amaury Forgeot d'Arca40d5732009-01-12 23:36:55 +0000906 def test_3720(self):
907 # Avoid a crash, when an iterator deletes its next() method.
908 class BadIterator(object):
909 def __iter__(self):
910 return self
911 def next(self):
912 del BadIterator.next
913 return 1
914
915 try:
916 for i in BadIterator() :
917 pass
918 except TypeError:
919 pass
920
Ezio Melotti64514972012-11-18 23:14:42 +0200921 def test_extending_list_with_iterator_does_not_segfault(self):
922 # The code to extend a list with an iterator has a fair
923 # amount of nontrivial logic in terms of guessing how
924 # much memory to allocate in advance, "stealing" refs,
925 # and then shrinking at the end. This is a basic smoke
926 # test for that scenario.
927 def gen():
928 for i in range(500):
929 yield i
930 lst = [0] * 500
931 for i in range(240):
932 lst.pop(0)
933 lst.extend(gen())
934 self.assertEqual(len(lst), 760)
935
Serhiy Storchaka14a7d632016-03-30 20:43:06 +0300936 def test_free_after_iterating(self):
937 check_free_after_iterating(self, iter, SequenceClass, (0,))
938
Guido van Rossum674eae62002-07-16 21:48:11 +0000939
Fred Drake2e2be372001-09-20 21:33:42 +0000940def test_main():
941 run_unittest(TestCase)
942
943
944if __name__ == "__main__":
945 test_main()