blob: 5e96c6ddae7eb21950f9b6196123bfb461d65762 [file] [log] [blame]
Guido van Rossum8b48cf92001-04-21 13:33:54 +00001# Test iterators.
2
3import unittest
Senthil Kumaran3ddc4352010-01-08 18:41:40 +00004from test.test_support import run_unittest, TESTFN, unlink, have_unicode, \
5 check_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)
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 Kumaran3ddc4352010-01-08 18:41:40 +0000399 def test_deprecated_builtin_map(self):
400 # Silence Py3k warning
401 with check_warnings():
402 self._test_builtin_map()
403
404 def _test_builtin_map(self):
Tim Peters4e9afdc2001-05-03 23:54:49 +0000405 self.assertEqual(map(None, SequenceClass(5)), range(5))
406 self.assertEqual(map(lambda x: x+1, SequenceClass(5)), range(1, 6))
407
408 d = {"one": 1, "two": 2, "three": 3}
409 self.assertEqual(map(None, d), d.keys())
410 self.assertEqual(map(lambda k, d=d: (k, d[k]), d), d.items())
411 dkeys = d.keys()
412 expected = [(i < len(d) and dkeys[i] or None,
413 i,
414 i < len(d) and dkeys[i] or None)
415 for i in range(5)]
416 self.assertEqual(map(None, d,
417 SequenceClass(5),
418 iter(d.iterkeys())),
Tim Peters8bc10b02001-05-03 23:58:47 +0000419 expected)
Tim Peters4e9afdc2001-05-03 23:54:49 +0000420
421 f = open(TESTFN, "w")
422 try:
423 for i in range(10):
424 f.write("xy" * i + "\n") # line i has len 2*i+1
425 finally:
426 f.close()
427 f = open(TESTFN, "r")
428 try:
429 self.assertEqual(map(len, f), range(1, 21, 2))
Tim Peters4e9afdc2001-05-03 23:54:49 +0000430 finally:
431 f.close()
432 try:
433 unlink(TESTFN)
434 except OSError:
435 pass
436
Tim Peters8572b4f2001-05-06 01:05:02 +0000437 # Test zip()'s use of iterators.
438 def test_builtin_zip(self):
Raymond Hettingereaef6152003-08-02 07:42:57 +0000439 self.assertEqual(zip(), [])
440 self.assertEqual(zip(*[]), [])
441 self.assertEqual(zip(*[(1, 2), 'ab']), [(1, 'a'), (2, 'b')])
442
Tim Peters8572b4f2001-05-06 01:05:02 +0000443 self.assertRaises(TypeError, zip, None)
444 self.assertRaises(TypeError, zip, range(10), 42)
445 self.assertRaises(TypeError, zip, range(10), zip)
446
447 self.assertEqual(zip(IteratingSequenceClass(3)),
448 [(0,), (1,), (2,)])
449 self.assertEqual(zip(SequenceClass(3)),
450 [(0,), (1,), (2,)])
451
452 d = {"one": 1, "two": 2, "three": 3}
453 self.assertEqual(d.items(), zip(d, d.itervalues()))
454
455 # Generate all ints starting at constructor arg.
456 class IntsFrom:
457 def __init__(self, start):
458 self.i = start
459
460 def __iter__(self):
461 return self
462
463 def next(self):
464 i = self.i
465 self.i = i+1
466 return i
467
468 f = open(TESTFN, "w")
469 try:
470 f.write("a\n" "bbb\n" "cc\n")
471 finally:
472 f.close()
473 f = open(TESTFN, "r")
474 try:
475 self.assertEqual(zip(IntsFrom(0), f, IntsFrom(-100)),
476 [(0, "a\n", -100),
477 (1, "bbb\n", -99),
478 (2, "cc\n", -98)])
479 finally:
480 f.close()
481 try:
482 unlink(TESTFN)
483 except OSError:
484 pass
485
Tim Peters67d687a2002-04-29 21:27:32 +0000486 self.assertEqual(zip(xrange(5)), [(i,) for i in range(5)])
487
488 # Classes that lie about their lengths.
489 class NoGuessLen5:
490 def __getitem__(self, i):
491 if i >= 5:
492 raise IndexError
493 return i
494
495 class Guess3Len5(NoGuessLen5):
496 def __len__(self):
497 return 3
498
499 class Guess30Len5(NoGuessLen5):
500 def __len__(self):
501 return 30
502
503 self.assertEqual(len(Guess3Len5()), 3)
504 self.assertEqual(len(Guess30Len5()), 30)
505 self.assertEqual(zip(NoGuessLen5()), zip(range(5)))
506 self.assertEqual(zip(Guess3Len5()), zip(range(5)))
507 self.assertEqual(zip(Guess30Len5()), zip(range(5)))
508
509 expected = [(i, i) for i in range(5)]
510 for x in NoGuessLen5(), Guess3Len5(), Guess30Len5():
511 for y in NoGuessLen5(), Guess3Len5(), Guess30Len5():
512 self.assertEqual(zip(x, y), expected)
513
Tim Peters15d81ef2001-05-04 04:39:21 +0000514 # Test reduces()'s use of iterators.
Senthil Kumaran3ddc4352010-01-08 18:41:40 +0000515 def test_deprecated_builtin_reduce(self):
516 # Silence Py3k warning
517 with check_warnings():
518 self._test_builtin_reduce()
519
520 def _test_builtin_reduce(self):
Tim Peters15d81ef2001-05-04 04:39:21 +0000521 from operator import add
522 self.assertEqual(reduce(add, SequenceClass(5)), 10)
523 self.assertEqual(reduce(add, SequenceClass(5), 42), 52)
524 self.assertRaises(TypeError, reduce, add, SequenceClass(0))
525 self.assertEqual(reduce(add, SequenceClass(0), 42), 42)
526 self.assertEqual(reduce(add, SequenceClass(1)), 0)
527 self.assertEqual(reduce(add, SequenceClass(1), 42), 42)
528
529 d = {"one": 1, "two": 2, "three": 3}
530 self.assertEqual(reduce(add, d), "".join(d.keys()))
531
Martin v. Löwis339d0f72001-08-17 18:39:25 +0000532 # This test case will be removed if we don't have Unicode
Tim Peters2cfe3682001-05-05 05:36:48 +0000533 def test_unicode_join_endcase(self):
534
535 # This class inserts a Unicode object into its argument's natural
536 # iteration, in the 3rd position.
537 class OhPhooey:
538 def __init__(self, seq):
539 self.it = iter(seq)
540 self.i = 0
541
542 def __iter__(self):
543 return self
544
545 def next(self):
546 i = self.i
547 self.i = i+1
548 if i == 2:
Martin v. Löwis339d0f72001-08-17 18:39:25 +0000549 return unicode("fooled you!")
Tim Peters2cfe3682001-05-05 05:36:48 +0000550 return self.it.next()
551
552 f = open(TESTFN, "w")
553 try:
554 f.write("a\n" + "b\n" + "c\n")
555 finally:
556 f.close()
557
558 f = open(TESTFN, "r")
559 # Nasty: string.join(s) can't know whether unicode.join() is needed
560 # until it's seen all of s's elements. But in this case, f's
561 # iterator cannot be restarted. So what we're testing here is
562 # whether string.join() can manage to remember everything it's seen
563 # and pass that on to unicode.join().
564 try:
565 got = " - ".join(OhPhooey(f))
Martin v. Löwis339d0f72001-08-17 18:39:25 +0000566 self.assertEqual(got, unicode("a\n - b\n - fooled you! - c\n"))
Tim Peters2cfe3682001-05-05 05:36:48 +0000567 finally:
568 f.close()
569 try:
570 unlink(TESTFN)
571 except OSError:
572 pass
Martin v. Löwis339d0f72001-08-17 18:39:25 +0000573 if not have_unicode:
574 def test_unicode_join_endcase(self): pass
Tim Peters2cfe3682001-05-05 05:36:48 +0000575
Tim Petersde9725f2001-05-05 10:06:17 +0000576 # Test iterators with 'x in y' and 'x not in y'.
577 def test_in_and_not_in(self):
Tim Peterscb8d3682001-05-05 21:05:01 +0000578 for sc5 in IteratingSequenceClass(5), SequenceClass(5):
579 for i in range(5):
Benjamin Peterson5c8da862009-06-30 22:57:08 +0000580 self.assertTrue(i in sc5)
Tim Peterscb8d3682001-05-05 21:05:01 +0000581 for i in "abc", -1, 5, 42.42, (3, 4), [], {1: 1}, 3-12j, sc5:
Benjamin Peterson5c8da862009-06-30 22:57:08 +0000582 self.assertTrue(i not in sc5)
Tim Petersde9725f2001-05-05 10:06:17 +0000583
584 self.assertRaises(TypeError, lambda: 3 in 12)
585 self.assertRaises(TypeError, lambda: 3 not in map)
586
587 d = {"one": 1, "two": 2, "three": 3, 1j: 2j}
588 for k in d:
Benjamin Peterson5c8da862009-06-30 22:57:08 +0000589 self.assertTrue(k in d)
590 self.assertTrue(k not in d.itervalues())
Tim Petersde9725f2001-05-05 10:06:17 +0000591 for v in d.values():
Benjamin Peterson5c8da862009-06-30 22:57:08 +0000592 self.assertTrue(v in d.itervalues())
593 self.assertTrue(v not in d)
Tim Petersde9725f2001-05-05 10:06:17 +0000594 for k, v in d.iteritems():
Benjamin Peterson5c8da862009-06-30 22:57:08 +0000595 self.assertTrue((k, v) in d.iteritems())
596 self.assertTrue((v, k) not in d.iteritems())
Tim Petersde9725f2001-05-05 10:06:17 +0000597
598 f = open(TESTFN, "w")
599 try:
600 f.write("a\n" "b\n" "c\n")
601 finally:
602 f.close()
603 f = open(TESTFN, "r")
604 try:
605 for chunk in "abc":
606 f.seek(0, 0)
Benjamin Peterson5c8da862009-06-30 22:57:08 +0000607 self.assertTrue(chunk not in f)
Tim Petersde9725f2001-05-05 10:06:17 +0000608 f.seek(0, 0)
Benjamin Peterson5c8da862009-06-30 22:57:08 +0000609 self.assertTrue((chunk + "\n") in f)
Tim Petersde9725f2001-05-05 10:06:17 +0000610 finally:
611 f.close()
612 try:
613 unlink(TESTFN)
614 except OSError:
615 pass
616
Tim Peters75f8e352001-05-05 11:33:43 +0000617 # Test iterators with operator.countOf (PySequence_Count).
618 def test_countOf(self):
619 from operator import countOf
620 self.assertEqual(countOf([1,2,2,3,2,5], 2), 3)
621 self.assertEqual(countOf((1,2,2,3,2,5), 2), 3)
622 self.assertEqual(countOf("122325", "2"), 3)
623 self.assertEqual(countOf("122325", "6"), 0)
624
625 self.assertRaises(TypeError, countOf, 42, 1)
626 self.assertRaises(TypeError, countOf, countOf, countOf)
627
628 d = {"one": 3, "two": 3, "three": 3, 1j: 2j}
629 for k in d:
630 self.assertEqual(countOf(d, k), 1)
631 self.assertEqual(countOf(d.itervalues(), 3), 3)
632 self.assertEqual(countOf(d.itervalues(), 2j), 1)
633 self.assertEqual(countOf(d.itervalues(), 1j), 0)
634
635 f = open(TESTFN, "w")
636 try:
637 f.write("a\n" "b\n" "c\n" "b\n")
638 finally:
639 f.close()
640 f = open(TESTFN, "r")
641 try:
642 for letter, count in ("a", 1), ("b", 2), ("c", 1), ("d", 0):
643 f.seek(0, 0)
644 self.assertEqual(countOf(f, letter + "\n"), count)
645 finally:
646 f.close()
647 try:
648 unlink(TESTFN)
649 except OSError:
650 pass
651
Tim Peters16a77ad2001-09-08 04:00:12 +0000652 # Test iterators with operator.indexOf (PySequence_Index).
653 def test_indexOf(self):
654 from operator import indexOf
655 self.assertEqual(indexOf([1,2,2,3,2,5], 1), 0)
656 self.assertEqual(indexOf((1,2,2,3,2,5), 2), 1)
657 self.assertEqual(indexOf((1,2,2,3,2,5), 3), 3)
658 self.assertEqual(indexOf((1,2,2,3,2,5), 5), 5)
659 self.assertRaises(ValueError, indexOf, (1,2,2,3,2,5), 0)
660 self.assertRaises(ValueError, indexOf, (1,2,2,3,2,5), 6)
661
662 self.assertEqual(indexOf("122325", "2"), 1)
663 self.assertEqual(indexOf("122325", "5"), 5)
664 self.assertRaises(ValueError, indexOf, "122325", "6")
665
666 self.assertRaises(TypeError, indexOf, 42, 1)
667 self.assertRaises(TypeError, indexOf, indexOf, indexOf)
668
669 f = open(TESTFN, "w")
670 try:
671 f.write("a\n" "b\n" "c\n" "d\n" "e\n")
672 finally:
673 f.close()
674 f = open(TESTFN, "r")
675 try:
676 fiter = iter(f)
677 self.assertEqual(indexOf(fiter, "b\n"), 1)
678 self.assertEqual(indexOf(fiter, "d\n"), 1)
679 self.assertEqual(indexOf(fiter, "e\n"), 0)
680 self.assertRaises(ValueError, indexOf, fiter, "a\n")
681 finally:
682 f.close()
683 try:
684 unlink(TESTFN)
685 except OSError:
686 pass
687
688 iclass = IteratingSequenceClass(3)
689 for i in range(3):
690 self.assertEqual(indexOf(iclass, i), i)
691 self.assertRaises(ValueError, indexOf, iclass, -1)
692
Tim Peters2c9aa5e2001-09-23 04:06:05 +0000693 # Test iterators with file.writelines().
694 def test_writelines(self):
695 f = file(TESTFN, "w")
696
697 try:
698 self.assertRaises(TypeError, f.writelines, None)
699 self.assertRaises(TypeError, f.writelines, 42)
Tim Peters527e64f2001-10-04 05:36:56 +0000700
Tim Peters2c9aa5e2001-09-23 04:06:05 +0000701 f.writelines(["1\n", "2\n"])
702 f.writelines(("3\n", "4\n"))
703 f.writelines({'5\n': None})
704 f.writelines({})
705
706 # Try a big chunk too.
707 class Iterator:
708 def __init__(self, start, finish):
709 self.start = start
710 self.finish = finish
711 self.i = self.start
712
713 def next(self):
714 if self.i >= self.finish:
715 raise StopIteration
716 result = str(self.i) + '\n'
717 self.i += 1
718 return result
719
720 def __iter__(self):
721 return self
722
723 class Whatever:
724 def __init__(self, start, finish):
725 self.start = start
726 self.finish = finish
727
728 def __iter__(self):
729 return Iterator(self.start, self.finish)
Tim Peters527e64f2001-10-04 05:36:56 +0000730
731 f.writelines(Whatever(6, 6+2000))
Tim Peters2c9aa5e2001-09-23 04:06:05 +0000732 f.close()
733
734 f = file(TESTFN)
735 expected = [str(i) + "\n" for i in range(1, 2006)]
736 self.assertEqual(list(f), expected)
Tim Peters527e64f2001-10-04 05:36:56 +0000737
Tim Peters2c9aa5e2001-09-23 04:06:05 +0000738 finally:
739 f.close()
740 try:
741 unlink(TESTFN)
742 except OSError:
743 pass
744
745
Tim Petersd6d010b2001-06-21 02:49:55 +0000746 # Test iterators on RHS of unpacking assignments.
747 def test_unpack_iter(self):
748 a, b = 1, 2
749 self.assertEqual((a, b), (1, 2))
750
751 a, b, c = IteratingSequenceClass(3)
752 self.assertEqual((a, b, c), (0, 1, 2))
753
754 try: # too many values
755 a, b = IteratingSequenceClass(3)
756 except ValueError:
757 pass
758 else:
759 self.fail("should have raised ValueError")
760
761 try: # not enough values
762 a, b, c = IteratingSequenceClass(2)
763 except ValueError:
764 pass
765 else:
766 self.fail("should have raised ValueError")
767
768 try: # not iterable
769 a, b, c = len
770 except TypeError:
771 pass
772 else:
773 self.fail("should have raised TypeError")
774
775 a, b, c = {1: 42, 2: 42, 3: 42}.itervalues()
776 self.assertEqual((a, b, c), (42, 42, 42))
777
778 f = open(TESTFN, "w")
779 lines = ("a\n", "bb\n", "ccc\n")
780 try:
781 for line in lines:
782 f.write(line)
783 finally:
784 f.close()
785 f = open(TESTFN, "r")
786 try:
787 a, b, c = f
788 self.assertEqual((a, b, c), lines)
789 finally:
790 f.close()
791 try:
792 unlink(TESTFN)
793 except OSError:
794 pass
795
796 (a, b), (c,) = IteratingSequenceClass(2), {42: 24}
797 self.assertEqual((a, b, c), (0, 1, 42))
798
Guido van Rossumbb8f59a2001-12-03 19:33:25 +0000799 # Test reference count behavior
800
801 class C(object):
802 count = 0
803 def __new__(cls):
804 cls.count += 1
805 return object.__new__(cls)
806 def __del__(self):
807 cls = self.__class__
808 assert cls.count > 0
809 cls.count -= 1
810 x = C()
811 self.assertEqual(C.count, 1)
812 del x
813 self.assertEqual(C.count, 0)
814 l = [C(), C(), C()]
815 self.assertEqual(C.count, 3)
816 try:
817 a, b = iter(l)
818 except ValueError:
819 pass
820 del l
821 self.assertEqual(C.count, 0)
Fred Drake2e2be372001-09-20 21:33:42 +0000822
Guido van Rossum674eae62002-07-16 21:48:11 +0000823
824 # Make sure StopIteration is a "sink state".
825 # This tests various things that weren't sink states in Python 2.2.1,
826 # plus various things that always were fine.
827
828 def test_sinkstate_list(self):
829 # This used to fail
830 a = range(5)
831 b = iter(a)
832 self.assertEqual(list(b), range(5))
833 a.extend(range(5, 10))
834 self.assertEqual(list(b), [])
835
836 def test_sinkstate_tuple(self):
837 a = (0, 1, 2, 3, 4)
838 b = iter(a)
839 self.assertEqual(list(b), range(5))
840 self.assertEqual(list(b), [])
841
842 def test_sinkstate_string(self):
843 a = "abcde"
844 b = iter(a)
845 self.assertEqual(list(b), ['a', 'b', 'c', 'd', 'e'])
846 self.assertEqual(list(b), [])
847
848 def test_sinkstate_sequence(self):
849 # This used to fail
850 a = SequenceClass(5)
851 b = iter(a)
852 self.assertEqual(list(b), range(5))
853 a.n = 10
854 self.assertEqual(list(b), [])
855
856 def test_sinkstate_callable(self):
857 # This used to fail
858 def spam(state=[0]):
859 i = state[0]
860 state[0] = i+1
861 if i == 10:
862 raise AssertionError, "shouldn't have gotten this far"
863 return i
864 b = iter(spam, 5)
865 self.assertEqual(list(b), range(5))
866 self.assertEqual(list(b), [])
867
868 def test_sinkstate_dict(self):
869 # XXX For a more thorough test, see towards the end of:
870 # http://mail.python.org/pipermail/python-dev/2002-July/026512.html
871 a = {1:1, 2:2, 0:0, 4:4, 3:3}
872 for b in iter(a), a.iterkeys(), a.iteritems(), a.itervalues():
873 b = iter(a)
874 self.assertEqual(len(list(b)), 5)
875 self.assertEqual(list(b), [])
876
877 def test_sinkstate_yield(self):
878 def gen():
879 for i in range(5):
880 yield i
881 b = gen()
882 self.assertEqual(list(b), range(5))
883 self.assertEqual(list(b), [])
884
885 def test_sinkstate_range(self):
886 a = xrange(5)
887 b = iter(a)
888 self.assertEqual(list(b), range(5))
889 self.assertEqual(list(b), [])
890
891 def test_sinkstate_enumerate(self):
892 a = range(5)
893 e = enumerate(a)
894 b = iter(e)
895 self.assertEqual(list(b), zip(range(5), range(5)))
896 self.assertEqual(list(b), [])
897
Amaury Forgeot d'Arca40d5732009-01-12 23:36:55 +0000898 def test_3720(self):
899 # Avoid a crash, when an iterator deletes its next() method.
900 class BadIterator(object):
901 def __iter__(self):
902 return self
903 def next(self):
904 del BadIterator.next
905 return 1
906
907 try:
908 for i in BadIterator() :
909 pass
910 except TypeError:
911 pass
912
Guido van Rossum674eae62002-07-16 21:48:11 +0000913
Fred Drake2e2be372001-09-20 21:33:42 +0000914def test_main():
915 run_unittest(TestCase)
916
917
918if __name__ == "__main__":
919 test_main()