blob: e424303305737cd0ba2f05559d6a2498ff6cd395 [file] [log] [blame]
Guido van Rossum8b48cf92001-04-21 13:33:54 +00001# Test iterators.
2
3import unittest
Benjamin Peterson945c5792010-06-22 20:34:34 +00004from test.support import run_unittest, TESTFN, unlink, cpython_only
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)
Benjamin Petersonc9c0f202009-06-30 23:06:06 +000078 self.assertTrue(it is it2)
Guido van Rossum8b48cf92001-04-21 13:33:54 +000079
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
Amaury Forgeot d'Arcf343e012009-01-12 23:58:21 +0000123 # Test a new_style class with __iter__ but no next() method
124 def test_new_style_iter_class(self):
125 class IterClass(object):
126 def __iter__(self):
127 return self
128 self.assertRaises(TypeError, iter, IterClass())
129
Guido van Rossum8b48cf92001-04-21 13:33:54 +0000130 # Test two-argument iter() with callable instance
131 def test_iter_callable(self):
132 class C:
133 def __init__(self):
134 self.i = 0
135 def __call__(self):
136 i = self.i
137 self.i = i + 1
138 if i > 100:
139 raise IndexError # Emergency stop
140 return i
Guido van Rossum805365e2007-05-07 22:24:25 +0000141 self.check_iterator(iter(C(), 10), list(range(10)))
Guido van Rossum8b48cf92001-04-21 13:33:54 +0000142
143 # Test two-argument iter() with function
144 def test_iter_function(self):
145 def spam(state=[0]):
146 i = state[0]
147 state[0] = i+1
148 return i
Guido van Rossum805365e2007-05-07 22:24:25 +0000149 self.check_iterator(iter(spam, 10), list(range(10)))
Guido van Rossum8b48cf92001-04-21 13:33:54 +0000150
151 # Test two-argument iter() with function that raises StopIteration
152 def test_iter_function_stop(self):
153 def spam(state=[0]):
154 i = state[0]
155 if i == 10:
156 raise StopIteration
157 state[0] = i+1
158 return i
Guido van Rossum805365e2007-05-07 22:24:25 +0000159 self.check_iterator(iter(spam, 20), list(range(10)))
Guido van Rossum8b48cf92001-04-21 13:33:54 +0000160
161 # Test exception propagation through function iterator
162 def test_exception_function(self):
163 def spam(state=[0]):
164 i = state[0]
165 state[0] = i+1
166 if i == 10:
167 raise RuntimeError
168 return i
169 res = []
170 try:
171 for x in iter(spam, 20):
172 res.append(x)
173 except RuntimeError:
Guido van Rossum805365e2007-05-07 22:24:25 +0000174 self.assertEqual(res, list(range(10)))
Guido van Rossum8b48cf92001-04-21 13:33:54 +0000175 else:
176 self.fail("should have raised RuntimeError")
177
178 # Test exception propagation through sequence iterator
179 def test_exception_sequence(self):
180 class MySequenceClass(SequenceClass):
181 def __getitem__(self, i):
182 if i == 10:
183 raise RuntimeError
184 return SequenceClass.__getitem__(self, i)
185 res = []
186 try:
187 for x in MySequenceClass(20):
188 res.append(x)
189 except RuntimeError:
Guido van Rossum805365e2007-05-07 22:24:25 +0000190 self.assertEqual(res, list(range(10)))
Guido van Rossum8b48cf92001-04-21 13:33:54 +0000191 else:
192 self.fail("should have raised RuntimeError")
193
194 # Test for StopIteration from __getitem__
195 def test_stop_sequence(self):
196 class MySequenceClass(SequenceClass):
197 def __getitem__(self, i):
198 if i == 10:
199 raise StopIteration
200 return SequenceClass.__getitem__(self, i)
Guido van Rossum805365e2007-05-07 22:24:25 +0000201 self.check_for_loop(MySequenceClass(20), list(range(10)))
Guido van Rossum8b48cf92001-04-21 13:33:54 +0000202
203 # Test a big range
204 def test_iter_big_range(self):
Guido van Rossum805365e2007-05-07 22:24:25 +0000205 self.check_for_loop(iter(range(10000)), list(range(10000)))
Guido van Rossum8b48cf92001-04-21 13:33:54 +0000206
207 # Test an empty list
208 def test_iter_empty(self):
209 self.check_for_loop(iter([]), [])
210
211 # Test a tuple
212 def test_iter_tuple(self):
Guido van Rossum805365e2007-05-07 22:24:25 +0000213 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 +0000214
Guido van Rossum805365e2007-05-07 22:24:25 +0000215 # Test a range
216 def test_iter_range(self):
217 self.check_for_loop(iter(range(10)), list(range(10)))
Guido van Rossum8b48cf92001-04-21 13:33:54 +0000218
219 # Test a string
220 def test_iter_string(self):
221 self.check_for_loop(iter("abcde"), ["a", "b", "c", "d", "e"])
222
Guido van Rossum8b48cf92001-04-21 13:33:54 +0000223 # Test a directory
224 def test_iter_dict(self):
225 dict = {}
226 for i in range(10):
227 dict[i] = None
Brett Cannon0caf6d82007-02-22 04:49:03 +0000228 self.check_for_loop(dict, list(dict.keys()))
Guido van Rossum8b48cf92001-04-21 13:33:54 +0000229
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):
Guido van Rossum805365e2007-05-07 22:24:25 +0000251 self.assertEqual(list(SequenceClass(5)), list(range(5)))
Tim Petersf553f892001-05-01 20:45:31 +0000252 self.assertEqual(list(SequenceClass(0)), [])
253 self.assertEqual(list(()), [])
Tim Petersf553f892001-05-01 20:45:31 +0000254
255 d = {"one": 1, "two": 2, "three": 3}
Brett Cannon0caf6d82007-02-22 04:49:03 +0000256 self.assertEqual(list(d), list(d.keys()))
Tim Petersf553f892001-05-01 20:45:31 +0000257
258 self.assertRaises(TypeError, list, list)
259 self.assertRaises(TypeError, list, 42)
260
261 f = open(TESTFN, "w")
262 try:
263 for i in range(5):
264 f.write("%d\n" % i)
265 finally:
266 f.close()
267 f = open(TESTFN, "r")
268 try:
269 self.assertEqual(list(f), ["0\n", "1\n", "2\n", "3\n", "4\n"])
270 f.seek(0, 0)
Guido van Rossum8ee52432002-08-06 17:14:04 +0000271 self.assertEqual(list(f),
Tim Petersf553f892001-05-01 20:45:31 +0000272 ["0\n", "1\n", "2\n", "3\n", "4\n"])
273 finally:
274 f.close()
275 try:
276 unlink(TESTFN)
277 except OSError:
278 pass
279
Tim Peters6912d4d2001-05-05 03:56:37 +0000280 # Test tuples()'s use of iterators.
281 def test_builtin_tuple(self):
282 self.assertEqual(tuple(SequenceClass(5)), (0, 1, 2, 3, 4))
283 self.assertEqual(tuple(SequenceClass(0)), ())
284 self.assertEqual(tuple([]), ())
285 self.assertEqual(tuple(()), ())
286 self.assertEqual(tuple("abc"), ("a", "b", "c"))
287
288 d = {"one": 1, "two": 2, "three": 3}
289 self.assertEqual(tuple(d), tuple(d.keys()))
290
291 self.assertRaises(TypeError, tuple, list)
292 self.assertRaises(TypeError, tuple, 42)
293
294 f = open(TESTFN, "w")
295 try:
296 for i in range(5):
297 f.write("%d\n" % i)
298 finally:
299 f.close()
300 f = open(TESTFN, "r")
301 try:
302 self.assertEqual(tuple(f), ("0\n", "1\n", "2\n", "3\n", "4\n"))
303 f.seek(0, 0)
Guido van Rossum8ee52432002-08-06 17:14:04 +0000304 self.assertEqual(tuple(f),
Tim Peters6912d4d2001-05-05 03:56:37 +0000305 ("0\n", "1\n", "2\n", "3\n", "4\n"))
306 finally:
307 f.close()
308 try:
309 unlink(TESTFN)
310 except OSError:
311 pass
312
Tim Peters0e57abf2001-05-02 07:39:38 +0000313 # Test filter()'s use of iterators.
314 def test_builtin_filter(self):
Guido van Rossumc1f779c2007-07-03 08:25:58 +0000315 self.assertEqual(list(filter(None, SequenceClass(5))),
316 list(range(1, 5)))
317 self.assertEqual(list(filter(None, SequenceClass(0))), [])
318 self.assertEqual(list(filter(None, ())), [])
319 self.assertEqual(list(filter(None, "abc")), ["a", "b", "c"])
Tim Peters0e57abf2001-05-02 07:39:38 +0000320
321 d = {"one": 1, "two": 2, "three": 3}
Guido van Rossumc1f779c2007-07-03 08:25:58 +0000322 self.assertEqual(list(filter(None, d)), list(d.keys()))
Tim Peters0e57abf2001-05-02 07:39:38 +0000323
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
Georg Brandla18af4e2007-04-21 15:47:16 +0000345 def __next__(self):
Tim Peters0e57abf2001-05-02 07:39:38 +0000346 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))
Guido van Rossumc1f779c2007-07-03 08:25:58 +0000355 self.assertEqual(list(filter(lambda x: not x, seq)), [bFalse]*25)
356 self.assertEqual(list(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):
Guido van Rossumc1f779c2007-07-03 08:25:58 +0000392 self.assertEqual(list(map(lambda x: x+1, SequenceClass(5))),
393 list(range(1, 6)))
Tim Peters4e9afdc2001-05-03 23:54:49 +0000394
395 d = {"one": 1, "two": 2, "three": 3}
Guido van Rossumc1f779c2007-07-03 08:25:58 +0000396 self.assertEqual(list(map(lambda k, d=d: (k, d[k]), d)),
397 list(d.items()))
Brett Cannon0caf6d82007-02-22 04:49:03 +0000398 dkeys = list(d.keys())
Tim Peters4e9afdc2001-05-03 23:54:49 +0000399 expected = [(i < len(d) and dkeys[i] or None,
400 i,
401 i < len(d) and dkeys[i] or None)
Guido van Rossumc1f779c2007-07-03 08:25:58 +0000402 for i in range(3)]
Tim Peters4e9afdc2001-05-03 23:54:49 +0000403
404 f = open(TESTFN, "w")
405 try:
406 for i in range(10):
407 f.write("xy" * i + "\n") # line i has len 2*i+1
408 finally:
409 f.close()
410 f = open(TESTFN, "r")
411 try:
Guido van Rossumc1f779c2007-07-03 08:25:58 +0000412 self.assertEqual(list(map(len, f)), list(range(1, 21, 2)))
Tim Peters4e9afdc2001-05-03 23:54:49 +0000413 finally:
414 f.close()
415 try:
416 unlink(TESTFN)
417 except OSError:
418 pass
419
Tim Peters8572b4f2001-05-06 01:05:02 +0000420 # Test zip()'s use of iterators.
421 def test_builtin_zip(self):
Guido van Rossum801f0d72006-08-24 19:48:10 +0000422 self.assertEqual(list(zip()), [])
423 self.assertEqual(list(zip(*[])), [])
424 self.assertEqual(list(zip(*[(1, 2), 'ab'])), [(1, 'a'), (2, 'b')])
Raymond Hettingereaef6152003-08-02 07:42:57 +0000425
Tim Peters8572b4f2001-05-06 01:05:02 +0000426 self.assertRaises(TypeError, zip, None)
427 self.assertRaises(TypeError, zip, range(10), 42)
428 self.assertRaises(TypeError, zip, range(10), zip)
429
Guido van Rossum801f0d72006-08-24 19:48:10 +0000430 self.assertEqual(list(zip(IteratingSequenceClass(3))),
Tim Peters8572b4f2001-05-06 01:05:02 +0000431 [(0,), (1,), (2,)])
Guido van Rossum801f0d72006-08-24 19:48:10 +0000432 self.assertEqual(list(zip(SequenceClass(3))),
Tim Peters8572b4f2001-05-06 01:05:02 +0000433 [(0,), (1,), (2,)])
434
435 d = {"one": 1, "two": 2, "three": 3}
Brett Cannon0caf6d82007-02-22 04:49:03 +0000436 self.assertEqual(list(d.items()), list(zip(d, d.values())))
Tim Peters8572b4f2001-05-06 01:05:02 +0000437
438 # Generate all ints starting at constructor arg.
439 class IntsFrom:
440 def __init__(self, start):
441 self.i = start
442
443 def __iter__(self):
444 return self
445
Georg Brandla18af4e2007-04-21 15:47:16 +0000446 def __next__(self):
Tim Peters8572b4f2001-05-06 01:05:02 +0000447 i = self.i
448 self.i = i+1
449 return i
450
451 f = open(TESTFN, "w")
452 try:
453 f.write("a\n" "bbb\n" "cc\n")
454 finally:
455 f.close()
456 f = open(TESTFN, "r")
457 try:
Guido van Rossum801f0d72006-08-24 19:48:10 +0000458 self.assertEqual(list(zip(IntsFrom(0), f, IntsFrom(-100))),
Tim Peters8572b4f2001-05-06 01:05:02 +0000459 [(0, "a\n", -100),
460 (1, "bbb\n", -99),
461 (2, "cc\n", -98)])
462 finally:
463 f.close()
464 try:
465 unlink(TESTFN)
466 except OSError:
467 pass
468
Guido van Rossum805365e2007-05-07 22:24:25 +0000469 self.assertEqual(list(zip(range(5))), [(i,) for i in range(5)])
Tim Peters67d687a2002-04-29 21:27:32 +0000470
471 # Classes that lie about their lengths.
472 class NoGuessLen5:
473 def __getitem__(self, i):
474 if i >= 5:
475 raise IndexError
476 return i
477
478 class Guess3Len5(NoGuessLen5):
479 def __len__(self):
480 return 3
481
482 class Guess30Len5(NoGuessLen5):
483 def __len__(self):
484 return 30
485
Guido van Rossum801f0d72006-08-24 19:48:10 +0000486 def lzip(*args):
487 return list(zip(*args))
488
Tim Peters67d687a2002-04-29 21:27:32 +0000489 self.assertEqual(len(Guess3Len5()), 3)
490 self.assertEqual(len(Guess30Len5()), 30)
Guido van Rossum801f0d72006-08-24 19:48:10 +0000491 self.assertEqual(lzip(NoGuessLen5()), lzip(range(5)))
492 self.assertEqual(lzip(Guess3Len5()), lzip(range(5)))
493 self.assertEqual(lzip(Guess30Len5()), lzip(range(5)))
Tim Peters67d687a2002-04-29 21:27:32 +0000494
495 expected = [(i, i) for i in range(5)]
496 for x in NoGuessLen5(), Guess3Len5(), Guess30Len5():
497 for y in NoGuessLen5(), Guess3Len5(), Guess30Len5():
Guido van Rossum801f0d72006-08-24 19:48:10 +0000498 self.assertEqual(lzip(x, y), expected)
Tim Peters67d687a2002-04-29 21:27:32 +0000499
Tim Peters2cfe3682001-05-05 05:36:48 +0000500 def test_unicode_join_endcase(self):
501
502 # This class inserts a Unicode object into its argument's natural
503 # iteration, in the 3rd position.
504 class OhPhooey:
505 def __init__(self, seq):
506 self.it = iter(seq)
507 self.i = 0
508
509 def __iter__(self):
510 return self
511
Georg Brandla18af4e2007-04-21 15:47:16 +0000512 def __next__(self):
Tim Peters2cfe3682001-05-05 05:36:48 +0000513 i = self.i
514 self.i = i+1
515 if i == 2:
Walter Dörwald1f5947b2007-05-22 16:52:54 +0000516 return "fooled you!"
Georg Brandla18af4e2007-04-21 15:47:16 +0000517 return next(self.it)
Tim Peters2cfe3682001-05-05 05:36:48 +0000518
519 f = open(TESTFN, "w")
520 try:
521 f.write("a\n" + "b\n" + "c\n")
522 finally:
523 f.close()
524
525 f = open(TESTFN, "r")
526 # Nasty: string.join(s) can't know whether unicode.join() is needed
527 # until it's seen all of s's elements. But in this case, f's
528 # iterator cannot be restarted. So what we're testing here is
529 # whether string.join() can manage to remember everything it's seen
530 # and pass that on to unicode.join().
531 try:
532 got = " - ".join(OhPhooey(f))
Walter Dörwald5de48bd2007-06-11 21:38:39 +0000533 self.assertEqual(got, "a\n - b\n - fooled you! - c\n")
Tim Peters2cfe3682001-05-05 05:36:48 +0000534 finally:
535 f.close()
536 try:
537 unlink(TESTFN)
538 except OSError:
539 pass
540
Tim Petersde9725f2001-05-05 10:06:17 +0000541 # Test iterators with 'x in y' and 'x not in y'.
542 def test_in_and_not_in(self):
Tim Peterscb8d3682001-05-05 21:05:01 +0000543 for sc5 in IteratingSequenceClass(5), SequenceClass(5):
544 for i in range(5):
Benjamin Peterson577473f2010-01-19 00:09:57 +0000545 self.assertIn(i, sc5)
Tim Peterscb8d3682001-05-05 21:05:01 +0000546 for i in "abc", -1, 5, 42.42, (3, 4), [], {1: 1}, 3-12j, sc5:
Benjamin Peterson577473f2010-01-19 00:09:57 +0000547 self.assertNotIn(i, sc5)
Tim Petersde9725f2001-05-05 10:06:17 +0000548
549 self.assertRaises(TypeError, lambda: 3 in 12)
550 self.assertRaises(TypeError, lambda: 3 not in map)
551
552 d = {"one": 1, "two": 2, "three": 3, 1j: 2j}
553 for k in d:
Benjamin Peterson577473f2010-01-19 00:09:57 +0000554 self.assertIn(k, d)
555 self.assertNotIn(k, d.values())
Tim Petersde9725f2001-05-05 10:06:17 +0000556 for v in d.values():
Benjamin Peterson577473f2010-01-19 00:09:57 +0000557 self.assertIn(v, d.values())
558 self.assertNotIn(v, d)
Guido van Rossumcc2b0162007-02-11 06:12:03 +0000559 for k, v in d.items():
Benjamin Peterson577473f2010-01-19 00:09:57 +0000560 self.assertIn((k, v), d.items())
561 self.assertNotIn((v, k), d.items())
Tim Petersde9725f2001-05-05 10:06:17 +0000562
563 f = open(TESTFN, "w")
564 try:
565 f.write("a\n" "b\n" "c\n")
566 finally:
567 f.close()
568 f = open(TESTFN, "r")
569 try:
570 for chunk in "abc":
571 f.seek(0, 0)
Benjamin Peterson577473f2010-01-19 00:09:57 +0000572 self.assertNotIn(chunk, f)
Tim Petersde9725f2001-05-05 10:06:17 +0000573 f.seek(0, 0)
Benjamin Peterson577473f2010-01-19 00:09:57 +0000574 self.assertIn((chunk + "\n"), f)
Tim Petersde9725f2001-05-05 10:06:17 +0000575 finally:
576 f.close()
577 try:
578 unlink(TESTFN)
579 except OSError:
580 pass
581
Tim Peters75f8e352001-05-05 11:33:43 +0000582 # Test iterators with operator.countOf (PySequence_Count).
583 def test_countOf(self):
584 from operator import countOf
585 self.assertEqual(countOf([1,2,2,3,2,5], 2), 3)
586 self.assertEqual(countOf((1,2,2,3,2,5), 2), 3)
587 self.assertEqual(countOf("122325", "2"), 3)
588 self.assertEqual(countOf("122325", "6"), 0)
589
590 self.assertRaises(TypeError, countOf, 42, 1)
591 self.assertRaises(TypeError, countOf, countOf, countOf)
592
593 d = {"one": 3, "two": 3, "three": 3, 1j: 2j}
594 for k in d:
595 self.assertEqual(countOf(d, k), 1)
Guido van Rossumcc2b0162007-02-11 06:12:03 +0000596 self.assertEqual(countOf(d.values(), 3), 3)
597 self.assertEqual(countOf(d.values(), 2j), 1)
598 self.assertEqual(countOf(d.values(), 1j), 0)
Tim Peters75f8e352001-05-05 11:33:43 +0000599
600 f = open(TESTFN, "w")
601 try:
602 f.write("a\n" "b\n" "c\n" "b\n")
603 finally:
604 f.close()
605 f = open(TESTFN, "r")
606 try:
607 for letter, count in ("a", 1), ("b", 2), ("c", 1), ("d", 0):
608 f.seek(0, 0)
609 self.assertEqual(countOf(f, letter + "\n"), count)
610 finally:
611 f.close()
612 try:
613 unlink(TESTFN)
614 except OSError:
615 pass
616
Tim Peters16a77ad2001-09-08 04:00:12 +0000617 # Test iterators with operator.indexOf (PySequence_Index).
618 def test_indexOf(self):
619 from operator import indexOf
620 self.assertEqual(indexOf([1,2,2,3,2,5], 1), 0)
621 self.assertEqual(indexOf((1,2,2,3,2,5), 2), 1)
622 self.assertEqual(indexOf((1,2,2,3,2,5), 3), 3)
623 self.assertEqual(indexOf((1,2,2,3,2,5), 5), 5)
624 self.assertRaises(ValueError, indexOf, (1,2,2,3,2,5), 0)
625 self.assertRaises(ValueError, indexOf, (1,2,2,3,2,5), 6)
626
627 self.assertEqual(indexOf("122325", "2"), 1)
628 self.assertEqual(indexOf("122325", "5"), 5)
629 self.assertRaises(ValueError, indexOf, "122325", "6")
630
631 self.assertRaises(TypeError, indexOf, 42, 1)
632 self.assertRaises(TypeError, indexOf, indexOf, indexOf)
633
634 f = open(TESTFN, "w")
635 try:
636 f.write("a\n" "b\n" "c\n" "d\n" "e\n")
637 finally:
638 f.close()
639 f = open(TESTFN, "r")
640 try:
641 fiter = iter(f)
642 self.assertEqual(indexOf(fiter, "b\n"), 1)
643 self.assertEqual(indexOf(fiter, "d\n"), 1)
644 self.assertEqual(indexOf(fiter, "e\n"), 0)
645 self.assertRaises(ValueError, indexOf, fiter, "a\n")
646 finally:
647 f.close()
648 try:
649 unlink(TESTFN)
650 except OSError:
651 pass
652
653 iclass = IteratingSequenceClass(3)
654 for i in range(3):
655 self.assertEqual(indexOf(iclass, i), i)
656 self.assertRaises(ValueError, indexOf, iclass, -1)
657
Tim Peters2c9aa5e2001-09-23 04:06:05 +0000658 # Test iterators with file.writelines().
659 def test_writelines(self):
Alex Martelli01c77c62006-08-24 02:58:11 +0000660 f = open(TESTFN, "w")
Tim Peters2c9aa5e2001-09-23 04:06:05 +0000661
662 try:
663 self.assertRaises(TypeError, f.writelines, None)
664 self.assertRaises(TypeError, f.writelines, 42)
Tim Peters527e64f2001-10-04 05:36:56 +0000665
Tim Peters2c9aa5e2001-09-23 04:06:05 +0000666 f.writelines(["1\n", "2\n"])
667 f.writelines(("3\n", "4\n"))
668 f.writelines({'5\n': None})
669 f.writelines({})
670
671 # Try a big chunk too.
672 class Iterator:
673 def __init__(self, start, finish):
674 self.start = start
675 self.finish = finish
676 self.i = self.start
677
Georg Brandla18af4e2007-04-21 15:47:16 +0000678 def __next__(self):
Tim Peters2c9aa5e2001-09-23 04:06:05 +0000679 if self.i >= self.finish:
680 raise StopIteration
681 result = str(self.i) + '\n'
682 self.i += 1
683 return result
684
685 def __iter__(self):
686 return self
687
688 class Whatever:
689 def __init__(self, start, finish):
690 self.start = start
691 self.finish = finish
692
693 def __iter__(self):
694 return Iterator(self.start, self.finish)
Tim Peters527e64f2001-10-04 05:36:56 +0000695
696 f.writelines(Whatever(6, 6+2000))
Tim Peters2c9aa5e2001-09-23 04:06:05 +0000697 f.close()
698
Alex Martelli01c77c62006-08-24 02:58:11 +0000699 f = open(TESTFN)
Tim Peters2c9aa5e2001-09-23 04:06:05 +0000700 expected = [str(i) + "\n" for i in range(1, 2006)]
701 self.assertEqual(list(f), expected)
Tim Peters527e64f2001-10-04 05:36:56 +0000702
Tim Peters2c9aa5e2001-09-23 04:06:05 +0000703 finally:
704 f.close()
705 try:
706 unlink(TESTFN)
707 except OSError:
708 pass
709
710
Tim Petersd6d010b2001-06-21 02:49:55 +0000711 # Test iterators on RHS of unpacking assignments.
712 def test_unpack_iter(self):
713 a, b = 1, 2
714 self.assertEqual((a, b), (1, 2))
715
716 a, b, c = IteratingSequenceClass(3)
717 self.assertEqual((a, b, c), (0, 1, 2))
718
719 try: # too many values
720 a, b = IteratingSequenceClass(3)
721 except ValueError:
722 pass
723 else:
724 self.fail("should have raised ValueError")
725
726 try: # not enough values
727 a, b, c = IteratingSequenceClass(2)
728 except ValueError:
729 pass
730 else:
731 self.fail("should have raised ValueError")
732
733 try: # not iterable
734 a, b, c = len
735 except TypeError:
736 pass
737 else:
738 self.fail("should have raised TypeError")
739
Guido van Rossumcc2b0162007-02-11 06:12:03 +0000740 a, b, c = {1: 42, 2: 42, 3: 42}.values()
Tim Petersd6d010b2001-06-21 02:49:55 +0000741 self.assertEqual((a, b, c), (42, 42, 42))
742
743 f = open(TESTFN, "w")
744 lines = ("a\n", "bb\n", "ccc\n")
745 try:
746 for line in lines:
747 f.write(line)
748 finally:
749 f.close()
750 f = open(TESTFN, "r")
751 try:
752 a, b, c = f
753 self.assertEqual((a, b, c), lines)
754 finally:
755 f.close()
756 try:
757 unlink(TESTFN)
758 except OSError:
759 pass
760
761 (a, b), (c,) = IteratingSequenceClass(2), {42: 24}
762 self.assertEqual((a, b, c), (0, 1, 42))
763
Guido van Rossumbb8f59a2001-12-03 19:33:25 +0000764
Benjamin Peterson945c5792010-06-22 20:34:34 +0000765 @cpython_only
766 def test_ref_counting_behavior(self):
Guido van Rossumbb8f59a2001-12-03 19:33:25 +0000767 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
Amaury Forgeot d'Arcf343e012009-01-12 23:58:21 +0000864 def test_3720(self):
865 # Avoid a crash, when an iterator deletes its next() method.
866 class BadIterator(object):
867 def __iter__(self):
868 return self
869 def __next__(self):
870 del BadIterator.__next__
871 return 1
872
873 try:
874 for i in BadIterator() :
875 pass
876 except TypeError:
877 pass
878
Guido van Rossum674eae62002-07-16 21:48:11 +0000879
Fred Drake2e2be372001-09-20 21:33:42 +0000880def test_main():
881 run_unittest(TestCase)
882
883
884if __name__ == "__main__":
885 test_main()