blob: 07a3bf2e23ba9736020a04a315ce1eb236fee6a3 [file] [log] [blame]
Guido van Rossum8b48cf92001-04-21 13:33:54 +00001# Test iterators.
2
3import unittest
Walter Dörwald1f5947b2007-05-22 16:52:54 +00004from test.test_support import run_unittest, TESTFN, unlink
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
Georg Brandla18af4e2007-04-21 15:47:16 +000025 def __next__(self):
Guido van Rossum8b48cf92001-04-21 13:33:54 +000026 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:
Georg Brandla18af4e2007-04-21 15:47:16 +000056 val = next(it)
Guido van Rossum8b48cf92001-04-21 13:33:54 +000057 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):
Guido van Rossum805365e2007-05-07 22:24:25 +000071 self.check_iterator(iter(range(10)), list(range(10)))
Guido van Rossum8b48cf92001-04-21 13:33:54 +000072
73 # Test that iter(iter(x)) is the same as iter(x)
74 def test_iter_idempotency(self):
Guido van Rossum805365e2007-05-07 22:24:25 +000075 seq = list(range(10))
Guido van Rossum8b48cf92001-04-21 13:33:54 +000076 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):
Guido van Rossum805365e2007-05-07 22:24:25 +000082 self.check_for_loop(iter(range(10)), list(range(10)))
Guido van Rossum8b48cf92001-04-21 13:33:54 +000083
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):
Guido van Rossum805365e2007-05-07 22:24:25 +0000109 self.check_for_loop(IteratingSequenceClass(10), list(range(10)))
Guido van Rossum8b48cf92001-04-21 13:33:54 +0000110
111 # Test a class with __iter__ with explicit iter()
112 def test_iter_class_iter(self):
Guido van Rossum805365e2007-05-07 22:24:25 +0000113 self.check_iterator(iter(IteratingSequenceClass(10)), list(range(10)))
Guido van Rossum8b48cf92001-04-21 13:33:54 +0000114
115 # Test for loop on a sequence class without __iter__
116 def test_seq_class_for(self):
Guido van Rossum805365e2007-05-07 22:24:25 +0000117 self.check_for_loop(SequenceClass(10), list(range(10)))
Guido van Rossum8b48cf92001-04-21 13:33:54 +0000118
119 # Test iter() on a sequence class without __iter__
120 def test_seq_class_iter(self):
Guido van Rossum805365e2007-05-07 22:24:25 +0000121 self.check_iterator(iter(SequenceClass(10)), list(range(10)))
Guido van Rossum8b48cf92001-04-21 13:33:54 +0000122
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
Guido van Rossum805365e2007-05-07 22:24:25 +0000134 self.check_iterator(iter(C(), 10), list(range(10)))
Guido van Rossum8b48cf92001-04-21 13:33:54 +0000135
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
Guido van Rossum805365e2007-05-07 22:24:25 +0000142 self.check_iterator(iter(spam, 10), list(range(10)))
Guido van Rossum8b48cf92001-04-21 13:33:54 +0000143
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
Guido van Rossum805365e2007-05-07 22:24:25 +0000152 self.check_iterator(iter(spam, 20), list(range(10)))
Guido van Rossum8b48cf92001-04-21 13:33:54 +0000153
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:
Guido van Rossum805365e2007-05-07 22:24:25 +0000167 self.assertEqual(res, list(range(10)))
Guido van Rossum8b48cf92001-04-21 13:33:54 +0000168 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:
Guido van Rossum805365e2007-05-07 22:24:25 +0000183 self.assertEqual(res, list(range(10)))
Guido van Rossum8b48cf92001-04-21 13:33:54 +0000184 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)
Guido van Rossum805365e2007-05-07 22:24:25 +0000194 self.check_for_loop(MySequenceClass(20), list(range(10)))
Guido van Rossum8b48cf92001-04-21 13:33:54 +0000195
196 # Test a big range
197 def test_iter_big_range(self):
Guido van Rossum805365e2007-05-07 22:24:25 +0000198 self.check_for_loop(iter(range(10000)), list(range(10000)))
Guido van Rossum8b48cf92001-04-21 13:33:54 +0000199
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):
Guido van Rossum805365e2007-05-07 22:24:25 +0000206 self.check_for_loop(iter((0,1,2,3,4,5,6,7,8,9)), list(range(10)))
Guido van Rossum8b48cf92001-04-21 13:33:54 +0000207
Guido van Rossum805365e2007-05-07 22:24:25 +0000208 # Test a range
209 def test_iter_range(self):
210 self.check_for_loop(iter(range(10)), list(range(10)))
Guido van Rossum8b48cf92001-04-21 13:33:54 +0000211
212 # Test a string
213 def test_iter_string(self):
214 self.check_for_loop(iter("abcde"), ["a", "b", "c", "d", "e"])
215
Guido van Rossum8b48cf92001-04-21 13:33:54 +0000216 # Test a directory
217 def test_iter_dict(self):
218 dict = {}
219 for i in range(10):
220 dict[i] = None
Brett Cannon0caf6d82007-02-22 04:49:03 +0000221 self.check_for_loop(dict, list(dict.keys()))
Guido van Rossum8b48cf92001-04-21 13:33:54 +0000222
223 # Test a file
224 def test_iter_file(self):
225 f = open(TESTFN, "w")
226 try:
227 for i in range(5):
228 f.write("%d\n" % i)
229 finally:
230 f.close()
231 f = open(TESTFN, "r")
232 try:
233 self.check_for_loop(f, ["0\n", "1\n", "2\n", "3\n", "4\n"])
234 self.check_for_loop(f, [])
235 finally:
236 f.close()
237 try:
238 unlink(TESTFN)
239 except OSError:
240 pass
241
Tim Petersf553f892001-05-01 20:45:31 +0000242 # Test list()'s use of iterators.
243 def test_builtin_list(self):
Guido van Rossum805365e2007-05-07 22:24:25 +0000244 self.assertEqual(list(SequenceClass(5)), list(range(5)))
Tim Petersf553f892001-05-01 20:45:31 +0000245 self.assertEqual(list(SequenceClass(0)), [])
246 self.assertEqual(list(()), [])
Tim Petersf553f892001-05-01 20:45:31 +0000247
248 d = {"one": 1, "two": 2, "three": 3}
Brett Cannon0caf6d82007-02-22 04:49:03 +0000249 self.assertEqual(list(d), list(d.keys()))
Tim Petersf553f892001-05-01 20:45:31 +0000250
251 self.assertRaises(TypeError, list, list)
252 self.assertRaises(TypeError, list, 42)
253
254 f = open(TESTFN, "w")
255 try:
256 for i in range(5):
257 f.write("%d\n" % i)
258 finally:
259 f.close()
260 f = open(TESTFN, "r")
261 try:
262 self.assertEqual(list(f), ["0\n", "1\n", "2\n", "3\n", "4\n"])
263 f.seek(0, 0)
Guido van Rossum8ee52432002-08-06 17:14:04 +0000264 self.assertEqual(list(f),
Tim Petersf553f892001-05-01 20:45:31 +0000265 ["0\n", "1\n", "2\n", "3\n", "4\n"])
266 finally:
267 f.close()
268 try:
269 unlink(TESTFN)
270 except OSError:
271 pass
272
Tim Peters6912d4d2001-05-05 03:56:37 +0000273 # Test tuples()'s use of iterators.
274 def test_builtin_tuple(self):
275 self.assertEqual(tuple(SequenceClass(5)), (0, 1, 2, 3, 4))
276 self.assertEqual(tuple(SequenceClass(0)), ())
277 self.assertEqual(tuple([]), ())
278 self.assertEqual(tuple(()), ())
279 self.assertEqual(tuple("abc"), ("a", "b", "c"))
280
281 d = {"one": 1, "two": 2, "three": 3}
282 self.assertEqual(tuple(d), tuple(d.keys()))
283
284 self.assertRaises(TypeError, tuple, list)
285 self.assertRaises(TypeError, tuple, 42)
286
287 f = open(TESTFN, "w")
288 try:
289 for i in range(5):
290 f.write("%d\n" % i)
291 finally:
292 f.close()
293 f = open(TESTFN, "r")
294 try:
295 self.assertEqual(tuple(f), ("0\n", "1\n", "2\n", "3\n", "4\n"))
296 f.seek(0, 0)
Guido van Rossum8ee52432002-08-06 17:14:04 +0000297 self.assertEqual(tuple(f),
Tim Peters6912d4d2001-05-05 03:56:37 +0000298 ("0\n", "1\n", "2\n", "3\n", "4\n"))
299 finally:
300 f.close()
301 try:
302 unlink(TESTFN)
303 except OSError:
304 pass
305
Tim Peters0e57abf2001-05-02 07:39:38 +0000306 # Test filter()'s use of iterators.
307 def test_builtin_filter(self):
Guido van Rossumc1f779c2007-07-03 08:25:58 +0000308 self.assertEqual(list(filter(None, SequenceClass(5))),
309 list(range(1, 5)))
310 self.assertEqual(list(filter(None, SequenceClass(0))), [])
311 self.assertEqual(list(filter(None, ())), [])
312 self.assertEqual(list(filter(None, "abc")), ["a", "b", "c"])
Tim Peters0e57abf2001-05-02 07:39:38 +0000313
314 d = {"one": 1, "two": 2, "three": 3}
Guido van Rossumc1f779c2007-07-03 08:25:58 +0000315 self.assertEqual(list(filter(None, d)), list(d.keys()))
Tim Peters0e57abf2001-05-02 07:39:38 +0000316
317 self.assertRaises(TypeError, filter, None, list)
318 self.assertRaises(TypeError, filter, None, 42)
319
320 class Boolean:
321 def __init__(self, truth):
322 self.truth = truth
Jack Diederich4dafcc42006-11-28 19:15:13 +0000323 def __bool__(self):
Tim Peters0e57abf2001-05-02 07:39:38 +0000324 return self.truth
Jack Diederich4dafcc42006-11-28 19:15:13 +0000325 bTrue = Boolean(True)
326 bFalse = Boolean(False)
Tim Peters0e57abf2001-05-02 07:39:38 +0000327
328 class Seq:
329 def __init__(self, *args):
330 self.vals = args
331 def __iter__(self):
332 class SeqIter:
333 def __init__(self, vals):
334 self.vals = vals
335 self.i = 0
336 def __iter__(self):
337 return self
Georg Brandla18af4e2007-04-21 15:47:16 +0000338 def __next__(self):
Tim Peters0e57abf2001-05-02 07:39:38 +0000339 i = self.i
340 self.i = i + 1
341 if i < len(self.vals):
342 return self.vals[i]
343 else:
344 raise StopIteration
345 return SeqIter(self.vals)
346
Tim Peterscae330e2002-12-23 16:50:58 +0000347 seq = Seq(*([bTrue, bFalse] * 25))
Guido van Rossumc1f779c2007-07-03 08:25:58 +0000348 self.assertEqual(list(filter(lambda x: not x, seq)), [bFalse]*25)
349 self.assertEqual(list(filter(lambda x: not x, iter(seq))), [bFalse]*25)
Tim Peters0e57abf2001-05-02 07:39:38 +0000350
Tim Petersc3074532001-05-03 07:00:32 +0000351 # Test max() and min()'s use of iterators.
352 def test_builtin_max_min(self):
353 self.assertEqual(max(SequenceClass(5)), 4)
354 self.assertEqual(min(SequenceClass(5)), 0)
355 self.assertEqual(max(8, -1), 8)
356 self.assertEqual(min(8, -1), -1)
357
358 d = {"one": 1, "two": 2, "three": 3}
359 self.assertEqual(max(d), "two")
360 self.assertEqual(min(d), "one")
Guido van Rossumcc2b0162007-02-11 06:12:03 +0000361 self.assertEqual(max(d.values()), 3)
362 self.assertEqual(min(iter(d.values())), 1)
Tim Petersc3074532001-05-03 07:00:32 +0000363
Tim Petersc3074532001-05-03 07:00:32 +0000364 f = open(TESTFN, "w")
365 try:
366 f.write("medium line\n")
367 f.write("xtra large line\n")
368 f.write("itty-bitty line\n")
369 finally:
370 f.close()
371 f = open(TESTFN, "r")
372 try:
373 self.assertEqual(min(f), "itty-bitty line\n")
374 f.seek(0, 0)
375 self.assertEqual(max(f), "xtra large line\n")
376 finally:
377 f.close()
378 try:
379 unlink(TESTFN)
380 except OSError:
381 pass
382
Tim Peters4e9afdc2001-05-03 23:54:49 +0000383 # Test map()'s use of iterators.
384 def test_builtin_map(self):
Guido van Rossumc1f779c2007-07-03 08:25:58 +0000385 self.assertEqual(list(map(None, SequenceClass(5))),
386 [(0,), (1,), (2,), (3,), (4,)])
387 self.assertEqual(list(map(lambda x: x+1, SequenceClass(5))),
388 list(range(1, 6)))
Tim Peters4e9afdc2001-05-03 23:54:49 +0000389
390 d = {"one": 1, "two": 2, "three": 3}
Guido van Rossumc1f779c2007-07-03 08:25:58 +0000391 self.assertEqual(list(map(None, d)), [(k,) for k in d])
392 self.assertEqual(list(map(lambda k, d=d: (k, d[k]), d)),
393 list(d.items()))
Brett Cannon0caf6d82007-02-22 04:49:03 +0000394 dkeys = list(d.keys())
Tim Peters4e9afdc2001-05-03 23:54:49 +0000395 expected = [(i < len(d) and dkeys[i] or None,
396 i,
397 i < len(d) and dkeys[i] or None)
Guido van Rossumc1f779c2007-07-03 08:25:58 +0000398 for i in range(3)]
399 self.assertEqual(list(map(None,
400 d,
401 SequenceClass(5),
402 iter(d.keys()))),
Tim Peters8bc10b02001-05-03 23:58:47 +0000403 expected)
Tim Peters4e9afdc2001-05-03 23:54:49 +0000404
405 f = open(TESTFN, "w")
406 try:
407 for i in range(10):
408 f.write("xy" * i + "\n") # line i has len 2*i+1
409 finally:
410 f.close()
411 f = open(TESTFN, "r")
412 try:
Guido van Rossumc1f779c2007-07-03 08:25:58 +0000413 self.assertEqual(list(map(len, f)), list(range(1, 21, 2)))
Tim Peters4e9afdc2001-05-03 23:54:49 +0000414 finally:
415 f.close()
416 try:
417 unlink(TESTFN)
418 except OSError:
419 pass
420
Tim Peters8572b4f2001-05-06 01:05:02 +0000421 # Test zip()'s use of iterators.
422 def test_builtin_zip(self):
Guido van Rossum801f0d72006-08-24 19:48:10 +0000423 self.assertEqual(list(zip()), [])
424 self.assertEqual(list(zip(*[])), [])
425 self.assertEqual(list(zip(*[(1, 2), 'ab'])), [(1, 'a'), (2, 'b')])
Raymond Hettingereaef6152003-08-02 07:42:57 +0000426
Tim Peters8572b4f2001-05-06 01:05:02 +0000427 self.assertRaises(TypeError, zip, None)
428 self.assertRaises(TypeError, zip, range(10), 42)
429 self.assertRaises(TypeError, zip, range(10), zip)
430
Guido van Rossum801f0d72006-08-24 19:48:10 +0000431 self.assertEqual(list(zip(IteratingSequenceClass(3))),
Tim Peters8572b4f2001-05-06 01:05:02 +0000432 [(0,), (1,), (2,)])
Guido van Rossum801f0d72006-08-24 19:48:10 +0000433 self.assertEqual(list(zip(SequenceClass(3))),
Tim Peters8572b4f2001-05-06 01:05:02 +0000434 [(0,), (1,), (2,)])
435
436 d = {"one": 1, "two": 2, "three": 3}
Brett Cannon0caf6d82007-02-22 04:49:03 +0000437 self.assertEqual(list(d.items()), list(zip(d, d.values())))
Tim Peters8572b4f2001-05-06 01:05:02 +0000438
439 # Generate all ints starting at constructor arg.
440 class IntsFrom:
441 def __init__(self, start):
442 self.i = start
443
444 def __iter__(self):
445 return self
446
Georg Brandla18af4e2007-04-21 15:47:16 +0000447 def __next__(self):
Tim Peters8572b4f2001-05-06 01:05:02 +0000448 i = self.i
449 self.i = i+1
450 return i
451
452 f = open(TESTFN, "w")
453 try:
454 f.write("a\n" "bbb\n" "cc\n")
455 finally:
456 f.close()
457 f = open(TESTFN, "r")
458 try:
Guido van Rossum801f0d72006-08-24 19:48:10 +0000459 self.assertEqual(list(zip(IntsFrom(0), f, IntsFrom(-100))),
Tim Peters8572b4f2001-05-06 01:05:02 +0000460 [(0, "a\n", -100),
461 (1, "bbb\n", -99),
462 (2, "cc\n", -98)])
463 finally:
464 f.close()
465 try:
466 unlink(TESTFN)
467 except OSError:
468 pass
469
Guido van Rossum805365e2007-05-07 22:24:25 +0000470 self.assertEqual(list(zip(range(5))), [(i,) for i in range(5)])
Tim Peters67d687a2002-04-29 21:27:32 +0000471
472 # Classes that lie about their lengths.
473 class NoGuessLen5:
474 def __getitem__(self, i):
475 if i >= 5:
476 raise IndexError
477 return i
478
479 class Guess3Len5(NoGuessLen5):
480 def __len__(self):
481 return 3
482
483 class Guess30Len5(NoGuessLen5):
484 def __len__(self):
485 return 30
486
Guido van Rossum801f0d72006-08-24 19:48:10 +0000487 def lzip(*args):
488 return list(zip(*args))
489
Tim Peters67d687a2002-04-29 21:27:32 +0000490 self.assertEqual(len(Guess3Len5()), 3)
491 self.assertEqual(len(Guess30Len5()), 30)
Guido van Rossum801f0d72006-08-24 19:48:10 +0000492 self.assertEqual(lzip(NoGuessLen5()), lzip(range(5)))
493 self.assertEqual(lzip(Guess3Len5()), lzip(range(5)))
494 self.assertEqual(lzip(Guess30Len5()), lzip(range(5)))
Tim Peters67d687a2002-04-29 21:27:32 +0000495
496 expected = [(i, i) for i in range(5)]
497 for x in NoGuessLen5(), Guess3Len5(), Guess30Len5():
498 for y in NoGuessLen5(), Guess3Len5(), Guess30Len5():
Guido van Rossum801f0d72006-08-24 19:48:10 +0000499 self.assertEqual(lzip(x, y), expected)
Tim Peters67d687a2002-04-29 21:27:32 +0000500
Tim Peters2cfe3682001-05-05 05:36:48 +0000501 def test_unicode_join_endcase(self):
502
503 # This class inserts a Unicode object into its argument's natural
504 # iteration, in the 3rd position.
505 class OhPhooey:
506 def __init__(self, seq):
507 self.it = iter(seq)
508 self.i = 0
509
510 def __iter__(self):
511 return self
512
Georg Brandla18af4e2007-04-21 15:47:16 +0000513 def __next__(self):
Tim Peters2cfe3682001-05-05 05:36:48 +0000514 i = self.i
515 self.i = i+1
516 if i == 2:
Walter Dörwald1f5947b2007-05-22 16:52:54 +0000517 return "fooled you!"
Georg Brandla18af4e2007-04-21 15:47:16 +0000518 return next(self.it)
Tim Peters2cfe3682001-05-05 05:36:48 +0000519
520 f = open(TESTFN, "w")
521 try:
522 f.write("a\n" + "b\n" + "c\n")
523 finally:
524 f.close()
525
526 f = open(TESTFN, "r")
527 # Nasty: string.join(s) can't know whether unicode.join() is needed
528 # until it's seen all of s's elements. But in this case, f's
529 # iterator cannot be restarted. So what we're testing here is
530 # whether string.join() can manage to remember everything it's seen
531 # and pass that on to unicode.join().
532 try:
533 got = " - ".join(OhPhooey(f))
Walter Dörwald5de48bd2007-06-11 21:38:39 +0000534 self.assertEqual(got, "a\n - b\n - fooled you! - c\n")
Tim Peters2cfe3682001-05-05 05:36:48 +0000535 finally:
536 f.close()
537 try:
538 unlink(TESTFN)
539 except OSError:
540 pass
541
Tim Petersde9725f2001-05-05 10:06:17 +0000542 # Test iterators with 'x in y' and 'x not in y'.
543 def test_in_and_not_in(self):
Tim Peterscb8d3682001-05-05 21:05:01 +0000544 for sc5 in IteratingSequenceClass(5), SequenceClass(5):
545 for i in range(5):
546 self.assert_(i in sc5)
547 for i in "abc", -1, 5, 42.42, (3, 4), [], {1: 1}, 3-12j, sc5:
548 self.assert_(i not in sc5)
Tim Petersde9725f2001-05-05 10:06:17 +0000549
550 self.assertRaises(TypeError, lambda: 3 in 12)
551 self.assertRaises(TypeError, lambda: 3 not in map)
552
553 d = {"one": 1, "two": 2, "three": 3, 1j: 2j}
554 for k in d:
555 self.assert_(k in d)
Guido van Rossumcc2b0162007-02-11 06:12:03 +0000556 self.assert_(k not in d.values())
Tim Petersde9725f2001-05-05 10:06:17 +0000557 for v in d.values():
Guido van Rossumcc2b0162007-02-11 06:12:03 +0000558 self.assert_(v in d.values())
Tim Petersde9725f2001-05-05 10:06:17 +0000559 self.assert_(v not in d)
Guido van Rossumcc2b0162007-02-11 06:12:03 +0000560 for k, v in d.items():
561 self.assert_((k, v) in d.items())
562 self.assert_((v, k) not in d.items())
Tim Petersde9725f2001-05-05 10:06:17 +0000563
564 f = open(TESTFN, "w")
565 try:
566 f.write("a\n" "b\n" "c\n")
567 finally:
568 f.close()
569 f = open(TESTFN, "r")
570 try:
571 for chunk in "abc":
572 f.seek(0, 0)
573 self.assert_(chunk not in f)
574 f.seek(0, 0)
575 self.assert_((chunk + "\n") in f)
576 finally:
577 f.close()
578 try:
579 unlink(TESTFN)
580 except OSError:
581 pass
582
Tim Peters75f8e352001-05-05 11:33:43 +0000583 # Test iterators with operator.countOf (PySequence_Count).
584 def test_countOf(self):
585 from operator import countOf
586 self.assertEqual(countOf([1,2,2,3,2,5], 2), 3)
587 self.assertEqual(countOf((1,2,2,3,2,5), 2), 3)
588 self.assertEqual(countOf("122325", "2"), 3)
589 self.assertEqual(countOf("122325", "6"), 0)
590
591 self.assertRaises(TypeError, countOf, 42, 1)
592 self.assertRaises(TypeError, countOf, countOf, countOf)
593
594 d = {"one": 3, "two": 3, "three": 3, 1j: 2j}
595 for k in d:
596 self.assertEqual(countOf(d, k), 1)
Guido van Rossumcc2b0162007-02-11 06:12:03 +0000597 self.assertEqual(countOf(d.values(), 3), 3)
598 self.assertEqual(countOf(d.values(), 2j), 1)
599 self.assertEqual(countOf(d.values(), 1j), 0)
Tim Peters75f8e352001-05-05 11:33:43 +0000600
601 f = open(TESTFN, "w")
602 try:
603 f.write("a\n" "b\n" "c\n" "b\n")
604 finally:
605 f.close()
606 f = open(TESTFN, "r")
607 try:
608 for letter, count in ("a", 1), ("b", 2), ("c", 1), ("d", 0):
609 f.seek(0, 0)
610 self.assertEqual(countOf(f, letter + "\n"), count)
611 finally:
612 f.close()
613 try:
614 unlink(TESTFN)
615 except OSError:
616 pass
617
Tim Peters16a77ad2001-09-08 04:00:12 +0000618 # Test iterators with operator.indexOf (PySequence_Index).
619 def test_indexOf(self):
620 from operator import indexOf
621 self.assertEqual(indexOf([1,2,2,3,2,5], 1), 0)
622 self.assertEqual(indexOf((1,2,2,3,2,5), 2), 1)
623 self.assertEqual(indexOf((1,2,2,3,2,5), 3), 3)
624 self.assertEqual(indexOf((1,2,2,3,2,5), 5), 5)
625 self.assertRaises(ValueError, indexOf, (1,2,2,3,2,5), 0)
626 self.assertRaises(ValueError, indexOf, (1,2,2,3,2,5), 6)
627
628 self.assertEqual(indexOf("122325", "2"), 1)
629 self.assertEqual(indexOf("122325", "5"), 5)
630 self.assertRaises(ValueError, indexOf, "122325", "6")
631
632 self.assertRaises(TypeError, indexOf, 42, 1)
633 self.assertRaises(TypeError, indexOf, indexOf, indexOf)
634
635 f = open(TESTFN, "w")
636 try:
637 f.write("a\n" "b\n" "c\n" "d\n" "e\n")
638 finally:
639 f.close()
640 f = open(TESTFN, "r")
641 try:
642 fiter = iter(f)
643 self.assertEqual(indexOf(fiter, "b\n"), 1)
644 self.assertEqual(indexOf(fiter, "d\n"), 1)
645 self.assertEqual(indexOf(fiter, "e\n"), 0)
646 self.assertRaises(ValueError, indexOf, fiter, "a\n")
647 finally:
648 f.close()
649 try:
650 unlink(TESTFN)
651 except OSError:
652 pass
653
654 iclass = IteratingSequenceClass(3)
655 for i in range(3):
656 self.assertEqual(indexOf(iclass, i), i)
657 self.assertRaises(ValueError, indexOf, iclass, -1)
658
Tim Peters2c9aa5e2001-09-23 04:06:05 +0000659 # Test iterators with file.writelines().
660 def test_writelines(self):
Alex Martelli01c77c62006-08-24 02:58:11 +0000661 f = open(TESTFN, "w")
Tim Peters2c9aa5e2001-09-23 04:06:05 +0000662
663 try:
664 self.assertRaises(TypeError, f.writelines, None)
665 self.assertRaises(TypeError, f.writelines, 42)
Tim Peters527e64f2001-10-04 05:36:56 +0000666
Tim Peters2c9aa5e2001-09-23 04:06:05 +0000667 f.writelines(["1\n", "2\n"])
668 f.writelines(("3\n", "4\n"))
669 f.writelines({'5\n': None})
670 f.writelines({})
671
672 # Try a big chunk too.
673 class Iterator:
674 def __init__(self, start, finish):
675 self.start = start
676 self.finish = finish
677 self.i = self.start
678
Georg Brandla18af4e2007-04-21 15:47:16 +0000679 def __next__(self):
Tim Peters2c9aa5e2001-09-23 04:06:05 +0000680 if self.i >= self.finish:
681 raise StopIteration
682 result = str(self.i) + '\n'
683 self.i += 1
684 return result
685
686 def __iter__(self):
687 return self
688
689 class Whatever:
690 def __init__(self, start, finish):
691 self.start = start
692 self.finish = finish
693
694 def __iter__(self):
695 return Iterator(self.start, self.finish)
Tim Peters527e64f2001-10-04 05:36:56 +0000696
697 f.writelines(Whatever(6, 6+2000))
Tim Peters2c9aa5e2001-09-23 04:06:05 +0000698 f.close()
699
Alex Martelli01c77c62006-08-24 02:58:11 +0000700 f = open(TESTFN)
Tim Peters2c9aa5e2001-09-23 04:06:05 +0000701 expected = [str(i) + "\n" for i in range(1, 2006)]
702 self.assertEqual(list(f), expected)
Tim Peters527e64f2001-10-04 05:36:56 +0000703
Tim Peters2c9aa5e2001-09-23 04:06:05 +0000704 finally:
705 f.close()
706 try:
707 unlink(TESTFN)
708 except OSError:
709 pass
710
711
Tim Petersd6d010b2001-06-21 02:49:55 +0000712 # Test iterators on RHS of unpacking assignments.
713 def test_unpack_iter(self):
714 a, b = 1, 2
715 self.assertEqual((a, b), (1, 2))
716
717 a, b, c = IteratingSequenceClass(3)
718 self.assertEqual((a, b, c), (0, 1, 2))
719
720 try: # too many values
721 a, b = IteratingSequenceClass(3)
722 except ValueError:
723 pass
724 else:
725 self.fail("should have raised ValueError")
726
727 try: # not enough values
728 a, b, c = IteratingSequenceClass(2)
729 except ValueError:
730 pass
731 else:
732 self.fail("should have raised ValueError")
733
734 try: # not iterable
735 a, b, c = len
736 except TypeError:
737 pass
738 else:
739 self.fail("should have raised TypeError")
740
Guido van Rossumcc2b0162007-02-11 06:12:03 +0000741 a, b, c = {1: 42, 2: 42, 3: 42}.values()
Tim Petersd6d010b2001-06-21 02:49:55 +0000742 self.assertEqual((a, b, c), (42, 42, 42))
743
744 f = open(TESTFN, "w")
745 lines = ("a\n", "bb\n", "ccc\n")
746 try:
747 for line in lines:
748 f.write(line)
749 finally:
750 f.close()
751 f = open(TESTFN, "r")
752 try:
753 a, b, c = f
754 self.assertEqual((a, b, c), lines)
755 finally:
756 f.close()
757 try:
758 unlink(TESTFN)
759 except OSError:
760 pass
761
762 (a, b), (c,) = IteratingSequenceClass(2), {42: 24}
763 self.assertEqual((a, b, c), (0, 1, 42))
764
Guido van Rossumbb8f59a2001-12-03 19:33:25 +0000765 # Test reference count behavior
766
767 class C(object):
768 count = 0
769 def __new__(cls):
770 cls.count += 1
771 return object.__new__(cls)
772 def __del__(self):
773 cls = self.__class__
774 assert cls.count > 0
775 cls.count -= 1
776 x = C()
777 self.assertEqual(C.count, 1)
778 del x
779 self.assertEqual(C.count, 0)
780 l = [C(), C(), C()]
781 self.assertEqual(C.count, 3)
782 try:
783 a, b = iter(l)
784 except ValueError:
785 pass
786 del l
787 self.assertEqual(C.count, 0)
Fred Drake2e2be372001-09-20 21:33:42 +0000788
Guido van Rossum674eae62002-07-16 21:48:11 +0000789
790 # Make sure StopIteration is a "sink state".
791 # This tests various things that weren't sink states in Python 2.2.1,
792 # plus various things that always were fine.
793
794 def test_sinkstate_list(self):
795 # This used to fail
Guido van Rossum805365e2007-05-07 22:24:25 +0000796 a = list(range(5))
Guido van Rossum674eae62002-07-16 21:48:11 +0000797 b = iter(a)
Guido van Rossum805365e2007-05-07 22:24:25 +0000798 self.assertEqual(list(b), list(range(5)))
Guido van Rossum674eae62002-07-16 21:48:11 +0000799 a.extend(range(5, 10))
800 self.assertEqual(list(b), [])
801
802 def test_sinkstate_tuple(self):
803 a = (0, 1, 2, 3, 4)
804 b = iter(a)
Guido van Rossum805365e2007-05-07 22:24:25 +0000805 self.assertEqual(list(b), list(range(5)))
Guido van Rossum674eae62002-07-16 21:48:11 +0000806 self.assertEqual(list(b), [])
807
808 def test_sinkstate_string(self):
809 a = "abcde"
810 b = iter(a)
811 self.assertEqual(list(b), ['a', 'b', 'c', 'd', 'e'])
812 self.assertEqual(list(b), [])
813
814 def test_sinkstate_sequence(self):
815 # This used to fail
816 a = SequenceClass(5)
817 b = iter(a)
Guido van Rossum805365e2007-05-07 22:24:25 +0000818 self.assertEqual(list(b), list(range(5)))
Guido van Rossum674eae62002-07-16 21:48:11 +0000819 a.n = 10
820 self.assertEqual(list(b), [])
821
822 def test_sinkstate_callable(self):
823 # This used to fail
824 def spam(state=[0]):
825 i = state[0]
826 state[0] = i+1
827 if i == 10:
Collin Winter3add4d72007-08-29 23:37:32 +0000828 raise AssertionError("shouldn't have gotten this far")
Guido van Rossum674eae62002-07-16 21:48:11 +0000829 return i
830 b = iter(spam, 5)
Guido van Rossum805365e2007-05-07 22:24:25 +0000831 self.assertEqual(list(b), list(range(5)))
Guido van Rossum674eae62002-07-16 21:48:11 +0000832 self.assertEqual(list(b), [])
833
834 def test_sinkstate_dict(self):
835 # XXX For a more thorough test, see towards the end of:
836 # http://mail.python.org/pipermail/python-dev/2002-July/026512.html
837 a = {1:1, 2:2, 0:0, 4:4, 3:3}
Guido van Rossumcc2b0162007-02-11 06:12:03 +0000838 for b in iter(a), a.keys(), a.items(), a.values():
Guido van Rossum674eae62002-07-16 21:48:11 +0000839 b = iter(a)
840 self.assertEqual(len(list(b)), 5)
841 self.assertEqual(list(b), [])
842
843 def test_sinkstate_yield(self):
844 def gen():
845 for i in range(5):
846 yield i
847 b = gen()
Guido van Rossum805365e2007-05-07 22:24:25 +0000848 self.assertEqual(list(b), list(range(5)))
Guido van Rossum674eae62002-07-16 21:48:11 +0000849 self.assertEqual(list(b), [])
850
851 def test_sinkstate_range(self):
Guido van Rossum805365e2007-05-07 22:24:25 +0000852 a = range(5)
Guido van Rossum674eae62002-07-16 21:48:11 +0000853 b = iter(a)
Guido van Rossum805365e2007-05-07 22:24:25 +0000854 self.assertEqual(list(b), list(range(5)))
Guido van Rossum674eae62002-07-16 21:48:11 +0000855 self.assertEqual(list(b), [])
856
857 def test_sinkstate_enumerate(self):
858 a = range(5)
859 e = enumerate(a)
860 b = iter(e)
Guido van Rossum801f0d72006-08-24 19:48:10 +0000861 self.assertEqual(list(b), list(zip(range(5), range(5))))
Guido van Rossum674eae62002-07-16 21:48:11 +0000862 self.assertEqual(list(b), [])
863
864
Fred Drake2e2be372001-09-20 21:33:42 +0000865def test_main():
866 run_unittest(TestCase)
867
868
869if __name__ == "__main__":
870 test_main()