blob: e06f239ddab43f74227fa465e9e7bdd2d272e417 [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):
Serhiy Storchakabad12572014-12-15 14:03:42 +020079 for proto in range(pickle.HIGHEST_PROTOCOL + 1):
80 d = pickle.dumps(itorg, proto)
81 it = pickle.loads(d)
82 # Cannot assert type equality because dict iterators unpickle as list
83 # iterators.
84 # self.assertEqual(type(itorg), type(it))
85 self.assertTrue(isinstance(it, collections.abc.Iterator))
86 self.assertEqual(list(it), seq)
Kristján Valur Jónsson31668b82012-04-03 10:49:41 +000087
Serhiy Storchakabad12572014-12-15 14:03:42 +020088 it = pickle.loads(d)
89 try:
90 next(it)
91 except StopIteration:
92 continue
93 d = pickle.dumps(it, proto)
94 it = pickle.loads(d)
95 self.assertEqual(list(it), seq[1:])
Kristján Valur Jónsson31668b82012-04-03 10:49:41 +000096
Guido van Rossum8b48cf92001-04-21 13:33:54 +000097 # Test basic use of iter() function
98 def test_iter_basic(self):
Guido van Rossum805365e2007-05-07 22:24:25 +000099 self.check_iterator(iter(range(10)), list(range(10)))
Guido van Rossum8b48cf92001-04-21 13:33:54 +0000100
101 # Test that iter(iter(x)) is the same as iter(x)
102 def test_iter_idempotency(self):
Guido van Rossum805365e2007-05-07 22:24:25 +0000103 seq = list(range(10))
Guido van Rossum8b48cf92001-04-21 13:33:54 +0000104 it = iter(seq)
105 it2 = iter(it)
Benjamin Petersonc9c0f202009-06-30 23:06:06 +0000106 self.assertTrue(it is it2)
Guido van Rossum8b48cf92001-04-21 13:33:54 +0000107
108 # Test that for loops over iterators work
109 def test_iter_for_loop(self):
Guido van Rossum805365e2007-05-07 22:24:25 +0000110 self.check_for_loop(iter(range(10)), list(range(10)))
Guido van Rossum8b48cf92001-04-21 13:33:54 +0000111
112 # Test several independent iterators over the same list
113 def test_iter_independence(self):
114 seq = range(3)
115 res = []
116 for i in iter(seq):
117 for j in iter(seq):
118 for k in iter(seq):
119 res.append((i, j, k))
120 self.assertEqual(res, TRIPLETS)
121
122 # Test triple list comprehension using iterators
123 def test_nested_comprehensions_iter(self):
124 seq = range(3)
125 res = [(i, j, k)
126 for i in iter(seq) for j in iter(seq) for k in iter(seq)]
127 self.assertEqual(res, TRIPLETS)
128
129 # Test triple list comprehension without iterators
130 def test_nested_comprehensions_for(self):
131 seq = range(3)
132 res = [(i, j, k) for i in seq for j in seq for k in seq]
133 self.assertEqual(res, TRIPLETS)
134
135 # Test a class with __iter__ in a for loop
136 def test_iter_class_for(self):
Guido van Rossum805365e2007-05-07 22:24:25 +0000137 self.check_for_loop(IteratingSequenceClass(10), list(range(10)))
Guido van Rossum8b48cf92001-04-21 13:33:54 +0000138
139 # Test a class with __iter__ with explicit iter()
140 def test_iter_class_iter(self):
Guido van Rossum805365e2007-05-07 22:24:25 +0000141 self.check_iterator(iter(IteratingSequenceClass(10)), list(range(10)))
Guido van Rossum8b48cf92001-04-21 13:33:54 +0000142
143 # Test for loop on a sequence class without __iter__
144 def test_seq_class_for(self):
Guido van Rossum805365e2007-05-07 22:24:25 +0000145 self.check_for_loop(SequenceClass(10), list(range(10)))
Guido van Rossum8b48cf92001-04-21 13:33:54 +0000146
147 # Test iter() on a sequence class without __iter__
148 def test_seq_class_iter(self):
Guido van Rossum805365e2007-05-07 22:24:25 +0000149 self.check_iterator(iter(SequenceClass(10)), list(range(10)))
Guido van Rossum8b48cf92001-04-21 13:33:54 +0000150
Amaury Forgeot d'Arcf343e012009-01-12 23:58:21 +0000151 # Test a new_style class with __iter__ but no next() method
152 def test_new_style_iter_class(self):
153 class IterClass(object):
154 def __iter__(self):
155 return self
156 self.assertRaises(TypeError, iter, IterClass())
157
Guido van Rossum8b48cf92001-04-21 13:33:54 +0000158 # Test two-argument iter() with callable instance
159 def test_iter_callable(self):
160 class C:
161 def __init__(self):
162 self.i = 0
163 def __call__(self):
164 i = self.i
165 self.i = i + 1
166 if i > 100:
167 raise IndexError # Emergency stop
168 return i
Kristján Valur Jónsson31668b82012-04-03 10:49:41 +0000169 self.check_iterator(iter(C(), 10), list(range(10)), pickle=False)
Guido van Rossum8b48cf92001-04-21 13:33:54 +0000170
171 # Test two-argument iter() with function
172 def test_iter_function(self):
173 def spam(state=[0]):
174 i = state[0]
175 state[0] = i+1
176 return i
Kristján Valur Jónsson31668b82012-04-03 10:49:41 +0000177 self.check_iterator(iter(spam, 10), list(range(10)), pickle=False)
Guido van Rossum8b48cf92001-04-21 13:33:54 +0000178
179 # Test two-argument iter() with function that raises StopIteration
180 def test_iter_function_stop(self):
181 def spam(state=[0]):
182 i = state[0]
183 if i == 10:
184 raise StopIteration
185 state[0] = i+1
186 return i
Kristján Valur Jónsson31668b82012-04-03 10:49:41 +0000187 self.check_iterator(iter(spam, 20), list(range(10)), pickle=False)
Guido van Rossum8b48cf92001-04-21 13:33:54 +0000188
189 # Test exception propagation through function iterator
190 def test_exception_function(self):
191 def spam(state=[0]):
192 i = state[0]
193 state[0] = i+1
194 if i == 10:
195 raise RuntimeError
196 return i
197 res = []
198 try:
199 for x in iter(spam, 20):
200 res.append(x)
201 except RuntimeError:
Guido van Rossum805365e2007-05-07 22:24:25 +0000202 self.assertEqual(res, list(range(10)))
Guido van Rossum8b48cf92001-04-21 13:33:54 +0000203 else:
204 self.fail("should have raised RuntimeError")
205
206 # Test exception propagation through sequence iterator
207 def test_exception_sequence(self):
208 class MySequenceClass(SequenceClass):
209 def __getitem__(self, i):
210 if i == 10:
211 raise RuntimeError
212 return SequenceClass.__getitem__(self, i)
213 res = []
214 try:
215 for x in MySequenceClass(20):
216 res.append(x)
217 except RuntimeError:
Guido van Rossum805365e2007-05-07 22:24:25 +0000218 self.assertEqual(res, list(range(10)))
Guido van Rossum8b48cf92001-04-21 13:33:54 +0000219 else:
220 self.fail("should have raised RuntimeError")
221
222 # Test for StopIteration from __getitem__
223 def test_stop_sequence(self):
224 class MySequenceClass(SequenceClass):
225 def __getitem__(self, i):
226 if i == 10:
227 raise StopIteration
228 return SequenceClass.__getitem__(self, i)
Kristján Valur Jónsson31668b82012-04-03 10:49:41 +0000229 self.check_for_loop(MySequenceClass(20), list(range(10)), pickle=False)
Guido van Rossum8b48cf92001-04-21 13:33:54 +0000230
231 # Test a big range
232 def test_iter_big_range(self):
Guido van Rossum805365e2007-05-07 22:24:25 +0000233 self.check_for_loop(iter(range(10000)), list(range(10000)))
Guido van Rossum8b48cf92001-04-21 13:33:54 +0000234
235 # Test an empty list
236 def test_iter_empty(self):
237 self.check_for_loop(iter([]), [])
238
239 # Test a tuple
240 def test_iter_tuple(self):
Guido van Rossum805365e2007-05-07 22:24:25 +0000241 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 +0000242
Guido van Rossum805365e2007-05-07 22:24:25 +0000243 # Test a range
244 def test_iter_range(self):
245 self.check_for_loop(iter(range(10)), list(range(10)))
Guido van Rossum8b48cf92001-04-21 13:33:54 +0000246
247 # Test a string
248 def test_iter_string(self):
249 self.check_for_loop(iter("abcde"), ["a", "b", "c", "d", "e"])
250
Guido van Rossum8b48cf92001-04-21 13:33:54 +0000251 # Test a directory
252 def test_iter_dict(self):
253 dict = {}
254 for i in range(10):
255 dict[i] = None
Brett Cannon0caf6d82007-02-22 04:49:03 +0000256 self.check_for_loop(dict, list(dict.keys()))
Guido van Rossum8b48cf92001-04-21 13:33:54 +0000257
258 # Test a file
259 def test_iter_file(self):
260 f = open(TESTFN, "w")
261 try:
262 for i in range(5):
263 f.write("%d\n" % i)
264 finally:
265 f.close()
266 f = open(TESTFN, "r")
267 try:
Kristján Valur Jónsson31668b82012-04-03 10:49:41 +0000268 self.check_for_loop(f, ["0\n", "1\n", "2\n", "3\n", "4\n"], pickle=False)
269 self.check_for_loop(f, [], pickle=False)
Guido van Rossum8b48cf92001-04-21 13:33:54 +0000270 finally:
271 f.close()
272 try:
273 unlink(TESTFN)
274 except OSError:
275 pass
276
Tim Petersf553f892001-05-01 20:45:31 +0000277 # Test list()'s use of iterators.
278 def test_builtin_list(self):
Guido van Rossum805365e2007-05-07 22:24:25 +0000279 self.assertEqual(list(SequenceClass(5)), list(range(5)))
Tim Petersf553f892001-05-01 20:45:31 +0000280 self.assertEqual(list(SequenceClass(0)), [])
281 self.assertEqual(list(()), [])
Tim Petersf553f892001-05-01 20:45:31 +0000282
283 d = {"one": 1, "two": 2, "three": 3}
Brett Cannon0caf6d82007-02-22 04:49:03 +0000284 self.assertEqual(list(d), list(d.keys()))
Tim Petersf553f892001-05-01 20:45:31 +0000285
286 self.assertRaises(TypeError, list, list)
287 self.assertRaises(TypeError, list, 42)
288
289 f = open(TESTFN, "w")
290 try:
291 for i in range(5):
292 f.write("%d\n" % i)
293 finally:
294 f.close()
295 f = open(TESTFN, "r")
296 try:
297 self.assertEqual(list(f), ["0\n", "1\n", "2\n", "3\n", "4\n"])
298 f.seek(0, 0)
Guido van Rossum8ee52432002-08-06 17:14:04 +0000299 self.assertEqual(list(f),
Tim Petersf553f892001-05-01 20:45:31 +0000300 ["0\n", "1\n", "2\n", "3\n", "4\n"])
301 finally:
302 f.close()
303 try:
304 unlink(TESTFN)
305 except OSError:
306 pass
307
Tim Peters6912d4d2001-05-05 03:56:37 +0000308 # Test tuples()'s use of iterators.
309 def test_builtin_tuple(self):
310 self.assertEqual(tuple(SequenceClass(5)), (0, 1, 2, 3, 4))
311 self.assertEqual(tuple(SequenceClass(0)), ())
312 self.assertEqual(tuple([]), ())
313 self.assertEqual(tuple(()), ())
314 self.assertEqual(tuple("abc"), ("a", "b", "c"))
315
316 d = {"one": 1, "two": 2, "three": 3}
317 self.assertEqual(tuple(d), tuple(d.keys()))
318
319 self.assertRaises(TypeError, tuple, list)
320 self.assertRaises(TypeError, tuple, 42)
321
322 f = open(TESTFN, "w")
323 try:
324 for i in range(5):
325 f.write("%d\n" % i)
326 finally:
327 f.close()
328 f = open(TESTFN, "r")
329 try:
330 self.assertEqual(tuple(f), ("0\n", "1\n", "2\n", "3\n", "4\n"))
331 f.seek(0, 0)
Guido van Rossum8ee52432002-08-06 17:14:04 +0000332 self.assertEqual(tuple(f),
Tim Peters6912d4d2001-05-05 03:56:37 +0000333 ("0\n", "1\n", "2\n", "3\n", "4\n"))
334 finally:
335 f.close()
336 try:
337 unlink(TESTFN)
338 except OSError:
339 pass
340
Tim Peters0e57abf2001-05-02 07:39:38 +0000341 # Test filter()'s use of iterators.
342 def test_builtin_filter(self):
Guido van Rossumc1f779c2007-07-03 08:25:58 +0000343 self.assertEqual(list(filter(None, SequenceClass(5))),
344 list(range(1, 5)))
345 self.assertEqual(list(filter(None, SequenceClass(0))), [])
346 self.assertEqual(list(filter(None, ())), [])
347 self.assertEqual(list(filter(None, "abc")), ["a", "b", "c"])
Tim Peters0e57abf2001-05-02 07:39:38 +0000348
349 d = {"one": 1, "two": 2, "three": 3}
Guido van Rossumc1f779c2007-07-03 08:25:58 +0000350 self.assertEqual(list(filter(None, d)), list(d.keys()))
Tim Peters0e57abf2001-05-02 07:39:38 +0000351
352 self.assertRaises(TypeError, filter, None, list)
353 self.assertRaises(TypeError, filter, None, 42)
354
355 class Boolean:
356 def __init__(self, truth):
357 self.truth = truth
Jack Diederich4dafcc42006-11-28 19:15:13 +0000358 def __bool__(self):
Tim Peters0e57abf2001-05-02 07:39:38 +0000359 return self.truth
Jack Diederich4dafcc42006-11-28 19:15:13 +0000360 bTrue = Boolean(True)
361 bFalse = Boolean(False)
Tim Peters0e57abf2001-05-02 07:39:38 +0000362
363 class Seq:
364 def __init__(self, *args):
365 self.vals = args
366 def __iter__(self):
367 class SeqIter:
368 def __init__(self, vals):
369 self.vals = vals
370 self.i = 0
371 def __iter__(self):
372 return self
Georg Brandla18af4e2007-04-21 15:47:16 +0000373 def __next__(self):
Tim Peters0e57abf2001-05-02 07:39:38 +0000374 i = self.i
375 self.i = i + 1
376 if i < len(self.vals):
377 return self.vals[i]
378 else:
379 raise StopIteration
380 return SeqIter(self.vals)
381
Tim Peterscae330e2002-12-23 16:50:58 +0000382 seq = Seq(*([bTrue, bFalse] * 25))
Guido van Rossumc1f779c2007-07-03 08:25:58 +0000383 self.assertEqual(list(filter(lambda x: not x, seq)), [bFalse]*25)
384 self.assertEqual(list(filter(lambda x: not x, iter(seq))), [bFalse]*25)
Tim Peters0e57abf2001-05-02 07:39:38 +0000385
Tim Petersc3074532001-05-03 07:00:32 +0000386 # Test max() and min()'s use of iterators.
387 def test_builtin_max_min(self):
388 self.assertEqual(max(SequenceClass(5)), 4)
389 self.assertEqual(min(SequenceClass(5)), 0)
390 self.assertEqual(max(8, -1), 8)
391 self.assertEqual(min(8, -1), -1)
392
393 d = {"one": 1, "two": 2, "three": 3}
394 self.assertEqual(max(d), "two")
395 self.assertEqual(min(d), "one")
Guido van Rossumcc2b0162007-02-11 06:12:03 +0000396 self.assertEqual(max(d.values()), 3)
397 self.assertEqual(min(iter(d.values())), 1)
Tim Petersc3074532001-05-03 07:00:32 +0000398
Tim Petersc3074532001-05-03 07:00:32 +0000399 f = open(TESTFN, "w")
400 try:
401 f.write("medium line\n")
402 f.write("xtra large line\n")
403 f.write("itty-bitty line\n")
404 finally:
405 f.close()
406 f = open(TESTFN, "r")
407 try:
408 self.assertEqual(min(f), "itty-bitty line\n")
409 f.seek(0, 0)
410 self.assertEqual(max(f), "xtra large line\n")
411 finally:
412 f.close()
413 try:
414 unlink(TESTFN)
415 except OSError:
416 pass
417
Tim Peters4e9afdc2001-05-03 23:54:49 +0000418 # Test map()'s use of iterators.
419 def test_builtin_map(self):
Guido van Rossumc1f779c2007-07-03 08:25:58 +0000420 self.assertEqual(list(map(lambda x: x+1, SequenceClass(5))),
421 list(range(1, 6)))
Tim Peters4e9afdc2001-05-03 23:54:49 +0000422
423 d = {"one": 1, "two": 2, "three": 3}
Guido van Rossumc1f779c2007-07-03 08:25:58 +0000424 self.assertEqual(list(map(lambda k, d=d: (k, d[k]), d)),
425 list(d.items()))
Brett Cannon0caf6d82007-02-22 04:49:03 +0000426 dkeys = list(d.keys())
Tim Peters4e9afdc2001-05-03 23:54:49 +0000427 expected = [(i < len(d) and dkeys[i] or None,
428 i,
429 i < len(d) and dkeys[i] or None)
Guido van Rossumc1f779c2007-07-03 08:25:58 +0000430 for i in range(3)]
Tim Peters4e9afdc2001-05-03 23:54:49 +0000431
432 f = open(TESTFN, "w")
433 try:
434 for i in range(10):
435 f.write("xy" * i + "\n") # line i has len 2*i+1
436 finally:
437 f.close()
438 f = open(TESTFN, "r")
439 try:
Guido van Rossumc1f779c2007-07-03 08:25:58 +0000440 self.assertEqual(list(map(len, f)), list(range(1, 21, 2)))
Tim Peters4e9afdc2001-05-03 23:54:49 +0000441 finally:
442 f.close()
443 try:
444 unlink(TESTFN)
445 except OSError:
446 pass
447
Tim Peters8572b4f2001-05-06 01:05:02 +0000448 # Test zip()'s use of iterators.
449 def test_builtin_zip(self):
Guido van Rossum801f0d72006-08-24 19:48:10 +0000450 self.assertEqual(list(zip()), [])
451 self.assertEqual(list(zip(*[])), [])
452 self.assertEqual(list(zip(*[(1, 2), 'ab'])), [(1, 'a'), (2, 'b')])
Raymond Hettingereaef6152003-08-02 07:42:57 +0000453
Tim Peters8572b4f2001-05-06 01:05:02 +0000454 self.assertRaises(TypeError, zip, None)
455 self.assertRaises(TypeError, zip, range(10), 42)
456 self.assertRaises(TypeError, zip, range(10), zip)
457
Guido van Rossum801f0d72006-08-24 19:48:10 +0000458 self.assertEqual(list(zip(IteratingSequenceClass(3))),
Tim Peters8572b4f2001-05-06 01:05:02 +0000459 [(0,), (1,), (2,)])
Guido van Rossum801f0d72006-08-24 19:48:10 +0000460 self.assertEqual(list(zip(SequenceClass(3))),
Tim Peters8572b4f2001-05-06 01:05:02 +0000461 [(0,), (1,), (2,)])
462
463 d = {"one": 1, "two": 2, "three": 3}
Brett Cannon0caf6d82007-02-22 04:49:03 +0000464 self.assertEqual(list(d.items()), list(zip(d, d.values())))
Tim Peters8572b4f2001-05-06 01:05:02 +0000465
466 # Generate all ints starting at constructor arg.
467 class IntsFrom:
468 def __init__(self, start):
469 self.i = start
470
471 def __iter__(self):
472 return self
473
Georg Brandla18af4e2007-04-21 15:47:16 +0000474 def __next__(self):
Tim Peters8572b4f2001-05-06 01:05:02 +0000475 i = self.i
476 self.i = i+1
477 return i
478
479 f = open(TESTFN, "w")
480 try:
481 f.write("a\n" "bbb\n" "cc\n")
482 finally:
483 f.close()
484 f = open(TESTFN, "r")
485 try:
Guido van Rossum801f0d72006-08-24 19:48:10 +0000486 self.assertEqual(list(zip(IntsFrom(0), f, IntsFrom(-100))),
Tim Peters8572b4f2001-05-06 01:05:02 +0000487 [(0, "a\n", -100),
488 (1, "bbb\n", -99),
489 (2, "cc\n", -98)])
490 finally:
491 f.close()
492 try:
493 unlink(TESTFN)
494 except OSError:
495 pass
496
Guido van Rossum805365e2007-05-07 22:24:25 +0000497 self.assertEqual(list(zip(range(5))), [(i,) for i in range(5)])
Tim Peters67d687a2002-04-29 21:27:32 +0000498
499 # Classes that lie about their lengths.
500 class NoGuessLen5:
501 def __getitem__(self, i):
502 if i >= 5:
503 raise IndexError
504 return i
505
506 class Guess3Len5(NoGuessLen5):
507 def __len__(self):
508 return 3
509
510 class Guess30Len5(NoGuessLen5):
511 def __len__(self):
512 return 30
513
Guido van Rossum801f0d72006-08-24 19:48:10 +0000514 def lzip(*args):
515 return list(zip(*args))
516
Tim Peters67d687a2002-04-29 21:27:32 +0000517 self.assertEqual(len(Guess3Len5()), 3)
518 self.assertEqual(len(Guess30Len5()), 30)
Guido van Rossum801f0d72006-08-24 19:48:10 +0000519 self.assertEqual(lzip(NoGuessLen5()), lzip(range(5)))
520 self.assertEqual(lzip(Guess3Len5()), lzip(range(5)))
521 self.assertEqual(lzip(Guess30Len5()), lzip(range(5)))
Tim Peters67d687a2002-04-29 21:27:32 +0000522
523 expected = [(i, i) for i in range(5)]
524 for x in NoGuessLen5(), Guess3Len5(), Guess30Len5():
525 for y in NoGuessLen5(), Guess3Len5(), Guess30Len5():
Guido van Rossum801f0d72006-08-24 19:48:10 +0000526 self.assertEqual(lzip(x, y), expected)
Tim Peters67d687a2002-04-29 21:27:32 +0000527
Tim Peters2cfe3682001-05-05 05:36:48 +0000528 def test_unicode_join_endcase(self):
529
530 # This class inserts a Unicode object into its argument's natural
531 # iteration, in the 3rd position.
532 class OhPhooey:
533 def __init__(self, seq):
534 self.it = iter(seq)
535 self.i = 0
536
537 def __iter__(self):
538 return self
539
Georg Brandla18af4e2007-04-21 15:47:16 +0000540 def __next__(self):
Tim Peters2cfe3682001-05-05 05:36:48 +0000541 i = self.i
542 self.i = i+1
543 if i == 2:
Walter Dörwald1f5947b2007-05-22 16:52:54 +0000544 return "fooled you!"
Georg Brandla18af4e2007-04-21 15:47:16 +0000545 return next(self.it)
Tim Peters2cfe3682001-05-05 05:36:48 +0000546
547 f = open(TESTFN, "w")
548 try:
549 f.write("a\n" + "b\n" + "c\n")
550 finally:
551 f.close()
552
553 f = open(TESTFN, "r")
554 # Nasty: string.join(s) can't know whether unicode.join() is needed
555 # until it's seen all of s's elements. But in this case, f's
556 # iterator cannot be restarted. So what we're testing here is
557 # whether string.join() can manage to remember everything it's seen
558 # and pass that on to unicode.join().
559 try:
560 got = " - ".join(OhPhooey(f))
Walter Dörwald5de48bd2007-06-11 21:38:39 +0000561 self.assertEqual(got, "a\n - b\n - fooled you! - c\n")
Tim Peters2cfe3682001-05-05 05:36:48 +0000562 finally:
563 f.close()
564 try:
565 unlink(TESTFN)
566 except OSError:
567 pass
568
Tim Petersde9725f2001-05-05 10:06:17 +0000569 # Test iterators with 'x in y' and 'x not in y'.
570 def test_in_and_not_in(self):
Tim Peterscb8d3682001-05-05 21:05:01 +0000571 for sc5 in IteratingSequenceClass(5), SequenceClass(5):
572 for i in range(5):
Benjamin Peterson577473f2010-01-19 00:09:57 +0000573 self.assertIn(i, sc5)
Tim Peterscb8d3682001-05-05 21:05:01 +0000574 for i in "abc", -1, 5, 42.42, (3, 4), [], {1: 1}, 3-12j, sc5:
Benjamin Peterson577473f2010-01-19 00:09:57 +0000575 self.assertNotIn(i, sc5)
Tim Petersde9725f2001-05-05 10:06:17 +0000576
577 self.assertRaises(TypeError, lambda: 3 in 12)
578 self.assertRaises(TypeError, lambda: 3 not in map)
579
580 d = {"one": 1, "two": 2, "three": 3, 1j: 2j}
581 for k in d:
Benjamin Peterson577473f2010-01-19 00:09:57 +0000582 self.assertIn(k, d)
583 self.assertNotIn(k, d.values())
Tim Petersde9725f2001-05-05 10:06:17 +0000584 for v in d.values():
Benjamin Peterson577473f2010-01-19 00:09:57 +0000585 self.assertIn(v, d.values())
586 self.assertNotIn(v, d)
Guido van Rossumcc2b0162007-02-11 06:12:03 +0000587 for k, v in d.items():
Benjamin Peterson577473f2010-01-19 00:09:57 +0000588 self.assertIn((k, v), d.items())
589 self.assertNotIn((v, k), d.items())
Tim Petersde9725f2001-05-05 10:06:17 +0000590
591 f = open(TESTFN, "w")
592 try:
593 f.write("a\n" "b\n" "c\n")
594 finally:
595 f.close()
596 f = open(TESTFN, "r")
597 try:
598 for chunk in "abc":
599 f.seek(0, 0)
Benjamin Peterson577473f2010-01-19 00:09:57 +0000600 self.assertNotIn(chunk, f)
Tim Petersde9725f2001-05-05 10:06:17 +0000601 f.seek(0, 0)
Benjamin Peterson577473f2010-01-19 00:09:57 +0000602 self.assertIn((chunk + "\n"), f)
Tim Petersde9725f2001-05-05 10:06:17 +0000603 finally:
604 f.close()
605 try:
606 unlink(TESTFN)
607 except OSError:
608 pass
609
Tim Peters75f8e352001-05-05 11:33:43 +0000610 # Test iterators with operator.countOf (PySequence_Count).
611 def test_countOf(self):
612 from operator import countOf
613 self.assertEqual(countOf([1,2,2,3,2,5], 2), 3)
614 self.assertEqual(countOf((1,2,2,3,2,5), 2), 3)
615 self.assertEqual(countOf("122325", "2"), 3)
616 self.assertEqual(countOf("122325", "6"), 0)
617
618 self.assertRaises(TypeError, countOf, 42, 1)
619 self.assertRaises(TypeError, countOf, countOf, countOf)
620
621 d = {"one": 3, "two": 3, "three": 3, 1j: 2j}
622 for k in d:
623 self.assertEqual(countOf(d, k), 1)
Guido van Rossumcc2b0162007-02-11 06:12:03 +0000624 self.assertEqual(countOf(d.values(), 3), 3)
625 self.assertEqual(countOf(d.values(), 2j), 1)
626 self.assertEqual(countOf(d.values(), 1j), 0)
Tim Peters75f8e352001-05-05 11:33:43 +0000627
628 f = open(TESTFN, "w")
629 try:
630 f.write("a\n" "b\n" "c\n" "b\n")
631 finally:
632 f.close()
633 f = open(TESTFN, "r")
634 try:
635 for letter, count in ("a", 1), ("b", 2), ("c", 1), ("d", 0):
636 f.seek(0, 0)
637 self.assertEqual(countOf(f, letter + "\n"), count)
638 finally:
639 f.close()
640 try:
641 unlink(TESTFN)
642 except OSError:
643 pass
644
Tim Peters16a77ad2001-09-08 04:00:12 +0000645 # Test iterators with operator.indexOf (PySequence_Index).
646 def test_indexOf(self):
647 from operator import indexOf
648 self.assertEqual(indexOf([1,2,2,3,2,5], 1), 0)
649 self.assertEqual(indexOf((1,2,2,3,2,5), 2), 1)
650 self.assertEqual(indexOf((1,2,2,3,2,5), 3), 3)
651 self.assertEqual(indexOf((1,2,2,3,2,5), 5), 5)
652 self.assertRaises(ValueError, indexOf, (1,2,2,3,2,5), 0)
653 self.assertRaises(ValueError, indexOf, (1,2,2,3,2,5), 6)
654
655 self.assertEqual(indexOf("122325", "2"), 1)
656 self.assertEqual(indexOf("122325", "5"), 5)
657 self.assertRaises(ValueError, indexOf, "122325", "6")
658
659 self.assertRaises(TypeError, indexOf, 42, 1)
660 self.assertRaises(TypeError, indexOf, indexOf, indexOf)
661
662 f = open(TESTFN, "w")
663 try:
664 f.write("a\n" "b\n" "c\n" "d\n" "e\n")
665 finally:
666 f.close()
667 f = open(TESTFN, "r")
668 try:
669 fiter = iter(f)
670 self.assertEqual(indexOf(fiter, "b\n"), 1)
671 self.assertEqual(indexOf(fiter, "d\n"), 1)
672 self.assertEqual(indexOf(fiter, "e\n"), 0)
673 self.assertRaises(ValueError, indexOf, fiter, "a\n")
674 finally:
675 f.close()
676 try:
677 unlink(TESTFN)
678 except OSError:
679 pass
680
681 iclass = IteratingSequenceClass(3)
682 for i in range(3):
683 self.assertEqual(indexOf(iclass, i), i)
684 self.assertRaises(ValueError, indexOf, iclass, -1)
685
Tim Peters2c9aa5e2001-09-23 04:06:05 +0000686 # Test iterators with file.writelines().
687 def test_writelines(self):
Alex Martelli01c77c62006-08-24 02:58:11 +0000688 f = open(TESTFN, "w")
Tim Peters2c9aa5e2001-09-23 04:06:05 +0000689
690 try:
691 self.assertRaises(TypeError, f.writelines, None)
692 self.assertRaises(TypeError, f.writelines, 42)
Tim Peters527e64f2001-10-04 05:36:56 +0000693
Tim Peters2c9aa5e2001-09-23 04:06:05 +0000694 f.writelines(["1\n", "2\n"])
695 f.writelines(("3\n", "4\n"))
696 f.writelines({'5\n': None})
697 f.writelines({})
698
699 # Try a big chunk too.
700 class Iterator:
701 def __init__(self, start, finish):
702 self.start = start
703 self.finish = finish
704 self.i = self.start
705
Georg Brandla18af4e2007-04-21 15:47:16 +0000706 def __next__(self):
Tim Peters2c9aa5e2001-09-23 04:06:05 +0000707 if self.i >= self.finish:
708 raise StopIteration
709 result = str(self.i) + '\n'
710 self.i += 1
711 return result
712
713 def __iter__(self):
714 return self
715
716 class Whatever:
717 def __init__(self, start, finish):
718 self.start = start
719 self.finish = finish
720
721 def __iter__(self):
722 return Iterator(self.start, self.finish)
Tim Peters527e64f2001-10-04 05:36:56 +0000723
724 f.writelines(Whatever(6, 6+2000))
Tim Peters2c9aa5e2001-09-23 04:06:05 +0000725 f.close()
726
Alex Martelli01c77c62006-08-24 02:58:11 +0000727 f = open(TESTFN)
Tim Peters2c9aa5e2001-09-23 04:06:05 +0000728 expected = [str(i) + "\n" for i in range(1, 2006)]
729 self.assertEqual(list(f), expected)
Tim Peters527e64f2001-10-04 05:36:56 +0000730
Tim Peters2c9aa5e2001-09-23 04:06:05 +0000731 finally:
732 f.close()
733 try:
734 unlink(TESTFN)
735 except OSError:
736 pass
737
738
Tim Petersd6d010b2001-06-21 02:49:55 +0000739 # Test iterators on RHS of unpacking assignments.
740 def test_unpack_iter(self):
741 a, b = 1, 2
742 self.assertEqual((a, b), (1, 2))
743
744 a, b, c = IteratingSequenceClass(3)
745 self.assertEqual((a, b, c), (0, 1, 2))
746
747 try: # too many values
748 a, b = IteratingSequenceClass(3)
749 except ValueError:
750 pass
751 else:
752 self.fail("should have raised ValueError")
753
754 try: # not enough values
755 a, b, c = IteratingSequenceClass(2)
756 except ValueError:
757 pass
758 else:
759 self.fail("should have raised ValueError")
760
761 try: # not iterable
762 a, b, c = len
763 except TypeError:
764 pass
765 else:
766 self.fail("should have raised TypeError")
767
Guido van Rossumcc2b0162007-02-11 06:12:03 +0000768 a, b, c = {1: 42, 2: 42, 3: 42}.values()
Tim Petersd6d010b2001-06-21 02:49:55 +0000769 self.assertEqual((a, b, c), (42, 42, 42))
770
771 f = open(TESTFN, "w")
772 lines = ("a\n", "bb\n", "ccc\n")
773 try:
774 for line in lines:
775 f.write(line)
776 finally:
777 f.close()
778 f = open(TESTFN, "r")
779 try:
780 a, b, c = f
781 self.assertEqual((a, b, c), lines)
782 finally:
783 f.close()
784 try:
785 unlink(TESTFN)
786 except OSError:
787 pass
788
789 (a, b), (c,) = IteratingSequenceClass(2), {42: 24}
790 self.assertEqual((a, b, c), (0, 1, 42))
791
Guido van Rossumbb8f59a2001-12-03 19:33:25 +0000792
Benjamin Peterson945c5792010-06-22 20:34:34 +0000793 @cpython_only
794 def test_ref_counting_behavior(self):
Guido van Rossumbb8f59a2001-12-03 19:33:25 +0000795 class C(object):
796 count = 0
797 def __new__(cls):
798 cls.count += 1
799 return object.__new__(cls)
800 def __del__(self):
801 cls = self.__class__
802 assert cls.count > 0
803 cls.count -= 1
804 x = C()
805 self.assertEqual(C.count, 1)
806 del x
807 self.assertEqual(C.count, 0)
808 l = [C(), C(), C()]
809 self.assertEqual(C.count, 3)
810 try:
811 a, b = iter(l)
812 except ValueError:
813 pass
814 del l
815 self.assertEqual(C.count, 0)
Fred Drake2e2be372001-09-20 21:33:42 +0000816
Guido van Rossum674eae62002-07-16 21:48:11 +0000817
818 # Make sure StopIteration is a "sink state".
819 # This tests various things that weren't sink states in Python 2.2.1,
820 # plus various things that always were fine.
821
822 def test_sinkstate_list(self):
823 # This used to fail
Guido van Rossum805365e2007-05-07 22:24:25 +0000824 a = list(range(5))
Guido van Rossum674eae62002-07-16 21:48:11 +0000825 b = iter(a)
Guido van Rossum805365e2007-05-07 22:24:25 +0000826 self.assertEqual(list(b), list(range(5)))
Guido van Rossum674eae62002-07-16 21:48:11 +0000827 a.extend(range(5, 10))
828 self.assertEqual(list(b), [])
829
830 def test_sinkstate_tuple(self):
831 a = (0, 1, 2, 3, 4)
832 b = iter(a)
Guido van Rossum805365e2007-05-07 22:24:25 +0000833 self.assertEqual(list(b), list(range(5)))
Guido van Rossum674eae62002-07-16 21:48:11 +0000834 self.assertEqual(list(b), [])
835
836 def test_sinkstate_string(self):
837 a = "abcde"
838 b = iter(a)
839 self.assertEqual(list(b), ['a', 'b', 'c', 'd', 'e'])
840 self.assertEqual(list(b), [])
841
842 def test_sinkstate_sequence(self):
843 # This used to fail
844 a = SequenceClass(5)
845 b = iter(a)
Guido van Rossum805365e2007-05-07 22:24:25 +0000846 self.assertEqual(list(b), list(range(5)))
Guido van Rossum674eae62002-07-16 21:48:11 +0000847 a.n = 10
848 self.assertEqual(list(b), [])
849
850 def test_sinkstate_callable(self):
851 # This used to fail
852 def spam(state=[0]):
853 i = state[0]
854 state[0] = i+1
855 if i == 10:
Collin Winter3add4d72007-08-29 23:37:32 +0000856 raise AssertionError("shouldn't have gotten this far")
Guido van Rossum674eae62002-07-16 21:48:11 +0000857 return i
858 b = iter(spam, 5)
Guido van Rossum805365e2007-05-07 22:24:25 +0000859 self.assertEqual(list(b), list(range(5)))
Guido van Rossum674eae62002-07-16 21:48:11 +0000860 self.assertEqual(list(b), [])
861
862 def test_sinkstate_dict(self):
863 # XXX For a more thorough test, see towards the end of:
864 # http://mail.python.org/pipermail/python-dev/2002-July/026512.html
865 a = {1:1, 2:2, 0:0, 4:4, 3:3}
Guido van Rossumcc2b0162007-02-11 06:12:03 +0000866 for b in iter(a), a.keys(), a.items(), a.values():
Guido van Rossum674eae62002-07-16 21:48:11 +0000867 b = iter(a)
868 self.assertEqual(len(list(b)), 5)
869 self.assertEqual(list(b), [])
870
871 def test_sinkstate_yield(self):
872 def gen():
873 for i in range(5):
874 yield i
875 b = gen()
Guido van Rossum805365e2007-05-07 22:24:25 +0000876 self.assertEqual(list(b), list(range(5)))
Guido van Rossum674eae62002-07-16 21:48:11 +0000877 self.assertEqual(list(b), [])
878
879 def test_sinkstate_range(self):
Guido van Rossum805365e2007-05-07 22:24:25 +0000880 a = range(5)
Guido van Rossum674eae62002-07-16 21:48:11 +0000881 b = iter(a)
Guido van Rossum805365e2007-05-07 22:24:25 +0000882 self.assertEqual(list(b), list(range(5)))
Guido van Rossum674eae62002-07-16 21:48:11 +0000883 self.assertEqual(list(b), [])
884
885 def test_sinkstate_enumerate(self):
886 a = range(5)
887 e = enumerate(a)
888 b = iter(e)
Guido van Rossum801f0d72006-08-24 19:48:10 +0000889 self.assertEqual(list(b), list(zip(range(5), range(5))))
Guido van Rossum674eae62002-07-16 21:48:11 +0000890 self.assertEqual(list(b), [])
891
Amaury Forgeot d'Arcf343e012009-01-12 23:58:21 +0000892 def test_3720(self):
893 # Avoid a crash, when an iterator deletes its next() method.
894 class BadIterator(object):
895 def __iter__(self):
896 return self
897 def __next__(self):
898 del BadIterator.__next__
899 return 1
900
901 try:
902 for i in BadIterator() :
903 pass
904 except TypeError:
905 pass
906
Ezio Melotti739e1792012-11-18 23:16:02 +0200907 def test_extending_list_with_iterator_does_not_segfault(self):
908 # The code to extend a list with an iterator has a fair
909 # amount of nontrivial logic in terms of guessing how
910 # much memory to allocate in advance, "stealing" refs,
911 # and then shrinking at the end. This is a basic smoke
912 # test for that scenario.
913 def gen():
914 for i in range(500):
915 yield i
916 lst = [0] * 500
917 for i in range(240):
918 lst.pop(0)
919 lst.extend(gen())
920 self.assertEqual(len(lst), 760)
921
Guido van Rossum674eae62002-07-16 21:48:11 +0000922
Fred Drake2e2be372001-09-20 21:33:42 +0000923def test_main():
924 run_unittest(TestCase)
925
926
927if __name__ == "__main__":
928 test_main()