blob: b2f3e652325f38aa29831814c5896039f24c73bf [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
Kristján Valur Jónsson31668b82012-04-03 10:49:41 +00005import pickle
6import collections.abc
Guido van Rossum8b48cf92001-04-21 13:33:54 +00007
8# Test result of triple loop (too big to inline)
9TRIPLETS = [(0, 0, 0), (0, 0, 1), (0, 0, 2),
10 (0, 1, 0), (0, 1, 1), (0, 1, 2),
11 (0, 2, 0), (0, 2, 1), (0, 2, 2),
12
13 (1, 0, 0), (1, 0, 1), (1, 0, 2),
14 (1, 1, 0), (1, 1, 1), (1, 1, 2),
15 (1, 2, 0), (1, 2, 1), (1, 2, 2),
16
17 (2, 0, 0), (2, 0, 1), (2, 0, 2),
18 (2, 1, 0), (2, 1, 1), (2, 1, 2),
19 (2, 2, 0), (2, 2, 1), (2, 2, 2)]
20
21# Helper classes
22
23class BasicIterClass:
24 def __init__(self, n):
25 self.n = n
26 self.i = 0
Georg Brandla18af4e2007-04-21 15:47:16 +000027 def __next__(self):
Guido van Rossum8b48cf92001-04-21 13:33:54 +000028 res = self.i
29 if res >= self.n:
30 raise StopIteration
31 self.i = res + 1
32 return res
Kristján Valur Jónsson31668b82012-04-03 10:49:41 +000033 def __iter__(self):
34 return self
Guido van Rossum8b48cf92001-04-21 13:33:54 +000035
36class IteratingSequenceClass:
37 def __init__(self, n):
38 self.n = n
39 def __iter__(self):
40 return BasicIterClass(self.n)
41
42class SequenceClass:
43 def __init__(self, n):
44 self.n = n
45 def __getitem__(self, i):
46 if 0 <= i < self.n:
47 return i
48 else:
49 raise IndexError
50
51# Main test suite
52
53class TestCase(unittest.TestCase):
54
55 # Helper to check that an iterator returns a given sequence
Kristján Valur Jónsson31668b82012-04-03 10:49:41 +000056 def check_iterator(self, it, seq, pickle=True):
57 if pickle:
58 self.check_pickle(it, seq)
Guido van Rossum8b48cf92001-04-21 13:33:54 +000059 res = []
60 while 1:
61 try:
Georg Brandla18af4e2007-04-21 15:47:16 +000062 val = next(it)
Guido van Rossum8b48cf92001-04-21 13:33:54 +000063 except StopIteration:
64 break
65 res.append(val)
66 self.assertEqual(res, seq)
67
68 # Helper to check that a for loop generates a given sequence
Kristján Valur Jónsson31668b82012-04-03 10:49:41 +000069 def check_for_loop(self, expr, seq, pickle=True):
70 if pickle:
71 self.check_pickle(iter(expr), seq)
Guido van Rossum8b48cf92001-04-21 13:33:54 +000072 res = []
73 for val in expr:
74 res.append(val)
75 self.assertEqual(res, seq)
76
Kristján Valur Jónsson31668b82012-04-03 10:49:41 +000077 # Helper to check picklability
78 def check_pickle(self, itorg, seq):
79 d = pickle.dumps(itorg)
80 it = pickle.loads(d)
81 # Cannot assert type equality because dict iterators unpickle as list
82 # iterators.
83 # self.assertEqual(type(itorg), type(it))
84 self.assertTrue(isinstance(it, collections.abc.Iterator))
85 self.assertEqual(list(it), seq)
86
87 it = pickle.loads(d)
88 try:
89 next(it)
90 except StopIteration:
91 return
92 d = pickle.dumps(it)
93 it = pickle.loads(d)
94 self.assertEqual(list(it), seq[1:])
95
Guido van Rossum8b48cf92001-04-21 13:33:54 +000096 # Test basic use of iter() function
97 def test_iter_basic(self):
Guido van Rossum805365e2007-05-07 22:24:25 +000098 self.check_iterator(iter(range(10)), list(range(10)))
Guido van Rossum8b48cf92001-04-21 13:33:54 +000099
100 # Test that iter(iter(x)) is the same as iter(x)
101 def test_iter_idempotency(self):
Guido van Rossum805365e2007-05-07 22:24:25 +0000102 seq = list(range(10))
Guido van Rossum8b48cf92001-04-21 13:33:54 +0000103 it = iter(seq)
104 it2 = iter(it)
Benjamin Petersonc9c0f202009-06-30 23:06:06 +0000105 self.assertTrue(it is it2)
Guido van Rossum8b48cf92001-04-21 13:33:54 +0000106
107 # Test that for loops over iterators work
108 def test_iter_for_loop(self):
Guido van Rossum805365e2007-05-07 22:24:25 +0000109 self.check_for_loop(iter(range(10)), list(range(10)))
Guido van Rossum8b48cf92001-04-21 13:33:54 +0000110
111 # Test several independent iterators over the same list
112 def test_iter_independence(self):
113 seq = range(3)
114 res = []
115 for i in iter(seq):
116 for j in iter(seq):
117 for k in iter(seq):
118 res.append((i, j, k))
119 self.assertEqual(res, TRIPLETS)
120
121 # Test triple list comprehension using iterators
122 def test_nested_comprehensions_iter(self):
123 seq = range(3)
124 res = [(i, j, k)
125 for i in iter(seq) for j in iter(seq) for k in iter(seq)]
126 self.assertEqual(res, TRIPLETS)
127
128 # Test triple list comprehension without iterators
129 def test_nested_comprehensions_for(self):
130 seq = range(3)
131 res = [(i, j, k) for i in seq for j in seq for k in seq]
132 self.assertEqual(res, TRIPLETS)
133
134 # Test a class with __iter__ in a for loop
135 def test_iter_class_for(self):
Guido van Rossum805365e2007-05-07 22:24:25 +0000136 self.check_for_loop(IteratingSequenceClass(10), list(range(10)))
Guido van Rossum8b48cf92001-04-21 13:33:54 +0000137
138 # Test a class with __iter__ with explicit iter()
139 def test_iter_class_iter(self):
Guido van Rossum805365e2007-05-07 22:24:25 +0000140 self.check_iterator(iter(IteratingSequenceClass(10)), list(range(10)))
Guido van Rossum8b48cf92001-04-21 13:33:54 +0000141
142 # Test for loop on a sequence class without __iter__
143 def test_seq_class_for(self):
Guido van Rossum805365e2007-05-07 22:24:25 +0000144 self.check_for_loop(SequenceClass(10), list(range(10)))
Guido van Rossum8b48cf92001-04-21 13:33:54 +0000145
146 # Test iter() on a sequence class without __iter__
147 def test_seq_class_iter(self):
Guido van Rossum805365e2007-05-07 22:24:25 +0000148 self.check_iterator(iter(SequenceClass(10)), list(range(10)))
Guido van Rossum8b48cf92001-04-21 13:33:54 +0000149
Amaury Forgeot d'Arcf343e012009-01-12 23:58:21 +0000150 # Test a new_style class with __iter__ but no next() method
151 def test_new_style_iter_class(self):
152 class IterClass(object):
153 def __iter__(self):
154 return self
155 self.assertRaises(TypeError, iter, IterClass())
156
Guido van Rossum8b48cf92001-04-21 13:33:54 +0000157 # Test two-argument iter() with callable instance
158 def test_iter_callable(self):
159 class C:
160 def __init__(self):
161 self.i = 0
162 def __call__(self):
163 i = self.i
164 self.i = i + 1
165 if i > 100:
166 raise IndexError # Emergency stop
167 return i
Kristján Valur Jónsson31668b82012-04-03 10:49:41 +0000168 self.check_iterator(iter(C(), 10), list(range(10)), pickle=False)
Guido van Rossum8b48cf92001-04-21 13:33:54 +0000169
170 # Test two-argument iter() with function
171 def test_iter_function(self):
172 def spam(state=[0]):
173 i = state[0]
174 state[0] = i+1
175 return i
Kristján Valur Jónsson31668b82012-04-03 10:49:41 +0000176 self.check_iterator(iter(spam, 10), list(range(10)), pickle=False)
Guido van Rossum8b48cf92001-04-21 13:33:54 +0000177
178 # Test two-argument iter() with function that raises StopIteration
179 def test_iter_function_stop(self):
180 def spam(state=[0]):
181 i = state[0]
182 if i == 10:
183 raise StopIteration
184 state[0] = i+1
185 return i
Kristján Valur Jónsson31668b82012-04-03 10:49:41 +0000186 self.check_iterator(iter(spam, 20), list(range(10)), pickle=False)
Guido van Rossum8b48cf92001-04-21 13:33:54 +0000187
188 # Test exception propagation through function iterator
189 def test_exception_function(self):
190 def spam(state=[0]):
191 i = state[0]
192 state[0] = i+1
193 if i == 10:
194 raise RuntimeError
195 return i
196 res = []
197 try:
198 for x in iter(spam, 20):
199 res.append(x)
200 except RuntimeError:
Guido van Rossum805365e2007-05-07 22:24:25 +0000201 self.assertEqual(res, list(range(10)))
Guido van Rossum8b48cf92001-04-21 13:33:54 +0000202 else:
203 self.fail("should have raised RuntimeError")
204
205 # Test exception propagation through sequence iterator
206 def test_exception_sequence(self):
207 class MySequenceClass(SequenceClass):
208 def __getitem__(self, i):
209 if i == 10:
210 raise RuntimeError
211 return SequenceClass.__getitem__(self, i)
212 res = []
213 try:
214 for x in MySequenceClass(20):
215 res.append(x)
216 except RuntimeError:
Guido van Rossum805365e2007-05-07 22:24:25 +0000217 self.assertEqual(res, list(range(10)))
Guido van Rossum8b48cf92001-04-21 13:33:54 +0000218 else:
219 self.fail("should have raised RuntimeError")
220
221 # Test for StopIteration from __getitem__
222 def test_stop_sequence(self):
223 class MySequenceClass(SequenceClass):
224 def __getitem__(self, i):
225 if i == 10:
226 raise StopIteration
227 return SequenceClass.__getitem__(self, i)
Kristján Valur Jónsson31668b82012-04-03 10:49:41 +0000228 self.check_for_loop(MySequenceClass(20), list(range(10)), pickle=False)
Guido van Rossum8b48cf92001-04-21 13:33:54 +0000229
230 # Test a big range
231 def test_iter_big_range(self):
Guido van Rossum805365e2007-05-07 22:24:25 +0000232 self.check_for_loop(iter(range(10000)), list(range(10000)))
Guido van Rossum8b48cf92001-04-21 13:33:54 +0000233
234 # Test an empty list
235 def test_iter_empty(self):
236 self.check_for_loop(iter([]), [])
237
238 # Test a tuple
239 def test_iter_tuple(self):
Guido van Rossum805365e2007-05-07 22:24:25 +0000240 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 +0000241
Guido van Rossum805365e2007-05-07 22:24:25 +0000242 # Test a range
243 def test_iter_range(self):
244 self.check_for_loop(iter(range(10)), list(range(10)))
Guido van Rossum8b48cf92001-04-21 13:33:54 +0000245
246 # Test a string
247 def test_iter_string(self):
248 self.check_for_loop(iter("abcde"), ["a", "b", "c", "d", "e"])
249
Guido van Rossum8b48cf92001-04-21 13:33:54 +0000250 # Test a directory
251 def test_iter_dict(self):
252 dict = {}
253 for i in range(10):
254 dict[i] = None
Brett Cannon0caf6d82007-02-22 04:49:03 +0000255 self.check_for_loop(dict, list(dict.keys()))
Guido van Rossum8b48cf92001-04-21 13:33:54 +0000256
257 # Test a file
258 def test_iter_file(self):
259 f = open(TESTFN, "w")
260 try:
261 for i in range(5):
262 f.write("%d\n" % i)
263 finally:
264 f.close()
265 f = open(TESTFN, "r")
266 try:
Kristján Valur Jónsson31668b82012-04-03 10:49:41 +0000267 self.check_for_loop(f, ["0\n", "1\n", "2\n", "3\n", "4\n"], pickle=False)
268 self.check_for_loop(f, [], pickle=False)
Guido van Rossum8b48cf92001-04-21 13:33:54 +0000269 finally:
270 f.close()
271 try:
272 unlink(TESTFN)
273 except OSError:
274 pass
275
Tim Petersf553f892001-05-01 20:45:31 +0000276 # Test list()'s use of iterators.
277 def test_builtin_list(self):
Guido van Rossum805365e2007-05-07 22:24:25 +0000278 self.assertEqual(list(SequenceClass(5)), list(range(5)))
Tim Petersf553f892001-05-01 20:45:31 +0000279 self.assertEqual(list(SequenceClass(0)), [])
280 self.assertEqual(list(()), [])
Tim Petersf553f892001-05-01 20:45:31 +0000281
282 d = {"one": 1, "two": 2, "three": 3}
Brett Cannon0caf6d82007-02-22 04:49:03 +0000283 self.assertEqual(list(d), list(d.keys()))
Tim Petersf553f892001-05-01 20:45:31 +0000284
285 self.assertRaises(TypeError, list, list)
286 self.assertRaises(TypeError, list, 42)
287
288 f = open(TESTFN, "w")
289 try:
290 for i in range(5):
291 f.write("%d\n" % i)
292 finally:
293 f.close()
294 f = open(TESTFN, "r")
295 try:
296 self.assertEqual(list(f), ["0\n", "1\n", "2\n", "3\n", "4\n"])
297 f.seek(0, 0)
Guido van Rossum8ee52432002-08-06 17:14:04 +0000298 self.assertEqual(list(f),
Tim Petersf553f892001-05-01 20:45:31 +0000299 ["0\n", "1\n", "2\n", "3\n", "4\n"])
300 finally:
301 f.close()
302 try:
303 unlink(TESTFN)
304 except OSError:
305 pass
306
Tim Peters6912d4d2001-05-05 03:56:37 +0000307 # Test tuples()'s use of iterators.
308 def test_builtin_tuple(self):
309 self.assertEqual(tuple(SequenceClass(5)), (0, 1, 2, 3, 4))
310 self.assertEqual(tuple(SequenceClass(0)), ())
311 self.assertEqual(tuple([]), ())
312 self.assertEqual(tuple(()), ())
313 self.assertEqual(tuple("abc"), ("a", "b", "c"))
314
315 d = {"one": 1, "two": 2, "three": 3}
316 self.assertEqual(tuple(d), tuple(d.keys()))
317
318 self.assertRaises(TypeError, tuple, list)
319 self.assertRaises(TypeError, tuple, 42)
320
321 f = open(TESTFN, "w")
322 try:
323 for i in range(5):
324 f.write("%d\n" % i)
325 finally:
326 f.close()
327 f = open(TESTFN, "r")
328 try:
329 self.assertEqual(tuple(f), ("0\n", "1\n", "2\n", "3\n", "4\n"))
330 f.seek(0, 0)
Guido van Rossum8ee52432002-08-06 17:14:04 +0000331 self.assertEqual(tuple(f),
Tim Peters6912d4d2001-05-05 03:56:37 +0000332 ("0\n", "1\n", "2\n", "3\n", "4\n"))
333 finally:
334 f.close()
335 try:
336 unlink(TESTFN)
337 except OSError:
338 pass
339
Tim Peters0e57abf2001-05-02 07:39:38 +0000340 # Test filter()'s use of iterators.
341 def test_builtin_filter(self):
Guido van Rossumc1f779c2007-07-03 08:25:58 +0000342 self.assertEqual(list(filter(None, SequenceClass(5))),
343 list(range(1, 5)))
344 self.assertEqual(list(filter(None, SequenceClass(0))), [])
345 self.assertEqual(list(filter(None, ())), [])
346 self.assertEqual(list(filter(None, "abc")), ["a", "b", "c"])
Tim Peters0e57abf2001-05-02 07:39:38 +0000347
348 d = {"one": 1, "two": 2, "three": 3}
Guido van Rossumc1f779c2007-07-03 08:25:58 +0000349 self.assertEqual(list(filter(None, d)), list(d.keys()))
Tim Peters0e57abf2001-05-02 07:39:38 +0000350
351 self.assertRaises(TypeError, filter, None, list)
352 self.assertRaises(TypeError, filter, None, 42)
353
354 class Boolean:
355 def __init__(self, truth):
356 self.truth = truth
Jack Diederich4dafcc42006-11-28 19:15:13 +0000357 def __bool__(self):
Tim Peters0e57abf2001-05-02 07:39:38 +0000358 return self.truth
Jack Diederich4dafcc42006-11-28 19:15:13 +0000359 bTrue = Boolean(True)
360 bFalse = Boolean(False)
Tim Peters0e57abf2001-05-02 07:39:38 +0000361
362 class Seq:
363 def __init__(self, *args):
364 self.vals = args
365 def __iter__(self):
366 class SeqIter:
367 def __init__(self, vals):
368 self.vals = vals
369 self.i = 0
370 def __iter__(self):
371 return self
Georg Brandla18af4e2007-04-21 15:47:16 +0000372 def __next__(self):
Tim Peters0e57abf2001-05-02 07:39:38 +0000373 i = self.i
374 self.i = i + 1
375 if i < len(self.vals):
376 return self.vals[i]
377 else:
378 raise StopIteration
379 return SeqIter(self.vals)
380
Tim Peterscae330e2002-12-23 16:50:58 +0000381 seq = Seq(*([bTrue, bFalse] * 25))
Guido van Rossumc1f779c2007-07-03 08:25:58 +0000382 self.assertEqual(list(filter(lambda x: not x, seq)), [bFalse]*25)
383 self.assertEqual(list(filter(lambda x: not x, iter(seq))), [bFalse]*25)
Tim Peters0e57abf2001-05-02 07:39:38 +0000384
Tim Petersc3074532001-05-03 07:00:32 +0000385 # Test max() and min()'s use of iterators.
386 def test_builtin_max_min(self):
387 self.assertEqual(max(SequenceClass(5)), 4)
388 self.assertEqual(min(SequenceClass(5)), 0)
389 self.assertEqual(max(8, -1), 8)
390 self.assertEqual(min(8, -1), -1)
391
392 d = {"one": 1, "two": 2, "three": 3}
393 self.assertEqual(max(d), "two")
394 self.assertEqual(min(d), "one")
Guido van Rossumcc2b0162007-02-11 06:12:03 +0000395 self.assertEqual(max(d.values()), 3)
396 self.assertEqual(min(iter(d.values())), 1)
Tim Petersc3074532001-05-03 07:00:32 +0000397
Tim Petersc3074532001-05-03 07:00:32 +0000398 f = open(TESTFN, "w")
399 try:
400 f.write("medium line\n")
401 f.write("xtra large line\n")
402 f.write("itty-bitty line\n")
403 finally:
404 f.close()
405 f = open(TESTFN, "r")
406 try:
407 self.assertEqual(min(f), "itty-bitty line\n")
408 f.seek(0, 0)
409 self.assertEqual(max(f), "xtra large line\n")
410 finally:
411 f.close()
412 try:
413 unlink(TESTFN)
414 except OSError:
415 pass
416
Tim Peters4e9afdc2001-05-03 23:54:49 +0000417 # Test map()'s use of iterators.
418 def test_builtin_map(self):
Guido van Rossumc1f779c2007-07-03 08:25:58 +0000419 self.assertEqual(list(map(lambda x: x+1, SequenceClass(5))),
420 list(range(1, 6)))
Tim Peters4e9afdc2001-05-03 23:54:49 +0000421
422 d = {"one": 1, "two": 2, "three": 3}
Guido van Rossumc1f779c2007-07-03 08:25:58 +0000423 self.assertEqual(list(map(lambda k, d=d: (k, d[k]), d)),
424 list(d.items()))
Brett Cannon0caf6d82007-02-22 04:49:03 +0000425 dkeys = list(d.keys())
Tim Peters4e9afdc2001-05-03 23:54:49 +0000426 expected = [(i < len(d) and dkeys[i] or None,
427 i,
428 i < len(d) and dkeys[i] or None)
Guido van Rossumc1f779c2007-07-03 08:25:58 +0000429 for i in range(3)]
Tim Peters4e9afdc2001-05-03 23:54:49 +0000430
431 f = open(TESTFN, "w")
432 try:
433 for i in range(10):
434 f.write("xy" * i + "\n") # line i has len 2*i+1
435 finally:
436 f.close()
437 f = open(TESTFN, "r")
438 try:
Guido van Rossumc1f779c2007-07-03 08:25:58 +0000439 self.assertEqual(list(map(len, f)), list(range(1, 21, 2)))
Tim Peters4e9afdc2001-05-03 23:54:49 +0000440 finally:
441 f.close()
442 try:
443 unlink(TESTFN)
444 except OSError:
445 pass
446
Tim Peters8572b4f2001-05-06 01:05:02 +0000447 # Test zip()'s use of iterators.
448 def test_builtin_zip(self):
Guido van Rossum801f0d72006-08-24 19:48:10 +0000449 self.assertEqual(list(zip()), [])
450 self.assertEqual(list(zip(*[])), [])
451 self.assertEqual(list(zip(*[(1, 2), 'ab'])), [(1, 'a'), (2, 'b')])
Raymond Hettingereaef6152003-08-02 07:42:57 +0000452
Tim Peters8572b4f2001-05-06 01:05:02 +0000453 self.assertRaises(TypeError, zip, None)
454 self.assertRaises(TypeError, zip, range(10), 42)
455 self.assertRaises(TypeError, zip, range(10), zip)
456
Guido van Rossum801f0d72006-08-24 19:48:10 +0000457 self.assertEqual(list(zip(IteratingSequenceClass(3))),
Tim Peters8572b4f2001-05-06 01:05:02 +0000458 [(0,), (1,), (2,)])
Guido van Rossum801f0d72006-08-24 19:48:10 +0000459 self.assertEqual(list(zip(SequenceClass(3))),
Tim Peters8572b4f2001-05-06 01:05:02 +0000460 [(0,), (1,), (2,)])
461
462 d = {"one": 1, "two": 2, "three": 3}
Brett Cannon0caf6d82007-02-22 04:49:03 +0000463 self.assertEqual(list(d.items()), list(zip(d, d.values())))
Tim Peters8572b4f2001-05-06 01:05:02 +0000464
465 # Generate all ints starting at constructor arg.
466 class IntsFrom:
467 def __init__(self, start):
468 self.i = start
469
470 def __iter__(self):
471 return self
472
Georg Brandla18af4e2007-04-21 15:47:16 +0000473 def __next__(self):
Tim Peters8572b4f2001-05-06 01:05:02 +0000474 i = self.i
475 self.i = i+1
476 return i
477
478 f = open(TESTFN, "w")
479 try:
480 f.write("a\n" "bbb\n" "cc\n")
481 finally:
482 f.close()
483 f = open(TESTFN, "r")
484 try:
Guido van Rossum801f0d72006-08-24 19:48:10 +0000485 self.assertEqual(list(zip(IntsFrom(0), f, IntsFrom(-100))),
Tim Peters8572b4f2001-05-06 01:05:02 +0000486 [(0, "a\n", -100),
487 (1, "bbb\n", -99),
488 (2, "cc\n", -98)])
489 finally:
490 f.close()
491 try:
492 unlink(TESTFN)
493 except OSError:
494 pass
495
Guido van Rossum805365e2007-05-07 22:24:25 +0000496 self.assertEqual(list(zip(range(5))), [(i,) for i in range(5)])
Tim Peters67d687a2002-04-29 21:27:32 +0000497
498 # Classes that lie about their lengths.
499 class NoGuessLen5:
500 def __getitem__(self, i):
501 if i >= 5:
502 raise IndexError
503 return i
504
505 class Guess3Len5(NoGuessLen5):
506 def __len__(self):
507 return 3
508
509 class Guess30Len5(NoGuessLen5):
510 def __len__(self):
511 return 30
512
Guido van Rossum801f0d72006-08-24 19:48:10 +0000513 def lzip(*args):
514 return list(zip(*args))
515
Tim Peters67d687a2002-04-29 21:27:32 +0000516 self.assertEqual(len(Guess3Len5()), 3)
517 self.assertEqual(len(Guess30Len5()), 30)
Guido van Rossum801f0d72006-08-24 19:48:10 +0000518 self.assertEqual(lzip(NoGuessLen5()), lzip(range(5)))
519 self.assertEqual(lzip(Guess3Len5()), lzip(range(5)))
520 self.assertEqual(lzip(Guess30Len5()), lzip(range(5)))
Tim Peters67d687a2002-04-29 21:27:32 +0000521
522 expected = [(i, i) for i in range(5)]
523 for x in NoGuessLen5(), Guess3Len5(), Guess30Len5():
524 for y in NoGuessLen5(), Guess3Len5(), Guess30Len5():
Guido van Rossum801f0d72006-08-24 19:48:10 +0000525 self.assertEqual(lzip(x, y), expected)
Tim Peters67d687a2002-04-29 21:27:32 +0000526
Tim Peters2cfe3682001-05-05 05:36:48 +0000527 def test_unicode_join_endcase(self):
528
529 # This class inserts a Unicode object into its argument's natural
530 # iteration, in the 3rd position.
531 class OhPhooey:
532 def __init__(self, seq):
533 self.it = iter(seq)
534 self.i = 0
535
536 def __iter__(self):
537 return self
538
Georg Brandla18af4e2007-04-21 15:47:16 +0000539 def __next__(self):
Tim Peters2cfe3682001-05-05 05:36:48 +0000540 i = self.i
541 self.i = i+1
542 if i == 2:
Walter Dörwald1f5947b2007-05-22 16:52:54 +0000543 return "fooled you!"
Georg Brandla18af4e2007-04-21 15:47:16 +0000544 return next(self.it)
Tim Peters2cfe3682001-05-05 05:36:48 +0000545
546 f = open(TESTFN, "w")
547 try:
548 f.write("a\n" + "b\n" + "c\n")
549 finally:
550 f.close()
551
552 f = open(TESTFN, "r")
553 # Nasty: string.join(s) can't know whether unicode.join() is needed
554 # until it's seen all of s's elements. But in this case, f's
555 # iterator cannot be restarted. So what we're testing here is
556 # whether string.join() can manage to remember everything it's seen
557 # and pass that on to unicode.join().
558 try:
559 got = " - ".join(OhPhooey(f))
Walter Dörwald5de48bd2007-06-11 21:38:39 +0000560 self.assertEqual(got, "a\n - b\n - fooled you! - c\n")
Tim Peters2cfe3682001-05-05 05:36:48 +0000561 finally:
562 f.close()
563 try:
564 unlink(TESTFN)
565 except OSError:
566 pass
567
Tim Petersde9725f2001-05-05 10:06:17 +0000568 # Test iterators with 'x in y' and 'x not in y'.
569 def test_in_and_not_in(self):
Tim Peterscb8d3682001-05-05 21:05:01 +0000570 for sc5 in IteratingSequenceClass(5), SequenceClass(5):
571 for i in range(5):
Benjamin Peterson577473f2010-01-19 00:09:57 +0000572 self.assertIn(i, sc5)
Tim Peterscb8d3682001-05-05 21:05:01 +0000573 for i in "abc", -1, 5, 42.42, (3, 4), [], {1: 1}, 3-12j, sc5:
Benjamin Peterson577473f2010-01-19 00:09:57 +0000574 self.assertNotIn(i, sc5)
Tim Petersde9725f2001-05-05 10:06:17 +0000575
576 self.assertRaises(TypeError, lambda: 3 in 12)
577 self.assertRaises(TypeError, lambda: 3 not in map)
578
579 d = {"one": 1, "two": 2, "three": 3, 1j: 2j}
580 for k in d:
Benjamin Peterson577473f2010-01-19 00:09:57 +0000581 self.assertIn(k, d)
582 self.assertNotIn(k, d.values())
Tim Petersde9725f2001-05-05 10:06:17 +0000583 for v in d.values():
Benjamin Peterson577473f2010-01-19 00:09:57 +0000584 self.assertIn(v, d.values())
585 self.assertNotIn(v, d)
Guido van Rossumcc2b0162007-02-11 06:12:03 +0000586 for k, v in d.items():
Benjamin Peterson577473f2010-01-19 00:09:57 +0000587 self.assertIn((k, v), d.items())
588 self.assertNotIn((v, k), d.items())
Tim Petersde9725f2001-05-05 10:06:17 +0000589
590 f = open(TESTFN, "w")
591 try:
592 f.write("a\n" "b\n" "c\n")
593 finally:
594 f.close()
595 f = open(TESTFN, "r")
596 try:
597 for chunk in "abc":
598 f.seek(0, 0)
Benjamin Peterson577473f2010-01-19 00:09:57 +0000599 self.assertNotIn(chunk, f)
Tim Petersde9725f2001-05-05 10:06:17 +0000600 f.seek(0, 0)
Benjamin Peterson577473f2010-01-19 00:09:57 +0000601 self.assertIn((chunk + "\n"), f)
Tim Petersde9725f2001-05-05 10:06:17 +0000602 finally:
603 f.close()
604 try:
605 unlink(TESTFN)
606 except OSError:
607 pass
608
Tim Peters75f8e352001-05-05 11:33:43 +0000609 # Test iterators with operator.countOf (PySequence_Count).
610 def test_countOf(self):
611 from operator import countOf
612 self.assertEqual(countOf([1,2,2,3,2,5], 2), 3)
613 self.assertEqual(countOf((1,2,2,3,2,5), 2), 3)
614 self.assertEqual(countOf("122325", "2"), 3)
615 self.assertEqual(countOf("122325", "6"), 0)
616
617 self.assertRaises(TypeError, countOf, 42, 1)
618 self.assertRaises(TypeError, countOf, countOf, countOf)
619
620 d = {"one": 3, "two": 3, "three": 3, 1j: 2j}
621 for k in d:
622 self.assertEqual(countOf(d, k), 1)
Guido van Rossumcc2b0162007-02-11 06:12:03 +0000623 self.assertEqual(countOf(d.values(), 3), 3)
624 self.assertEqual(countOf(d.values(), 2j), 1)
625 self.assertEqual(countOf(d.values(), 1j), 0)
Tim Peters75f8e352001-05-05 11:33:43 +0000626
627 f = open(TESTFN, "w")
628 try:
629 f.write("a\n" "b\n" "c\n" "b\n")
630 finally:
631 f.close()
632 f = open(TESTFN, "r")
633 try:
634 for letter, count in ("a", 1), ("b", 2), ("c", 1), ("d", 0):
635 f.seek(0, 0)
636 self.assertEqual(countOf(f, letter + "\n"), count)
637 finally:
638 f.close()
639 try:
640 unlink(TESTFN)
641 except OSError:
642 pass
643
Tim Peters16a77ad2001-09-08 04:00:12 +0000644 # Test iterators with operator.indexOf (PySequence_Index).
645 def test_indexOf(self):
646 from operator import indexOf
647 self.assertEqual(indexOf([1,2,2,3,2,5], 1), 0)
648 self.assertEqual(indexOf((1,2,2,3,2,5), 2), 1)
649 self.assertEqual(indexOf((1,2,2,3,2,5), 3), 3)
650 self.assertEqual(indexOf((1,2,2,3,2,5), 5), 5)
651 self.assertRaises(ValueError, indexOf, (1,2,2,3,2,5), 0)
652 self.assertRaises(ValueError, indexOf, (1,2,2,3,2,5), 6)
653
654 self.assertEqual(indexOf("122325", "2"), 1)
655 self.assertEqual(indexOf("122325", "5"), 5)
656 self.assertRaises(ValueError, indexOf, "122325", "6")
657
658 self.assertRaises(TypeError, indexOf, 42, 1)
659 self.assertRaises(TypeError, indexOf, indexOf, indexOf)
660
661 f = open(TESTFN, "w")
662 try:
663 f.write("a\n" "b\n" "c\n" "d\n" "e\n")
664 finally:
665 f.close()
666 f = open(TESTFN, "r")
667 try:
668 fiter = iter(f)
669 self.assertEqual(indexOf(fiter, "b\n"), 1)
670 self.assertEqual(indexOf(fiter, "d\n"), 1)
671 self.assertEqual(indexOf(fiter, "e\n"), 0)
672 self.assertRaises(ValueError, indexOf, fiter, "a\n")
673 finally:
674 f.close()
675 try:
676 unlink(TESTFN)
677 except OSError:
678 pass
679
680 iclass = IteratingSequenceClass(3)
681 for i in range(3):
682 self.assertEqual(indexOf(iclass, i), i)
683 self.assertRaises(ValueError, indexOf, iclass, -1)
684
Tim Peters2c9aa5e2001-09-23 04:06:05 +0000685 # Test iterators with file.writelines().
686 def test_writelines(self):
Alex Martelli01c77c62006-08-24 02:58:11 +0000687 f = open(TESTFN, "w")
Tim Peters2c9aa5e2001-09-23 04:06:05 +0000688
689 try:
690 self.assertRaises(TypeError, f.writelines, None)
691 self.assertRaises(TypeError, f.writelines, 42)
Tim Peters527e64f2001-10-04 05:36:56 +0000692
Tim Peters2c9aa5e2001-09-23 04:06:05 +0000693 f.writelines(["1\n", "2\n"])
694 f.writelines(("3\n", "4\n"))
695 f.writelines({'5\n': None})
696 f.writelines({})
697
698 # Try a big chunk too.
699 class Iterator:
700 def __init__(self, start, finish):
701 self.start = start
702 self.finish = finish
703 self.i = self.start
704
Georg Brandla18af4e2007-04-21 15:47:16 +0000705 def __next__(self):
Tim Peters2c9aa5e2001-09-23 04:06:05 +0000706 if self.i >= self.finish:
707 raise StopIteration
708 result = str(self.i) + '\n'
709 self.i += 1
710 return result
711
712 def __iter__(self):
713 return self
714
715 class Whatever:
716 def __init__(self, start, finish):
717 self.start = start
718 self.finish = finish
719
720 def __iter__(self):
721 return Iterator(self.start, self.finish)
Tim Peters527e64f2001-10-04 05:36:56 +0000722
723 f.writelines(Whatever(6, 6+2000))
Tim Peters2c9aa5e2001-09-23 04:06:05 +0000724 f.close()
725
Alex Martelli01c77c62006-08-24 02:58:11 +0000726 f = open(TESTFN)
Tim Peters2c9aa5e2001-09-23 04:06:05 +0000727 expected = [str(i) + "\n" for i in range(1, 2006)]
728 self.assertEqual(list(f), expected)
Tim Peters527e64f2001-10-04 05:36:56 +0000729
Tim Peters2c9aa5e2001-09-23 04:06:05 +0000730 finally:
731 f.close()
732 try:
733 unlink(TESTFN)
734 except OSError:
735 pass
736
737
Tim Petersd6d010b2001-06-21 02:49:55 +0000738 # Test iterators on RHS of unpacking assignments.
739 def test_unpack_iter(self):
740 a, b = 1, 2
741 self.assertEqual((a, b), (1, 2))
742
743 a, b, c = IteratingSequenceClass(3)
744 self.assertEqual((a, b, c), (0, 1, 2))
745
746 try: # too many values
747 a, b = IteratingSequenceClass(3)
748 except ValueError:
749 pass
750 else:
751 self.fail("should have raised ValueError")
752
753 try: # not enough values
754 a, b, c = IteratingSequenceClass(2)
755 except ValueError:
756 pass
757 else:
758 self.fail("should have raised ValueError")
759
760 try: # not iterable
761 a, b, c = len
762 except TypeError:
763 pass
764 else:
765 self.fail("should have raised TypeError")
766
Guido van Rossumcc2b0162007-02-11 06:12:03 +0000767 a, b, c = {1: 42, 2: 42, 3: 42}.values()
Tim Petersd6d010b2001-06-21 02:49:55 +0000768 self.assertEqual((a, b, c), (42, 42, 42))
769
770 f = open(TESTFN, "w")
771 lines = ("a\n", "bb\n", "ccc\n")
772 try:
773 for line in lines:
774 f.write(line)
775 finally:
776 f.close()
777 f = open(TESTFN, "r")
778 try:
779 a, b, c = f
780 self.assertEqual((a, b, c), lines)
781 finally:
782 f.close()
783 try:
784 unlink(TESTFN)
785 except OSError:
786 pass
787
788 (a, b), (c,) = IteratingSequenceClass(2), {42: 24}
789 self.assertEqual((a, b, c), (0, 1, 42))
790
Guido van Rossumbb8f59a2001-12-03 19:33:25 +0000791
Benjamin Peterson945c5792010-06-22 20:34:34 +0000792 @cpython_only
793 def test_ref_counting_behavior(self):
Guido van Rossumbb8f59a2001-12-03 19:33:25 +0000794 class C(object):
795 count = 0
796 def __new__(cls):
797 cls.count += 1
798 return object.__new__(cls)
799 def __del__(self):
800 cls = self.__class__
801 assert cls.count > 0
802 cls.count -= 1
803 x = C()
804 self.assertEqual(C.count, 1)
805 del x
806 self.assertEqual(C.count, 0)
807 l = [C(), C(), C()]
808 self.assertEqual(C.count, 3)
809 try:
810 a, b = iter(l)
811 except ValueError:
812 pass
813 del l
814 self.assertEqual(C.count, 0)
Fred Drake2e2be372001-09-20 21:33:42 +0000815
Guido van Rossum674eae62002-07-16 21:48:11 +0000816
817 # Make sure StopIteration is a "sink state".
818 # This tests various things that weren't sink states in Python 2.2.1,
819 # plus various things that always were fine.
820
821 def test_sinkstate_list(self):
822 # This used to fail
Guido van Rossum805365e2007-05-07 22:24:25 +0000823 a = list(range(5))
Guido van Rossum674eae62002-07-16 21:48:11 +0000824 b = iter(a)
Guido van Rossum805365e2007-05-07 22:24:25 +0000825 self.assertEqual(list(b), list(range(5)))
Guido van Rossum674eae62002-07-16 21:48:11 +0000826 a.extend(range(5, 10))
827 self.assertEqual(list(b), [])
828
829 def test_sinkstate_tuple(self):
830 a = (0, 1, 2, 3, 4)
831 b = iter(a)
Guido van Rossum805365e2007-05-07 22:24:25 +0000832 self.assertEqual(list(b), list(range(5)))
Guido van Rossum674eae62002-07-16 21:48:11 +0000833 self.assertEqual(list(b), [])
834
835 def test_sinkstate_string(self):
836 a = "abcde"
837 b = iter(a)
838 self.assertEqual(list(b), ['a', 'b', 'c', 'd', 'e'])
839 self.assertEqual(list(b), [])
840
841 def test_sinkstate_sequence(self):
842 # This used to fail
843 a = SequenceClass(5)
844 b = iter(a)
Guido van Rossum805365e2007-05-07 22:24:25 +0000845 self.assertEqual(list(b), list(range(5)))
Guido van Rossum674eae62002-07-16 21:48:11 +0000846 a.n = 10
847 self.assertEqual(list(b), [])
848
849 def test_sinkstate_callable(self):
850 # This used to fail
851 def spam(state=[0]):
852 i = state[0]
853 state[0] = i+1
854 if i == 10:
Collin Winter3add4d72007-08-29 23:37:32 +0000855 raise AssertionError("shouldn't have gotten this far")
Guido van Rossum674eae62002-07-16 21:48:11 +0000856 return i
857 b = iter(spam, 5)
Guido van Rossum805365e2007-05-07 22:24:25 +0000858 self.assertEqual(list(b), list(range(5)))
Guido van Rossum674eae62002-07-16 21:48:11 +0000859 self.assertEqual(list(b), [])
860
861 def test_sinkstate_dict(self):
862 # XXX For a more thorough test, see towards the end of:
863 # http://mail.python.org/pipermail/python-dev/2002-July/026512.html
864 a = {1:1, 2:2, 0:0, 4:4, 3:3}
Guido van Rossumcc2b0162007-02-11 06:12:03 +0000865 for b in iter(a), a.keys(), a.items(), a.values():
Guido van Rossum674eae62002-07-16 21:48:11 +0000866 b = iter(a)
867 self.assertEqual(len(list(b)), 5)
868 self.assertEqual(list(b), [])
869
870 def test_sinkstate_yield(self):
871 def gen():
872 for i in range(5):
873 yield i
874 b = gen()
Guido van Rossum805365e2007-05-07 22:24:25 +0000875 self.assertEqual(list(b), list(range(5)))
Guido van Rossum674eae62002-07-16 21:48:11 +0000876 self.assertEqual(list(b), [])
877
878 def test_sinkstate_range(self):
Guido van Rossum805365e2007-05-07 22:24:25 +0000879 a = range(5)
Guido van Rossum674eae62002-07-16 21:48:11 +0000880 b = iter(a)
Guido van Rossum805365e2007-05-07 22:24:25 +0000881 self.assertEqual(list(b), list(range(5)))
Guido van Rossum674eae62002-07-16 21:48:11 +0000882 self.assertEqual(list(b), [])
883
884 def test_sinkstate_enumerate(self):
885 a = range(5)
886 e = enumerate(a)
887 b = iter(e)
Guido van Rossum801f0d72006-08-24 19:48:10 +0000888 self.assertEqual(list(b), list(zip(range(5), range(5))))
Guido van Rossum674eae62002-07-16 21:48:11 +0000889 self.assertEqual(list(b), [])
890
Amaury Forgeot d'Arcf343e012009-01-12 23:58:21 +0000891 def test_3720(self):
892 # Avoid a crash, when an iterator deletes its next() method.
893 class BadIterator(object):
894 def __iter__(self):
895 return self
896 def __next__(self):
897 del BadIterator.__next__
898 return 1
899
900 try:
901 for i in BadIterator() :
902 pass
903 except TypeError:
904 pass
905
Guido van Rossum674eae62002-07-16 21:48:11 +0000906
Fred Drake2e2be372001-09-20 21:33:42 +0000907def test_main():
908 run_unittest(TestCase)
909
910
911if __name__ == "__main__":
912 test_main()