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