blob: 6132041fcdc55e228b853fca3043ad1c7affefee [file] [log] [blame]
Guido van Rossum8b48cf92001-04-21 13:33:54 +00001# Test iterators.
2
3import unittest
Ezio Melottia65e2af2010-08-02 19:56:05 +00004from test.test_support import run_unittest, TESTFN, unlink, have_unicode, \
5 _check_py3k_warnings
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)
79 self.assert_(it is it2)
80
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
124 # Test two-argument iter() with callable instance
125 def test_iter_callable(self):
126 class C:
127 def __init__(self):
128 self.i = 0
129 def __call__(self):
130 i = self.i
131 self.i = i + 1
132 if i > 100:
133 raise IndexError # Emergency stop
134 return i
135 self.check_iterator(iter(C(), 10), range(10))
136
137 # Test two-argument iter() with function
138 def test_iter_function(self):
139 def spam(state=[0]):
140 i = state[0]
141 state[0] = i+1
142 return i
143 self.check_iterator(iter(spam, 10), range(10))
144
145 # Test two-argument iter() with function that raises StopIteration
146 def test_iter_function_stop(self):
147 def spam(state=[0]):
148 i = state[0]
149 if i == 10:
150 raise StopIteration
151 state[0] = i+1
152 return i
153 self.check_iterator(iter(spam, 20), range(10))
154
155 # Test exception propagation through function iterator
156 def test_exception_function(self):
157 def spam(state=[0]):
158 i = state[0]
159 state[0] = i+1
160 if i == 10:
161 raise RuntimeError
162 return i
163 res = []
164 try:
165 for x in iter(spam, 20):
166 res.append(x)
167 except RuntimeError:
168 self.assertEqual(res, range(10))
169 else:
170 self.fail("should have raised RuntimeError")
171
172 # Test exception propagation through sequence iterator
173 def test_exception_sequence(self):
174 class MySequenceClass(SequenceClass):
175 def __getitem__(self, i):
176 if i == 10:
177 raise RuntimeError
178 return SequenceClass.__getitem__(self, i)
179 res = []
180 try:
181 for x in MySequenceClass(20):
182 res.append(x)
183 except RuntimeError:
184 self.assertEqual(res, range(10))
185 else:
186 self.fail("should have raised RuntimeError")
187
188 # Test for StopIteration from __getitem__
189 def test_stop_sequence(self):
190 class MySequenceClass(SequenceClass):
191 def __getitem__(self, i):
192 if i == 10:
193 raise StopIteration
194 return SequenceClass.__getitem__(self, i)
195 self.check_for_loop(MySequenceClass(20), range(10))
196
197 # Test a big range
198 def test_iter_big_range(self):
199 self.check_for_loop(iter(range(10000)), range(10000))
200
201 # Test an empty list
202 def test_iter_empty(self):
203 self.check_for_loop(iter([]), [])
204
205 # Test a tuple
206 def test_iter_tuple(self):
207 self.check_for_loop(iter((0,1,2,3,4,5,6,7,8,9)), range(10))
208
209 # Test an xrange
210 def test_iter_xrange(self):
211 self.check_for_loop(iter(xrange(10)), range(10))
212
213 # Test a string
214 def test_iter_string(self):
215 self.check_for_loop(iter("abcde"), ["a", "b", "c", "d", "e"])
216
217 # Test a Unicode string
Martin v. Löwis339d0f72001-08-17 18:39:25 +0000218 if have_unicode:
219 def test_iter_unicode(self):
220 self.check_for_loop(iter(unicode("abcde")),
221 [unicode("a"), unicode("b"), unicode("c"),
222 unicode("d"), unicode("e")])
Guido van Rossum8b48cf92001-04-21 13:33:54 +0000223
224 # Test a directory
225 def test_iter_dict(self):
226 dict = {}
227 for i in range(10):
228 dict[i] = None
229 self.check_for_loop(dict, dict.keys())
230
231 # Test a file
232 def test_iter_file(self):
233 f = open(TESTFN, "w")
234 try:
235 for i in range(5):
236 f.write("%d\n" % i)
237 finally:
238 f.close()
239 f = open(TESTFN, "r")
240 try:
241 self.check_for_loop(f, ["0\n", "1\n", "2\n", "3\n", "4\n"])
242 self.check_for_loop(f, [])
243 finally:
244 f.close()
245 try:
246 unlink(TESTFN)
247 except OSError:
248 pass
249
Tim Petersf553f892001-05-01 20:45:31 +0000250 # Test list()'s use of iterators.
251 def test_builtin_list(self):
252 self.assertEqual(list(SequenceClass(5)), range(5))
253 self.assertEqual(list(SequenceClass(0)), [])
254 self.assertEqual(list(()), [])
255 self.assertEqual(list(range(10, -1, -1)), range(10, -1, -1))
256
257 d = {"one": 1, "two": 2, "three": 3}
258 self.assertEqual(list(d), d.keys())
259
260 self.assertRaises(TypeError, list, list)
261 self.assertRaises(TypeError, list, 42)
262
263 f = open(TESTFN, "w")
264 try:
265 for i in range(5):
266 f.write("%d\n" % i)
267 finally:
268 f.close()
269 f = open(TESTFN, "r")
270 try:
271 self.assertEqual(list(f), ["0\n", "1\n", "2\n", "3\n", "4\n"])
272 f.seek(0, 0)
Guido van Rossum8ee52432002-08-06 17:14:04 +0000273 self.assertEqual(list(f),
Tim Petersf553f892001-05-01 20:45:31 +0000274 ["0\n", "1\n", "2\n", "3\n", "4\n"])
275 finally:
276 f.close()
277 try:
278 unlink(TESTFN)
279 except OSError:
280 pass
281
Tim Peters6912d4d2001-05-05 03:56:37 +0000282 # Test tuples()'s use of iterators.
283 def test_builtin_tuple(self):
284 self.assertEqual(tuple(SequenceClass(5)), (0, 1, 2, 3, 4))
285 self.assertEqual(tuple(SequenceClass(0)), ())
286 self.assertEqual(tuple([]), ())
287 self.assertEqual(tuple(()), ())
288 self.assertEqual(tuple("abc"), ("a", "b", "c"))
289
290 d = {"one": 1, "two": 2, "three": 3}
291 self.assertEqual(tuple(d), tuple(d.keys()))
292
293 self.assertRaises(TypeError, tuple, list)
294 self.assertRaises(TypeError, tuple, 42)
295
296 f = open(TESTFN, "w")
297 try:
298 for i in range(5):
299 f.write("%d\n" % i)
300 finally:
301 f.close()
302 f = open(TESTFN, "r")
303 try:
304 self.assertEqual(tuple(f), ("0\n", "1\n", "2\n", "3\n", "4\n"))
305 f.seek(0, 0)
Guido van Rossum8ee52432002-08-06 17:14:04 +0000306 self.assertEqual(tuple(f),
Tim Peters6912d4d2001-05-05 03:56:37 +0000307 ("0\n", "1\n", "2\n", "3\n", "4\n"))
308 finally:
309 f.close()
310 try:
311 unlink(TESTFN)
312 except OSError:
313 pass
314
Tim Peters0e57abf2001-05-02 07:39:38 +0000315 # Test filter()'s use of iterators.
316 def test_builtin_filter(self):
317 self.assertEqual(filter(None, SequenceClass(5)), range(1, 5))
318 self.assertEqual(filter(None, SequenceClass(0)), [])
319 self.assertEqual(filter(None, ()), ())
320 self.assertEqual(filter(None, "abc"), "abc")
321
322 d = {"one": 1, "two": 2, "three": 3}
323 self.assertEqual(filter(None, d), d.keys())
324
325 self.assertRaises(TypeError, filter, None, list)
326 self.assertRaises(TypeError, filter, None, 42)
327
328 class Boolean:
329 def __init__(self, truth):
330 self.truth = truth
331 def __nonzero__(self):
332 return self.truth
Tim Peterscae330e2002-12-23 16:50:58 +0000333 bTrue = Boolean(1)
334 bFalse = Boolean(0)
Tim Peters0e57abf2001-05-02 07:39:38 +0000335
336 class Seq:
337 def __init__(self, *args):
338 self.vals = args
339 def __iter__(self):
340 class SeqIter:
341 def __init__(self, vals):
342 self.vals = vals
343 self.i = 0
344 def __iter__(self):
345 return self
346 def next(self):
347 i = self.i
348 self.i = i + 1
349 if i < len(self.vals):
350 return self.vals[i]
351 else:
352 raise StopIteration
353 return SeqIter(self.vals)
354
Tim Peterscae330e2002-12-23 16:50:58 +0000355 seq = Seq(*([bTrue, bFalse] * 25))
356 self.assertEqual(filter(lambda x: not x, seq), [bFalse]*25)
357 self.assertEqual(filter(lambda x: not x, iter(seq)), [bFalse]*25)
Tim Peters0e57abf2001-05-02 07:39:38 +0000358
Tim Petersc3074532001-05-03 07:00:32 +0000359 # Test max() and min()'s use of iterators.
360 def test_builtin_max_min(self):
361 self.assertEqual(max(SequenceClass(5)), 4)
362 self.assertEqual(min(SequenceClass(5)), 0)
363 self.assertEqual(max(8, -1), 8)
364 self.assertEqual(min(8, -1), -1)
365
366 d = {"one": 1, "two": 2, "three": 3}
367 self.assertEqual(max(d), "two")
368 self.assertEqual(min(d), "one")
369 self.assertEqual(max(d.itervalues()), 3)
370 self.assertEqual(min(iter(d.itervalues())), 1)
371
Tim Petersc3074532001-05-03 07:00:32 +0000372 f = open(TESTFN, "w")
373 try:
374 f.write("medium line\n")
375 f.write("xtra large line\n")
376 f.write("itty-bitty line\n")
377 finally:
378 f.close()
379 f = open(TESTFN, "r")
380 try:
381 self.assertEqual(min(f), "itty-bitty line\n")
382 f.seek(0, 0)
383 self.assertEqual(max(f), "xtra large line\n")
384 finally:
385 f.close()
386 try:
387 unlink(TESTFN)
388 except OSError:
389 pass
390
Tim Peters4e9afdc2001-05-03 23:54:49 +0000391 # Test map()'s use of iterators.
392 def test_builtin_map(self):
Tim Peters4e9afdc2001-05-03 23:54:49 +0000393 self.assertEqual(map(lambda x: x+1, SequenceClass(5)), range(1, 6))
394
395 d = {"one": 1, "two": 2, "three": 3}
Tim Peters4e9afdc2001-05-03 23:54:49 +0000396 self.assertEqual(map(lambda k, d=d: (k, d[k]), d), d.items())
397 dkeys = d.keys()
398 expected = [(i < len(d) and dkeys[i] or None,
399 i,
400 i < len(d) and dkeys[i] or None)
401 for i in range(5)]
Ezio Melottia65e2af2010-08-02 19:56:05 +0000402
403 # Deprecated map(None, ...)
404 with _check_py3k_warnings():
405 self.assertEqual(map(None, SequenceClass(5)), range(5))
406 self.assertEqual(map(None, d), d.keys())
407 self.assertEqual(map(None, d,
408 SequenceClass(5),
409 iter(d.iterkeys())),
410 expected)
Tim Peters4e9afdc2001-05-03 23:54:49 +0000411
412 f = open(TESTFN, "w")
413 try:
414 for i in range(10):
415 f.write("xy" * i + "\n") # line i has len 2*i+1
416 finally:
417 f.close()
418 f = open(TESTFN, "r")
419 try:
420 self.assertEqual(map(len, f), range(1, 21, 2))
Tim Peters4e9afdc2001-05-03 23:54:49 +0000421 finally:
422 f.close()
423 try:
424 unlink(TESTFN)
425 except OSError:
426 pass
427
Tim Peters8572b4f2001-05-06 01:05:02 +0000428 # Test zip()'s use of iterators.
429 def test_builtin_zip(self):
Raymond Hettingereaef6152003-08-02 07:42:57 +0000430 self.assertEqual(zip(), [])
431 self.assertEqual(zip(*[]), [])
432 self.assertEqual(zip(*[(1, 2), 'ab']), [(1, 'a'), (2, 'b')])
433
Tim Peters8572b4f2001-05-06 01:05:02 +0000434 self.assertRaises(TypeError, zip, None)
435 self.assertRaises(TypeError, zip, range(10), 42)
436 self.assertRaises(TypeError, zip, range(10), zip)
437
438 self.assertEqual(zip(IteratingSequenceClass(3)),
439 [(0,), (1,), (2,)])
440 self.assertEqual(zip(SequenceClass(3)),
441 [(0,), (1,), (2,)])
442
443 d = {"one": 1, "two": 2, "three": 3}
444 self.assertEqual(d.items(), zip(d, d.itervalues()))
445
446 # Generate all ints starting at constructor arg.
447 class IntsFrom:
448 def __init__(self, start):
449 self.i = start
450
451 def __iter__(self):
452 return self
453
454 def next(self):
455 i = self.i
456 self.i = i+1
457 return i
458
459 f = open(TESTFN, "w")
460 try:
461 f.write("a\n" "bbb\n" "cc\n")
462 finally:
463 f.close()
464 f = open(TESTFN, "r")
465 try:
466 self.assertEqual(zip(IntsFrom(0), f, IntsFrom(-100)),
467 [(0, "a\n", -100),
468 (1, "bbb\n", -99),
469 (2, "cc\n", -98)])
470 finally:
471 f.close()
472 try:
473 unlink(TESTFN)
474 except OSError:
475 pass
476
Tim Peters67d687a2002-04-29 21:27:32 +0000477 self.assertEqual(zip(xrange(5)), [(i,) for i in range(5)])
478
479 # Classes that lie about their lengths.
480 class NoGuessLen5:
481 def __getitem__(self, i):
482 if i >= 5:
483 raise IndexError
484 return i
485
486 class Guess3Len5(NoGuessLen5):
487 def __len__(self):
488 return 3
489
490 class Guess30Len5(NoGuessLen5):
491 def __len__(self):
492 return 30
493
494 self.assertEqual(len(Guess3Len5()), 3)
495 self.assertEqual(len(Guess30Len5()), 30)
496 self.assertEqual(zip(NoGuessLen5()), zip(range(5)))
497 self.assertEqual(zip(Guess3Len5()), zip(range(5)))
498 self.assertEqual(zip(Guess30Len5()), zip(range(5)))
499
500 expected = [(i, i) for i in range(5)]
501 for x in NoGuessLen5(), Guess3Len5(), Guess30Len5():
502 for y in NoGuessLen5(), Guess3Len5(), Guess30Len5():
503 self.assertEqual(zip(x, y), expected)
504
Tim Peters15d81ef2001-05-04 04:39:21 +0000505 # Test reduces()'s use of iterators.
Ezio Melottia65e2af2010-08-02 19:56:05 +0000506 def test_deprecated_builtin_reduce(self):
507 with _check_py3k_warnings():
508 self._test_builtin_reduce()
509
510 def _test_builtin_reduce(self):
Tim Peters15d81ef2001-05-04 04:39:21 +0000511 from operator import add
512 self.assertEqual(reduce(add, SequenceClass(5)), 10)
513 self.assertEqual(reduce(add, SequenceClass(5), 42), 52)
514 self.assertRaises(TypeError, reduce, add, SequenceClass(0))
515 self.assertEqual(reduce(add, SequenceClass(0), 42), 42)
516 self.assertEqual(reduce(add, SequenceClass(1)), 0)
517 self.assertEqual(reduce(add, SequenceClass(1), 42), 42)
518
519 d = {"one": 1, "two": 2, "three": 3}
520 self.assertEqual(reduce(add, d), "".join(d.keys()))
521
Martin v. Löwis339d0f72001-08-17 18:39:25 +0000522 # This test case will be removed if we don't have Unicode
Tim Peters2cfe3682001-05-05 05:36:48 +0000523 def test_unicode_join_endcase(self):
524
525 # This class inserts a Unicode object into its argument's natural
526 # iteration, in the 3rd position.
527 class OhPhooey:
528 def __init__(self, seq):
529 self.it = iter(seq)
530 self.i = 0
531
532 def __iter__(self):
533 return self
534
535 def next(self):
536 i = self.i
537 self.i = i+1
538 if i == 2:
Martin v. Löwis339d0f72001-08-17 18:39:25 +0000539 return unicode("fooled you!")
Tim Peters2cfe3682001-05-05 05:36:48 +0000540 return self.it.next()
541
542 f = open(TESTFN, "w")
543 try:
544 f.write("a\n" + "b\n" + "c\n")
545 finally:
546 f.close()
547
548 f = open(TESTFN, "r")
549 # Nasty: string.join(s) can't know whether unicode.join() is needed
550 # until it's seen all of s's elements. But in this case, f's
551 # iterator cannot be restarted. So what we're testing here is
552 # whether string.join() can manage to remember everything it's seen
553 # and pass that on to unicode.join().
554 try:
555 got = " - ".join(OhPhooey(f))
Martin v. Löwis339d0f72001-08-17 18:39:25 +0000556 self.assertEqual(got, unicode("a\n - b\n - fooled you! - c\n"))
Tim Peters2cfe3682001-05-05 05:36:48 +0000557 finally:
558 f.close()
559 try:
560 unlink(TESTFN)
561 except OSError:
562 pass
Martin v. Löwis339d0f72001-08-17 18:39:25 +0000563 if not have_unicode:
564 def test_unicode_join_endcase(self): pass
Tim Peters2cfe3682001-05-05 05:36:48 +0000565
Tim Petersde9725f2001-05-05 10:06:17 +0000566 # Test iterators with 'x in y' and 'x not in y'.
567 def test_in_and_not_in(self):
Tim Peterscb8d3682001-05-05 21:05:01 +0000568 for sc5 in IteratingSequenceClass(5), SequenceClass(5):
569 for i in range(5):
570 self.assert_(i in sc5)
571 for i in "abc", -1, 5, 42.42, (3, 4), [], {1: 1}, 3-12j, sc5:
572 self.assert_(i not in sc5)
Tim Petersde9725f2001-05-05 10:06:17 +0000573
574 self.assertRaises(TypeError, lambda: 3 in 12)
575 self.assertRaises(TypeError, lambda: 3 not in map)
576
577 d = {"one": 1, "two": 2, "three": 3, 1j: 2j}
578 for k in d:
579 self.assert_(k in d)
580 self.assert_(k not in d.itervalues())
581 for v in d.values():
582 self.assert_(v in d.itervalues())
583 self.assert_(v not in d)
584 for k, v in d.iteritems():
585 self.assert_((k, v) in d.iteritems())
586 self.assert_((v, k) not in d.iteritems())
Tim Petersde9725f2001-05-05 10:06:17 +0000587
588 f = open(TESTFN, "w")
589 try:
590 f.write("a\n" "b\n" "c\n")
591 finally:
592 f.close()
593 f = open(TESTFN, "r")
594 try:
595 for chunk in "abc":
596 f.seek(0, 0)
597 self.assert_(chunk not in f)
598 f.seek(0, 0)
599 self.assert_((chunk + "\n") in f)
600 finally:
601 f.close()
602 try:
603 unlink(TESTFN)
604 except OSError:
605 pass
606
Tim Peters75f8e352001-05-05 11:33:43 +0000607 # Test iterators with operator.countOf (PySequence_Count).
608 def test_countOf(self):
609 from operator import countOf
610 self.assertEqual(countOf([1,2,2,3,2,5], 2), 3)
611 self.assertEqual(countOf((1,2,2,3,2,5), 2), 3)
612 self.assertEqual(countOf("122325", "2"), 3)
613 self.assertEqual(countOf("122325", "6"), 0)
614
615 self.assertRaises(TypeError, countOf, 42, 1)
616 self.assertRaises(TypeError, countOf, countOf, countOf)
617
618 d = {"one": 3, "two": 3, "three": 3, 1j: 2j}
619 for k in d:
620 self.assertEqual(countOf(d, k), 1)
621 self.assertEqual(countOf(d.itervalues(), 3), 3)
622 self.assertEqual(countOf(d.itervalues(), 2j), 1)
623 self.assertEqual(countOf(d.itervalues(), 1j), 0)
624
625 f = open(TESTFN, "w")
626 try:
627 f.write("a\n" "b\n" "c\n" "b\n")
628 finally:
629 f.close()
630 f = open(TESTFN, "r")
631 try:
632 for letter, count in ("a", 1), ("b", 2), ("c", 1), ("d", 0):
633 f.seek(0, 0)
634 self.assertEqual(countOf(f, letter + "\n"), count)
635 finally:
636 f.close()
637 try:
638 unlink(TESTFN)
639 except OSError:
640 pass
641
Tim Peters16a77ad2001-09-08 04:00:12 +0000642 # Test iterators with operator.indexOf (PySequence_Index).
643 def test_indexOf(self):
644 from operator import indexOf
645 self.assertEqual(indexOf([1,2,2,3,2,5], 1), 0)
646 self.assertEqual(indexOf((1,2,2,3,2,5), 2), 1)
647 self.assertEqual(indexOf((1,2,2,3,2,5), 3), 3)
648 self.assertEqual(indexOf((1,2,2,3,2,5), 5), 5)
649 self.assertRaises(ValueError, indexOf, (1,2,2,3,2,5), 0)
650 self.assertRaises(ValueError, indexOf, (1,2,2,3,2,5), 6)
651
652 self.assertEqual(indexOf("122325", "2"), 1)
653 self.assertEqual(indexOf("122325", "5"), 5)
654 self.assertRaises(ValueError, indexOf, "122325", "6")
655
656 self.assertRaises(TypeError, indexOf, 42, 1)
657 self.assertRaises(TypeError, indexOf, indexOf, indexOf)
658
659 f = open(TESTFN, "w")
660 try:
661 f.write("a\n" "b\n" "c\n" "d\n" "e\n")
662 finally:
663 f.close()
664 f = open(TESTFN, "r")
665 try:
666 fiter = iter(f)
667 self.assertEqual(indexOf(fiter, "b\n"), 1)
668 self.assertEqual(indexOf(fiter, "d\n"), 1)
669 self.assertEqual(indexOf(fiter, "e\n"), 0)
670 self.assertRaises(ValueError, indexOf, fiter, "a\n")
671 finally:
672 f.close()
673 try:
674 unlink(TESTFN)
675 except OSError:
676 pass
677
678 iclass = IteratingSequenceClass(3)
679 for i in range(3):
680 self.assertEqual(indexOf(iclass, i), i)
681 self.assertRaises(ValueError, indexOf, iclass, -1)
682
Tim Peters2c9aa5e2001-09-23 04:06:05 +0000683 # Test iterators with file.writelines().
684 def test_writelines(self):
685 f = file(TESTFN, "w")
686
687 try:
688 self.assertRaises(TypeError, f.writelines, None)
689 self.assertRaises(TypeError, f.writelines, 42)
Tim Peters527e64f2001-10-04 05:36:56 +0000690
Tim Peters2c9aa5e2001-09-23 04:06:05 +0000691 f.writelines(["1\n", "2\n"])
692 f.writelines(("3\n", "4\n"))
693 f.writelines({'5\n': None})
694 f.writelines({})
695
696 # Try a big chunk too.
697 class Iterator:
698 def __init__(self, start, finish):
699 self.start = start
700 self.finish = finish
701 self.i = self.start
702
703 def next(self):
704 if self.i >= self.finish:
705 raise StopIteration
706 result = str(self.i) + '\n'
707 self.i += 1
708 return result
709
710 def __iter__(self):
711 return self
712
713 class Whatever:
714 def __init__(self, start, finish):
715 self.start = start
716 self.finish = finish
717
718 def __iter__(self):
719 return Iterator(self.start, self.finish)
Tim Peters527e64f2001-10-04 05:36:56 +0000720
721 f.writelines(Whatever(6, 6+2000))
Tim Peters2c9aa5e2001-09-23 04:06:05 +0000722 f.close()
723
724 f = file(TESTFN)
725 expected = [str(i) + "\n" for i in range(1, 2006)]
726 self.assertEqual(list(f), expected)
Tim Peters527e64f2001-10-04 05:36:56 +0000727
Tim Peters2c9aa5e2001-09-23 04:06:05 +0000728 finally:
729 f.close()
730 try:
731 unlink(TESTFN)
732 except OSError:
733 pass
734
735
Tim Petersd6d010b2001-06-21 02:49:55 +0000736 # Test iterators on RHS of unpacking assignments.
737 def test_unpack_iter(self):
738 a, b = 1, 2
739 self.assertEqual((a, b), (1, 2))
740
741 a, b, c = IteratingSequenceClass(3)
742 self.assertEqual((a, b, c), (0, 1, 2))
743
744 try: # too many values
745 a, b = IteratingSequenceClass(3)
746 except ValueError:
747 pass
748 else:
749 self.fail("should have raised ValueError")
750
751 try: # not enough values
752 a, b, c = IteratingSequenceClass(2)
753 except ValueError:
754 pass
755 else:
756 self.fail("should have raised ValueError")
757
758 try: # not iterable
759 a, b, c = len
760 except TypeError:
761 pass
762 else:
763 self.fail("should have raised TypeError")
764
765 a, b, c = {1: 42, 2: 42, 3: 42}.itervalues()
766 self.assertEqual((a, b, c), (42, 42, 42))
767
768 f = open(TESTFN, "w")
769 lines = ("a\n", "bb\n", "ccc\n")
770 try:
771 for line in lines:
772 f.write(line)
773 finally:
774 f.close()
775 f = open(TESTFN, "r")
776 try:
777 a, b, c = f
778 self.assertEqual((a, b, c), lines)
779 finally:
780 f.close()
781 try:
782 unlink(TESTFN)
783 except OSError:
784 pass
785
786 (a, b), (c,) = IteratingSequenceClass(2), {42: 24}
787 self.assertEqual((a, b, c), (0, 1, 42))
788
Guido van Rossumbb8f59a2001-12-03 19:33:25 +0000789 # Test reference count behavior
790
791 class C(object):
792 count = 0
793 def __new__(cls):
794 cls.count += 1
795 return object.__new__(cls)
796 def __del__(self):
797 cls = self.__class__
798 assert cls.count > 0
799 cls.count -= 1
800 x = C()
801 self.assertEqual(C.count, 1)
802 del x
803 self.assertEqual(C.count, 0)
804 l = [C(), C(), C()]
805 self.assertEqual(C.count, 3)
806 try:
807 a, b = iter(l)
808 except ValueError:
809 pass
810 del l
811 self.assertEqual(C.count, 0)
Fred Drake2e2be372001-09-20 21:33:42 +0000812
Guido van Rossum674eae62002-07-16 21:48:11 +0000813
814 # Make sure StopIteration is a "sink state".
815 # This tests various things that weren't sink states in Python 2.2.1,
816 # plus various things that always were fine.
817
818 def test_sinkstate_list(self):
819 # This used to fail
820 a = range(5)
821 b = iter(a)
822 self.assertEqual(list(b), range(5))
823 a.extend(range(5, 10))
824 self.assertEqual(list(b), [])
825
826 def test_sinkstate_tuple(self):
827 a = (0, 1, 2, 3, 4)
828 b = iter(a)
829 self.assertEqual(list(b), range(5))
830 self.assertEqual(list(b), [])
831
832 def test_sinkstate_string(self):
833 a = "abcde"
834 b = iter(a)
835 self.assertEqual(list(b), ['a', 'b', 'c', 'd', 'e'])
836 self.assertEqual(list(b), [])
837
838 def test_sinkstate_sequence(self):
839 # This used to fail
840 a = SequenceClass(5)
841 b = iter(a)
842 self.assertEqual(list(b), range(5))
843 a.n = 10
844 self.assertEqual(list(b), [])
845
846 def test_sinkstate_callable(self):
847 # This used to fail
848 def spam(state=[0]):
849 i = state[0]
850 state[0] = i+1
851 if i == 10:
852 raise AssertionError, "shouldn't have gotten this far"
853 return i
854 b = iter(spam, 5)
855 self.assertEqual(list(b), range(5))
856 self.assertEqual(list(b), [])
857
858 def test_sinkstate_dict(self):
859 # XXX For a more thorough test, see towards the end of:
860 # http://mail.python.org/pipermail/python-dev/2002-July/026512.html
861 a = {1:1, 2:2, 0:0, 4:4, 3:3}
862 for b in iter(a), a.iterkeys(), a.iteritems(), a.itervalues():
863 b = iter(a)
864 self.assertEqual(len(list(b)), 5)
865 self.assertEqual(list(b), [])
866
867 def test_sinkstate_yield(self):
868 def gen():
869 for i in range(5):
870 yield i
871 b = gen()
872 self.assertEqual(list(b), range(5))
873 self.assertEqual(list(b), [])
874
875 def test_sinkstate_range(self):
876 a = xrange(5)
877 b = iter(a)
878 self.assertEqual(list(b), range(5))
879 self.assertEqual(list(b), [])
880
881 def test_sinkstate_enumerate(self):
882 a = range(5)
883 e = enumerate(a)
884 b = iter(e)
885 self.assertEqual(list(b), zip(range(5), range(5)))
886 self.assertEqual(list(b), [])
887
888
Fred Drake2e2be372001-09-20 21:33:42 +0000889def test_main():
890 run_unittest(TestCase)
891
892
893if __name__ == "__main__":
894 test_main()