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