blob: 524346939886db5c2711bcebe9c3bd816158a593 [file] [log] [blame]
Guido van Rossum8b48cf92001-04-21 13:33:54 +00001# Test iterators.
2
Serhiy Storchaka4faf5c52015-05-21 20:50:25 +03003import sys
Guido van Rossum8b48cf92001-04-21 13:33:54 +00004import unittest
Benjamin Peterson945c5792010-06-22 20:34:34 +00005from test.support import run_unittest, TESTFN, unlink, cpython_only
Serhiy Storchaka18b711c2019-08-04 14:12:48 +03006from test.support import check_free_after_iterating, ALWAYS_EQ, NEVER_EQ
Kristján Valur Jónsson31668b82012-04-03 10:49:41 +00007import pickle
8import collections.abc
Guido van Rossum8b48cf92001-04-21 13:33:54 +00009
10# Test result of triple loop (too big to inline)
11TRIPLETS = [(0, 0, 0), (0, 0, 1), (0, 0, 2),
12 (0, 1, 0), (0, 1, 1), (0, 1, 2),
13 (0, 2, 0), (0, 2, 1), (0, 2, 2),
14
15 (1, 0, 0), (1, 0, 1), (1, 0, 2),
16 (1, 1, 0), (1, 1, 1), (1, 1, 2),
17 (1, 2, 0), (1, 2, 1), (1, 2, 2),
18
19 (2, 0, 0), (2, 0, 1), (2, 0, 2),
20 (2, 1, 0), (2, 1, 1), (2, 1, 2),
21 (2, 2, 0), (2, 2, 1), (2, 2, 2)]
22
23# Helper classes
24
25class BasicIterClass:
26 def __init__(self, n):
27 self.n = n
28 self.i = 0
Georg Brandla18af4e2007-04-21 15:47:16 +000029 def __next__(self):
Guido van Rossum8b48cf92001-04-21 13:33:54 +000030 res = self.i
31 if res >= self.n:
32 raise StopIteration
33 self.i = res + 1
34 return res
Kristján Valur Jónsson31668b82012-04-03 10:49:41 +000035 def __iter__(self):
36 return self
Guido van Rossum8b48cf92001-04-21 13:33:54 +000037
38class IteratingSequenceClass:
39 def __init__(self, n):
40 self.n = n
41 def __iter__(self):
42 return BasicIterClass(self.n)
43
Serhiy Storchaka18b711c2019-08-04 14:12:48 +030044class IteratorProxyClass:
45 def __init__(self, i):
46 self.i = i
47 def __next__(self):
48 return next(self.i)
49 def __iter__(self):
50 return self
51
Guido van Rossum8b48cf92001-04-21 13:33:54 +000052class SequenceClass:
53 def __init__(self, n):
54 self.n = n
55 def __getitem__(self, i):
56 if 0 <= i < self.n:
57 return i
58 else:
59 raise IndexError
60
Serhiy Storchaka18b711c2019-08-04 14:12:48 +030061class SequenceProxyClass:
62 def __init__(self, s):
63 self.s = s
64 def __getitem__(self, i):
65 return self.s[i]
66
Serhiy Storchaka4faf5c52015-05-21 20:50:25 +030067class UnlimitedSequenceClass:
68 def __getitem__(self, i):
69 return i
70
Guido van Rossum97c1adf2016-08-18 09:22:23 -070071class DefaultIterClass:
72 pass
73
74class NoIterClass:
75 def __getitem__(self, i):
76 return i
77 __iter__ = None
78
Miss Islington (bot)353c4ba2020-06-22 01:20:56 -070079class BadIterableClass:
80 def __iter__(self):
81 raise ZeroDivisionError
82
Guido van Rossum8b48cf92001-04-21 13:33:54 +000083# Main test suite
84
85class TestCase(unittest.TestCase):
86
87 # Helper to check that an iterator returns a given sequence
Kristján Valur Jónsson31668b82012-04-03 10:49:41 +000088 def check_iterator(self, it, seq, pickle=True):
89 if pickle:
90 self.check_pickle(it, seq)
Guido van Rossum8b48cf92001-04-21 13:33:54 +000091 res = []
92 while 1:
93 try:
Georg Brandla18af4e2007-04-21 15:47:16 +000094 val = next(it)
Guido van Rossum8b48cf92001-04-21 13:33:54 +000095 except StopIteration:
96 break
97 res.append(val)
98 self.assertEqual(res, seq)
99
100 # Helper to check that a for loop generates a given sequence
Kristján Valur Jónsson31668b82012-04-03 10:49:41 +0000101 def check_for_loop(self, expr, seq, pickle=True):
102 if pickle:
103 self.check_pickle(iter(expr), seq)
Guido van Rossum8b48cf92001-04-21 13:33:54 +0000104 res = []
105 for val in expr:
106 res.append(val)
107 self.assertEqual(res, seq)
108
Kristján Valur Jónsson31668b82012-04-03 10:49:41 +0000109 # Helper to check picklability
110 def check_pickle(self, itorg, seq):
Serhiy Storchakabad12572014-12-15 14:03:42 +0200111 for proto in range(pickle.HIGHEST_PROTOCOL + 1):
112 d = pickle.dumps(itorg, proto)
113 it = pickle.loads(d)
114 # Cannot assert type equality because dict iterators unpickle as list
115 # iterators.
116 # self.assertEqual(type(itorg), type(it))
117 self.assertTrue(isinstance(it, collections.abc.Iterator))
118 self.assertEqual(list(it), seq)
Kristján Valur Jónsson31668b82012-04-03 10:49:41 +0000119
Serhiy Storchakabad12572014-12-15 14:03:42 +0200120 it = pickle.loads(d)
121 try:
122 next(it)
123 except StopIteration:
124 continue
125 d = pickle.dumps(it, proto)
126 it = pickle.loads(d)
127 self.assertEqual(list(it), seq[1:])
Kristján Valur Jónsson31668b82012-04-03 10:49:41 +0000128
Guido van Rossum8b48cf92001-04-21 13:33:54 +0000129 # Test basic use of iter() function
130 def test_iter_basic(self):
Guido van Rossum805365e2007-05-07 22:24:25 +0000131 self.check_iterator(iter(range(10)), list(range(10)))
Guido van Rossum8b48cf92001-04-21 13:33:54 +0000132
133 # Test that iter(iter(x)) is the same as iter(x)
134 def test_iter_idempotency(self):
Guido van Rossum805365e2007-05-07 22:24:25 +0000135 seq = list(range(10))
Guido van Rossum8b48cf92001-04-21 13:33:54 +0000136 it = iter(seq)
137 it2 = iter(it)
Benjamin Petersonc9c0f202009-06-30 23:06:06 +0000138 self.assertTrue(it is it2)
Guido van Rossum8b48cf92001-04-21 13:33:54 +0000139
140 # Test that for loops over iterators work
141 def test_iter_for_loop(self):
Guido van Rossum805365e2007-05-07 22:24:25 +0000142 self.check_for_loop(iter(range(10)), list(range(10)))
Guido van Rossum8b48cf92001-04-21 13:33:54 +0000143
144 # Test several independent iterators over the same list
145 def test_iter_independence(self):
146 seq = range(3)
147 res = []
148 for i in iter(seq):
149 for j in iter(seq):
150 for k in iter(seq):
151 res.append((i, j, k))
152 self.assertEqual(res, TRIPLETS)
153
154 # Test triple list comprehension using iterators
155 def test_nested_comprehensions_iter(self):
156 seq = range(3)
157 res = [(i, j, k)
158 for i in iter(seq) for j in iter(seq) for k in iter(seq)]
159 self.assertEqual(res, TRIPLETS)
160
161 # Test triple list comprehension without iterators
162 def test_nested_comprehensions_for(self):
163 seq = range(3)
164 res = [(i, j, k) for i in seq for j in seq for k in seq]
165 self.assertEqual(res, TRIPLETS)
166
167 # Test a class with __iter__ in a for loop
168 def test_iter_class_for(self):
Guido van Rossum805365e2007-05-07 22:24:25 +0000169 self.check_for_loop(IteratingSequenceClass(10), list(range(10)))
Guido van Rossum8b48cf92001-04-21 13:33:54 +0000170
171 # Test a class with __iter__ with explicit iter()
172 def test_iter_class_iter(self):
Guido van Rossum805365e2007-05-07 22:24:25 +0000173 self.check_iterator(iter(IteratingSequenceClass(10)), list(range(10)))
Guido van Rossum8b48cf92001-04-21 13:33:54 +0000174
175 # Test for loop on a sequence class without __iter__
176 def test_seq_class_for(self):
Guido van Rossum805365e2007-05-07 22:24:25 +0000177 self.check_for_loop(SequenceClass(10), list(range(10)))
Guido van Rossum8b48cf92001-04-21 13:33:54 +0000178
179 # Test iter() on a sequence class without __iter__
180 def test_seq_class_iter(self):
Guido van Rossum805365e2007-05-07 22:24:25 +0000181 self.check_iterator(iter(SequenceClass(10)), list(range(10)))
Guido van Rossum8b48cf92001-04-21 13:33:54 +0000182
Serhiy Storchakaaabafe72016-03-06 14:10:24 +0200183 def test_mutating_seq_class_iter_pickle(self):
184 orig = SequenceClass(5)
185 for proto in range(pickle.HIGHEST_PROTOCOL + 1):
186 # initial iterator
187 itorig = iter(orig)
188 d = pickle.dumps((itorig, orig), proto)
189 it, seq = pickle.loads(d)
190 seq.n = 7
191 self.assertIs(type(it), type(itorig))
192 self.assertEqual(list(it), list(range(7)))
193
194 # running iterator
195 next(itorig)
196 d = pickle.dumps((itorig, orig), proto)
197 it, seq = pickle.loads(d)
198 seq.n = 7
199 self.assertIs(type(it), type(itorig))
200 self.assertEqual(list(it), list(range(1, 7)))
201
202 # empty iterator
203 for i in range(1, 5):
204 next(itorig)
205 d = pickle.dumps((itorig, orig), proto)
206 it, seq = pickle.loads(d)
207 seq.n = 7
208 self.assertIs(type(it), type(itorig))
209 self.assertEqual(list(it), list(range(5, 7)))
210
211 # exhausted iterator
212 self.assertRaises(StopIteration, next, itorig)
213 d = pickle.dumps((itorig, orig), proto)
214 it, seq = pickle.loads(d)
215 seq.n = 7
216 self.assertTrue(isinstance(it, collections.abc.Iterator))
217 self.assertEqual(list(it), [])
218
Serhiy Storchaka8dc2ec12016-03-30 21:01:26 +0300219 def test_mutating_seq_class_exhausted_iter(self):
220 a = SequenceClass(5)
221 exhit = iter(a)
222 empit = iter(a)
223 for x in exhit: # exhaust the iterator
224 next(empit) # not exhausted
225 a.n = 7
226 self.assertEqual(list(exhit), [])
227 self.assertEqual(list(empit), [5, 6])
228 self.assertEqual(list(a), [0, 1, 2, 3, 4, 5, 6])
229
Amaury Forgeot d'Arcf343e012009-01-12 23:58:21 +0000230 # Test a new_style class with __iter__ but no next() method
231 def test_new_style_iter_class(self):
232 class IterClass(object):
233 def __iter__(self):
234 return self
235 self.assertRaises(TypeError, iter, IterClass())
236
Guido van Rossum8b48cf92001-04-21 13:33:54 +0000237 # Test two-argument iter() with callable instance
238 def test_iter_callable(self):
239 class C:
240 def __init__(self):
241 self.i = 0
242 def __call__(self):
243 i = self.i
244 self.i = i + 1
245 if i > 100:
246 raise IndexError # Emergency stop
247 return i
Kristján Valur Jónsson31668b82012-04-03 10:49:41 +0000248 self.check_iterator(iter(C(), 10), list(range(10)), pickle=False)
Guido van Rossum8b48cf92001-04-21 13:33:54 +0000249
250 # Test two-argument iter() with function
251 def test_iter_function(self):
252 def spam(state=[0]):
253 i = state[0]
254 state[0] = i+1
255 return i
Kristján Valur Jónsson31668b82012-04-03 10:49:41 +0000256 self.check_iterator(iter(spam, 10), list(range(10)), pickle=False)
Guido van Rossum8b48cf92001-04-21 13:33:54 +0000257
258 # Test two-argument iter() with function that raises StopIteration
259 def test_iter_function_stop(self):
260 def spam(state=[0]):
261 i = state[0]
262 if i == 10:
263 raise StopIteration
264 state[0] = i+1
265 return i
Kristján Valur Jónsson31668b82012-04-03 10:49:41 +0000266 self.check_iterator(iter(spam, 20), list(range(10)), pickle=False)
Guido van Rossum8b48cf92001-04-21 13:33:54 +0000267
268 # Test exception propagation through function iterator
269 def test_exception_function(self):
270 def spam(state=[0]):
271 i = state[0]
272 state[0] = i+1
273 if i == 10:
274 raise RuntimeError
275 return i
276 res = []
277 try:
278 for x in iter(spam, 20):
279 res.append(x)
280 except RuntimeError:
Guido van Rossum805365e2007-05-07 22:24:25 +0000281 self.assertEqual(res, list(range(10)))
Guido van Rossum8b48cf92001-04-21 13:33:54 +0000282 else:
283 self.fail("should have raised RuntimeError")
284
285 # Test exception propagation through sequence iterator
286 def test_exception_sequence(self):
287 class MySequenceClass(SequenceClass):
288 def __getitem__(self, i):
289 if i == 10:
290 raise RuntimeError
291 return SequenceClass.__getitem__(self, i)
292 res = []
293 try:
294 for x in MySequenceClass(20):
295 res.append(x)
296 except RuntimeError:
Guido van Rossum805365e2007-05-07 22:24:25 +0000297 self.assertEqual(res, list(range(10)))
Guido van Rossum8b48cf92001-04-21 13:33:54 +0000298 else:
299 self.fail("should have raised RuntimeError")
300
301 # Test for StopIteration from __getitem__
302 def test_stop_sequence(self):
303 class MySequenceClass(SequenceClass):
304 def __getitem__(self, i):
305 if i == 10:
306 raise StopIteration
307 return SequenceClass.__getitem__(self, i)
Kristján Valur Jónsson31668b82012-04-03 10:49:41 +0000308 self.check_for_loop(MySequenceClass(20), list(range(10)), pickle=False)
Guido van Rossum8b48cf92001-04-21 13:33:54 +0000309
310 # Test a big range
311 def test_iter_big_range(self):
Guido van Rossum805365e2007-05-07 22:24:25 +0000312 self.check_for_loop(iter(range(10000)), list(range(10000)))
Guido van Rossum8b48cf92001-04-21 13:33:54 +0000313
314 # Test an empty list
315 def test_iter_empty(self):
316 self.check_for_loop(iter([]), [])
317
318 # Test a tuple
319 def test_iter_tuple(self):
Guido van Rossum805365e2007-05-07 22:24:25 +0000320 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 +0000321
Guido van Rossum805365e2007-05-07 22:24:25 +0000322 # Test a range
323 def test_iter_range(self):
324 self.check_for_loop(iter(range(10)), list(range(10)))
Guido van Rossum8b48cf92001-04-21 13:33:54 +0000325
326 # Test a string
327 def test_iter_string(self):
328 self.check_for_loop(iter("abcde"), ["a", "b", "c", "d", "e"])
329
Guido van Rossum8b48cf92001-04-21 13:33:54 +0000330 # Test a directory
331 def test_iter_dict(self):
332 dict = {}
333 for i in range(10):
334 dict[i] = None
Brett Cannon0caf6d82007-02-22 04:49:03 +0000335 self.check_for_loop(dict, list(dict.keys()))
Guido van Rossum8b48cf92001-04-21 13:33:54 +0000336
337 # Test a file
338 def test_iter_file(self):
339 f = open(TESTFN, "w")
340 try:
341 for i in range(5):
342 f.write("%d\n" % i)
343 finally:
344 f.close()
345 f = open(TESTFN, "r")
346 try:
Kristján Valur Jónsson31668b82012-04-03 10:49:41 +0000347 self.check_for_loop(f, ["0\n", "1\n", "2\n", "3\n", "4\n"], pickle=False)
348 self.check_for_loop(f, [], pickle=False)
Guido van Rossum8b48cf92001-04-21 13:33:54 +0000349 finally:
350 f.close()
351 try:
352 unlink(TESTFN)
353 except OSError:
354 pass
355
Tim Petersf553f892001-05-01 20:45:31 +0000356 # Test list()'s use of iterators.
357 def test_builtin_list(self):
Guido van Rossum805365e2007-05-07 22:24:25 +0000358 self.assertEqual(list(SequenceClass(5)), list(range(5)))
Tim Petersf553f892001-05-01 20:45:31 +0000359 self.assertEqual(list(SequenceClass(0)), [])
360 self.assertEqual(list(()), [])
Tim Petersf553f892001-05-01 20:45:31 +0000361
362 d = {"one": 1, "two": 2, "three": 3}
Brett Cannon0caf6d82007-02-22 04:49:03 +0000363 self.assertEqual(list(d), list(d.keys()))
Tim Petersf553f892001-05-01 20:45:31 +0000364
365 self.assertRaises(TypeError, list, list)
366 self.assertRaises(TypeError, list, 42)
367
368 f = open(TESTFN, "w")
369 try:
370 for i in range(5):
371 f.write("%d\n" % i)
372 finally:
373 f.close()
374 f = open(TESTFN, "r")
375 try:
376 self.assertEqual(list(f), ["0\n", "1\n", "2\n", "3\n", "4\n"])
377 f.seek(0, 0)
Guido van Rossum8ee52432002-08-06 17:14:04 +0000378 self.assertEqual(list(f),
Tim Petersf553f892001-05-01 20:45:31 +0000379 ["0\n", "1\n", "2\n", "3\n", "4\n"])
380 finally:
381 f.close()
382 try:
383 unlink(TESTFN)
384 except OSError:
385 pass
386
Tim Peters6912d4d2001-05-05 03:56:37 +0000387 # Test tuples()'s use of iterators.
388 def test_builtin_tuple(self):
389 self.assertEqual(tuple(SequenceClass(5)), (0, 1, 2, 3, 4))
390 self.assertEqual(tuple(SequenceClass(0)), ())
391 self.assertEqual(tuple([]), ())
392 self.assertEqual(tuple(()), ())
393 self.assertEqual(tuple("abc"), ("a", "b", "c"))
394
395 d = {"one": 1, "two": 2, "three": 3}
396 self.assertEqual(tuple(d), tuple(d.keys()))
397
398 self.assertRaises(TypeError, tuple, list)
399 self.assertRaises(TypeError, tuple, 42)
400
401 f = open(TESTFN, "w")
402 try:
403 for i in range(5):
404 f.write("%d\n" % i)
405 finally:
406 f.close()
407 f = open(TESTFN, "r")
408 try:
409 self.assertEqual(tuple(f), ("0\n", "1\n", "2\n", "3\n", "4\n"))
410 f.seek(0, 0)
Guido van Rossum8ee52432002-08-06 17:14:04 +0000411 self.assertEqual(tuple(f),
Tim Peters6912d4d2001-05-05 03:56:37 +0000412 ("0\n", "1\n", "2\n", "3\n", "4\n"))
413 finally:
414 f.close()
415 try:
416 unlink(TESTFN)
417 except OSError:
418 pass
419
Tim Peters0e57abf2001-05-02 07:39:38 +0000420 # Test filter()'s use of iterators.
421 def test_builtin_filter(self):
Guido van Rossumc1f779c2007-07-03 08:25:58 +0000422 self.assertEqual(list(filter(None, SequenceClass(5))),
423 list(range(1, 5)))
424 self.assertEqual(list(filter(None, SequenceClass(0))), [])
425 self.assertEqual(list(filter(None, ())), [])
426 self.assertEqual(list(filter(None, "abc")), ["a", "b", "c"])
Tim Peters0e57abf2001-05-02 07:39:38 +0000427
428 d = {"one": 1, "two": 2, "three": 3}
Guido van Rossumc1f779c2007-07-03 08:25:58 +0000429 self.assertEqual(list(filter(None, d)), list(d.keys()))
Tim Peters0e57abf2001-05-02 07:39:38 +0000430
431 self.assertRaises(TypeError, filter, None, list)
432 self.assertRaises(TypeError, filter, None, 42)
433
434 class Boolean:
435 def __init__(self, truth):
436 self.truth = truth
Jack Diederich4dafcc42006-11-28 19:15:13 +0000437 def __bool__(self):
Tim Peters0e57abf2001-05-02 07:39:38 +0000438 return self.truth
Jack Diederich4dafcc42006-11-28 19:15:13 +0000439 bTrue = Boolean(True)
440 bFalse = Boolean(False)
Tim Peters0e57abf2001-05-02 07:39:38 +0000441
442 class Seq:
443 def __init__(self, *args):
444 self.vals = args
445 def __iter__(self):
446 class SeqIter:
447 def __init__(self, vals):
448 self.vals = vals
449 self.i = 0
450 def __iter__(self):
451 return self
Georg Brandla18af4e2007-04-21 15:47:16 +0000452 def __next__(self):
Tim Peters0e57abf2001-05-02 07:39:38 +0000453 i = self.i
454 self.i = i + 1
455 if i < len(self.vals):
456 return self.vals[i]
457 else:
458 raise StopIteration
459 return SeqIter(self.vals)
460
Tim Peterscae330e2002-12-23 16:50:58 +0000461 seq = Seq(*([bTrue, bFalse] * 25))
Guido van Rossumc1f779c2007-07-03 08:25:58 +0000462 self.assertEqual(list(filter(lambda x: not x, seq)), [bFalse]*25)
463 self.assertEqual(list(filter(lambda x: not x, iter(seq))), [bFalse]*25)
Tim Peters0e57abf2001-05-02 07:39:38 +0000464
Tim Petersc3074532001-05-03 07:00:32 +0000465 # Test max() and min()'s use of iterators.
466 def test_builtin_max_min(self):
467 self.assertEqual(max(SequenceClass(5)), 4)
468 self.assertEqual(min(SequenceClass(5)), 0)
469 self.assertEqual(max(8, -1), 8)
470 self.assertEqual(min(8, -1), -1)
471
472 d = {"one": 1, "two": 2, "three": 3}
473 self.assertEqual(max(d), "two")
474 self.assertEqual(min(d), "one")
Guido van Rossumcc2b0162007-02-11 06:12:03 +0000475 self.assertEqual(max(d.values()), 3)
476 self.assertEqual(min(iter(d.values())), 1)
Tim Petersc3074532001-05-03 07:00:32 +0000477
Tim Petersc3074532001-05-03 07:00:32 +0000478 f = open(TESTFN, "w")
479 try:
480 f.write("medium line\n")
481 f.write("xtra large line\n")
482 f.write("itty-bitty line\n")
483 finally:
484 f.close()
485 f = open(TESTFN, "r")
486 try:
487 self.assertEqual(min(f), "itty-bitty line\n")
488 f.seek(0, 0)
489 self.assertEqual(max(f), "xtra large line\n")
490 finally:
491 f.close()
492 try:
493 unlink(TESTFN)
494 except OSError:
495 pass
496
Tim Peters4e9afdc2001-05-03 23:54:49 +0000497 # Test map()'s use of iterators.
498 def test_builtin_map(self):
Guido van Rossumc1f779c2007-07-03 08:25:58 +0000499 self.assertEqual(list(map(lambda x: x+1, SequenceClass(5))),
500 list(range(1, 6)))
Tim Peters4e9afdc2001-05-03 23:54:49 +0000501
502 d = {"one": 1, "two": 2, "three": 3}
Guido van Rossumc1f779c2007-07-03 08:25:58 +0000503 self.assertEqual(list(map(lambda k, d=d: (k, d[k]), d)),
504 list(d.items()))
Brett Cannon0caf6d82007-02-22 04:49:03 +0000505 dkeys = list(d.keys())
Tim Peters4e9afdc2001-05-03 23:54:49 +0000506 expected = [(i < len(d) and dkeys[i] or None,
507 i,
508 i < len(d) and dkeys[i] or None)
Guido van Rossumc1f779c2007-07-03 08:25:58 +0000509 for i in range(3)]
Tim Peters4e9afdc2001-05-03 23:54:49 +0000510
511 f = open(TESTFN, "w")
512 try:
513 for i in range(10):
514 f.write("xy" * i + "\n") # line i has len 2*i+1
515 finally:
516 f.close()
517 f = open(TESTFN, "r")
518 try:
Guido van Rossumc1f779c2007-07-03 08:25:58 +0000519 self.assertEqual(list(map(len, f)), list(range(1, 21, 2)))
Tim Peters4e9afdc2001-05-03 23:54:49 +0000520 finally:
521 f.close()
522 try:
523 unlink(TESTFN)
524 except OSError:
525 pass
526
Tim Peters8572b4f2001-05-06 01:05:02 +0000527 # Test zip()'s use of iterators.
528 def test_builtin_zip(self):
Guido van Rossum801f0d72006-08-24 19:48:10 +0000529 self.assertEqual(list(zip()), [])
530 self.assertEqual(list(zip(*[])), [])
531 self.assertEqual(list(zip(*[(1, 2), 'ab'])), [(1, 'a'), (2, 'b')])
Raymond Hettingereaef6152003-08-02 07:42:57 +0000532
Tim Peters8572b4f2001-05-06 01:05:02 +0000533 self.assertRaises(TypeError, zip, None)
534 self.assertRaises(TypeError, zip, range(10), 42)
535 self.assertRaises(TypeError, zip, range(10), zip)
536
Guido van Rossum801f0d72006-08-24 19:48:10 +0000537 self.assertEqual(list(zip(IteratingSequenceClass(3))),
Tim Peters8572b4f2001-05-06 01:05:02 +0000538 [(0,), (1,), (2,)])
Guido van Rossum801f0d72006-08-24 19:48:10 +0000539 self.assertEqual(list(zip(SequenceClass(3))),
Tim Peters8572b4f2001-05-06 01:05:02 +0000540 [(0,), (1,), (2,)])
541
542 d = {"one": 1, "two": 2, "three": 3}
Brett Cannon0caf6d82007-02-22 04:49:03 +0000543 self.assertEqual(list(d.items()), list(zip(d, d.values())))
Tim Peters8572b4f2001-05-06 01:05:02 +0000544
545 # Generate all ints starting at constructor arg.
546 class IntsFrom:
547 def __init__(self, start):
548 self.i = start
549
550 def __iter__(self):
551 return self
552
Georg Brandla18af4e2007-04-21 15:47:16 +0000553 def __next__(self):
Tim Peters8572b4f2001-05-06 01:05:02 +0000554 i = self.i
555 self.i = i+1
556 return i
557
558 f = open(TESTFN, "w")
559 try:
560 f.write("a\n" "bbb\n" "cc\n")
561 finally:
562 f.close()
563 f = open(TESTFN, "r")
564 try:
Guido van Rossum801f0d72006-08-24 19:48:10 +0000565 self.assertEqual(list(zip(IntsFrom(0), f, IntsFrom(-100))),
Tim Peters8572b4f2001-05-06 01:05:02 +0000566 [(0, "a\n", -100),
567 (1, "bbb\n", -99),
568 (2, "cc\n", -98)])
569 finally:
570 f.close()
571 try:
572 unlink(TESTFN)
573 except OSError:
574 pass
575
Guido van Rossum805365e2007-05-07 22:24:25 +0000576 self.assertEqual(list(zip(range(5))), [(i,) for i in range(5)])
Tim Peters67d687a2002-04-29 21:27:32 +0000577
578 # Classes that lie about their lengths.
579 class NoGuessLen5:
580 def __getitem__(self, i):
581 if i >= 5:
582 raise IndexError
583 return i
584
585 class Guess3Len5(NoGuessLen5):
586 def __len__(self):
587 return 3
588
589 class Guess30Len5(NoGuessLen5):
590 def __len__(self):
591 return 30
592
Guido van Rossum801f0d72006-08-24 19:48:10 +0000593 def lzip(*args):
594 return list(zip(*args))
595
Tim Peters67d687a2002-04-29 21:27:32 +0000596 self.assertEqual(len(Guess3Len5()), 3)
597 self.assertEqual(len(Guess30Len5()), 30)
Guido van Rossum801f0d72006-08-24 19:48:10 +0000598 self.assertEqual(lzip(NoGuessLen5()), lzip(range(5)))
599 self.assertEqual(lzip(Guess3Len5()), lzip(range(5)))
600 self.assertEqual(lzip(Guess30Len5()), lzip(range(5)))
Tim Peters67d687a2002-04-29 21:27:32 +0000601
602 expected = [(i, i) for i in range(5)]
603 for x in NoGuessLen5(), Guess3Len5(), Guess30Len5():
604 for y in NoGuessLen5(), Guess3Len5(), Guess30Len5():
Guido van Rossum801f0d72006-08-24 19:48:10 +0000605 self.assertEqual(lzip(x, y), expected)
Tim Peters67d687a2002-04-29 21:27:32 +0000606
Tim Peters2cfe3682001-05-05 05:36:48 +0000607 def test_unicode_join_endcase(self):
608
609 # This class inserts a Unicode object into its argument's natural
610 # iteration, in the 3rd position.
611 class OhPhooey:
612 def __init__(self, seq):
613 self.it = iter(seq)
614 self.i = 0
615
616 def __iter__(self):
617 return self
618
Georg Brandla18af4e2007-04-21 15:47:16 +0000619 def __next__(self):
Tim Peters2cfe3682001-05-05 05:36:48 +0000620 i = self.i
621 self.i = i+1
622 if i == 2:
Walter Dörwald1f5947b2007-05-22 16:52:54 +0000623 return "fooled you!"
Georg Brandla18af4e2007-04-21 15:47:16 +0000624 return next(self.it)
Tim Peters2cfe3682001-05-05 05:36:48 +0000625
626 f = open(TESTFN, "w")
627 try:
628 f.write("a\n" + "b\n" + "c\n")
629 finally:
630 f.close()
631
632 f = open(TESTFN, "r")
633 # Nasty: string.join(s) can't know whether unicode.join() is needed
634 # until it's seen all of s's elements. But in this case, f's
635 # iterator cannot be restarted. So what we're testing here is
636 # whether string.join() can manage to remember everything it's seen
637 # and pass that on to unicode.join().
638 try:
639 got = " - ".join(OhPhooey(f))
Walter Dörwald5de48bd2007-06-11 21:38:39 +0000640 self.assertEqual(got, "a\n - b\n - fooled you! - c\n")
Tim Peters2cfe3682001-05-05 05:36:48 +0000641 finally:
642 f.close()
643 try:
644 unlink(TESTFN)
645 except OSError:
646 pass
647
Tim Petersde9725f2001-05-05 10:06:17 +0000648 # Test iterators with 'x in y' and 'x not in y'.
649 def test_in_and_not_in(self):
Tim Peterscb8d3682001-05-05 21:05:01 +0000650 for sc5 in IteratingSequenceClass(5), SequenceClass(5):
651 for i in range(5):
Benjamin Peterson577473f2010-01-19 00:09:57 +0000652 self.assertIn(i, sc5)
Tim Peterscb8d3682001-05-05 21:05:01 +0000653 for i in "abc", -1, 5, 42.42, (3, 4), [], {1: 1}, 3-12j, sc5:
Benjamin Peterson577473f2010-01-19 00:09:57 +0000654 self.assertNotIn(i, sc5)
Tim Petersde9725f2001-05-05 10:06:17 +0000655
Serhiy Storchaka18b711c2019-08-04 14:12:48 +0300656 self.assertIn(ALWAYS_EQ, IteratorProxyClass(iter([1])))
657 self.assertIn(ALWAYS_EQ, SequenceProxyClass([1]))
658 self.assertNotIn(ALWAYS_EQ, IteratorProxyClass(iter([NEVER_EQ])))
659 self.assertNotIn(ALWAYS_EQ, SequenceProxyClass([NEVER_EQ]))
660 self.assertIn(NEVER_EQ, IteratorProxyClass(iter([ALWAYS_EQ])))
661 self.assertIn(NEVER_EQ, SequenceProxyClass([ALWAYS_EQ]))
662
Tim Petersde9725f2001-05-05 10:06:17 +0000663 self.assertRaises(TypeError, lambda: 3 in 12)
664 self.assertRaises(TypeError, lambda: 3 not in map)
Miss Islington (bot)353c4ba2020-06-22 01:20:56 -0700665 self.assertRaises(ZeroDivisionError, lambda: 3 in BadIterableClass())
Tim Petersde9725f2001-05-05 10:06:17 +0000666
667 d = {"one": 1, "two": 2, "three": 3, 1j: 2j}
668 for k in d:
Benjamin Peterson577473f2010-01-19 00:09:57 +0000669 self.assertIn(k, d)
670 self.assertNotIn(k, d.values())
Tim Petersde9725f2001-05-05 10:06:17 +0000671 for v in d.values():
Benjamin Peterson577473f2010-01-19 00:09:57 +0000672 self.assertIn(v, d.values())
673 self.assertNotIn(v, d)
Guido van Rossumcc2b0162007-02-11 06:12:03 +0000674 for k, v in d.items():
Benjamin Peterson577473f2010-01-19 00:09:57 +0000675 self.assertIn((k, v), d.items())
676 self.assertNotIn((v, k), d.items())
Tim Petersde9725f2001-05-05 10:06:17 +0000677
678 f = open(TESTFN, "w")
679 try:
680 f.write("a\n" "b\n" "c\n")
681 finally:
682 f.close()
683 f = open(TESTFN, "r")
684 try:
685 for chunk in "abc":
686 f.seek(0, 0)
Benjamin Peterson577473f2010-01-19 00:09:57 +0000687 self.assertNotIn(chunk, f)
Tim Petersde9725f2001-05-05 10:06:17 +0000688 f.seek(0, 0)
Benjamin Peterson577473f2010-01-19 00:09:57 +0000689 self.assertIn((chunk + "\n"), f)
Tim Petersde9725f2001-05-05 10:06:17 +0000690 finally:
691 f.close()
692 try:
693 unlink(TESTFN)
694 except OSError:
695 pass
696
Tim Peters75f8e352001-05-05 11:33:43 +0000697 # Test iterators with operator.countOf (PySequence_Count).
698 def test_countOf(self):
699 from operator import countOf
700 self.assertEqual(countOf([1,2,2,3,2,5], 2), 3)
701 self.assertEqual(countOf((1,2,2,3,2,5), 2), 3)
702 self.assertEqual(countOf("122325", "2"), 3)
703 self.assertEqual(countOf("122325", "6"), 0)
704
705 self.assertRaises(TypeError, countOf, 42, 1)
706 self.assertRaises(TypeError, countOf, countOf, countOf)
707
708 d = {"one": 3, "two": 3, "three": 3, 1j: 2j}
709 for k in d:
710 self.assertEqual(countOf(d, k), 1)
Guido van Rossumcc2b0162007-02-11 06:12:03 +0000711 self.assertEqual(countOf(d.values(), 3), 3)
712 self.assertEqual(countOf(d.values(), 2j), 1)
713 self.assertEqual(countOf(d.values(), 1j), 0)
Tim Peters75f8e352001-05-05 11:33:43 +0000714
715 f = open(TESTFN, "w")
716 try:
717 f.write("a\n" "b\n" "c\n" "b\n")
718 finally:
719 f.close()
720 f = open(TESTFN, "r")
721 try:
722 for letter, count in ("a", 1), ("b", 2), ("c", 1), ("d", 0):
723 f.seek(0, 0)
724 self.assertEqual(countOf(f, letter + "\n"), count)
725 finally:
726 f.close()
727 try:
728 unlink(TESTFN)
729 except OSError:
730 pass
731
Tim Peters16a77ad2001-09-08 04:00:12 +0000732 # Test iterators with operator.indexOf (PySequence_Index).
733 def test_indexOf(self):
734 from operator import indexOf
735 self.assertEqual(indexOf([1,2,2,3,2,5], 1), 0)
736 self.assertEqual(indexOf((1,2,2,3,2,5), 2), 1)
737 self.assertEqual(indexOf((1,2,2,3,2,5), 3), 3)
738 self.assertEqual(indexOf((1,2,2,3,2,5), 5), 5)
739 self.assertRaises(ValueError, indexOf, (1,2,2,3,2,5), 0)
740 self.assertRaises(ValueError, indexOf, (1,2,2,3,2,5), 6)
741
742 self.assertEqual(indexOf("122325", "2"), 1)
743 self.assertEqual(indexOf("122325", "5"), 5)
744 self.assertRaises(ValueError, indexOf, "122325", "6")
745
746 self.assertRaises(TypeError, indexOf, 42, 1)
747 self.assertRaises(TypeError, indexOf, indexOf, indexOf)
Miss Islington (bot)353c4ba2020-06-22 01:20:56 -0700748 self.assertRaises(ZeroDivisionError, indexOf, BadIterableClass(), 1)
Tim Peters16a77ad2001-09-08 04:00:12 +0000749
750 f = open(TESTFN, "w")
751 try:
752 f.write("a\n" "b\n" "c\n" "d\n" "e\n")
753 finally:
754 f.close()
755 f = open(TESTFN, "r")
756 try:
757 fiter = iter(f)
758 self.assertEqual(indexOf(fiter, "b\n"), 1)
759 self.assertEqual(indexOf(fiter, "d\n"), 1)
760 self.assertEqual(indexOf(fiter, "e\n"), 0)
761 self.assertRaises(ValueError, indexOf, fiter, "a\n")
762 finally:
763 f.close()
764 try:
765 unlink(TESTFN)
766 except OSError:
767 pass
768
769 iclass = IteratingSequenceClass(3)
770 for i in range(3):
771 self.assertEqual(indexOf(iclass, i), i)
772 self.assertRaises(ValueError, indexOf, iclass, -1)
773
Tim Peters2c9aa5e2001-09-23 04:06:05 +0000774 # Test iterators with file.writelines().
775 def test_writelines(self):
Alex Martelli01c77c62006-08-24 02:58:11 +0000776 f = open(TESTFN, "w")
Tim Peters2c9aa5e2001-09-23 04:06:05 +0000777
778 try:
779 self.assertRaises(TypeError, f.writelines, None)
780 self.assertRaises(TypeError, f.writelines, 42)
Tim Peters527e64f2001-10-04 05:36:56 +0000781
Tim Peters2c9aa5e2001-09-23 04:06:05 +0000782 f.writelines(["1\n", "2\n"])
783 f.writelines(("3\n", "4\n"))
784 f.writelines({'5\n': None})
785 f.writelines({})
786
787 # Try a big chunk too.
788 class Iterator:
789 def __init__(self, start, finish):
790 self.start = start
791 self.finish = finish
792 self.i = self.start
793
Georg Brandla18af4e2007-04-21 15:47:16 +0000794 def __next__(self):
Tim Peters2c9aa5e2001-09-23 04:06:05 +0000795 if self.i >= self.finish:
796 raise StopIteration
797 result = str(self.i) + '\n'
798 self.i += 1
799 return result
800
801 def __iter__(self):
802 return self
803
804 class Whatever:
805 def __init__(self, start, finish):
806 self.start = start
807 self.finish = finish
808
809 def __iter__(self):
810 return Iterator(self.start, self.finish)
Tim Peters527e64f2001-10-04 05:36:56 +0000811
812 f.writelines(Whatever(6, 6+2000))
Tim Peters2c9aa5e2001-09-23 04:06:05 +0000813 f.close()
814
Alex Martelli01c77c62006-08-24 02:58:11 +0000815 f = open(TESTFN)
Tim Peters2c9aa5e2001-09-23 04:06:05 +0000816 expected = [str(i) + "\n" for i in range(1, 2006)]
817 self.assertEqual(list(f), expected)
Tim Peters527e64f2001-10-04 05:36:56 +0000818
Tim Peters2c9aa5e2001-09-23 04:06:05 +0000819 finally:
820 f.close()
821 try:
822 unlink(TESTFN)
823 except OSError:
824 pass
825
826
Tim Petersd6d010b2001-06-21 02:49:55 +0000827 # Test iterators on RHS of unpacking assignments.
828 def test_unpack_iter(self):
829 a, b = 1, 2
830 self.assertEqual((a, b), (1, 2))
831
832 a, b, c = IteratingSequenceClass(3)
833 self.assertEqual((a, b, c), (0, 1, 2))
834
835 try: # too many values
836 a, b = IteratingSequenceClass(3)
837 except ValueError:
838 pass
839 else:
840 self.fail("should have raised ValueError")
841
842 try: # not enough values
843 a, b, c = IteratingSequenceClass(2)
844 except ValueError:
845 pass
846 else:
847 self.fail("should have raised ValueError")
848
849 try: # not iterable
850 a, b, c = len
851 except TypeError:
852 pass
853 else:
854 self.fail("should have raised TypeError")
855
Guido van Rossumcc2b0162007-02-11 06:12:03 +0000856 a, b, c = {1: 42, 2: 42, 3: 42}.values()
Tim Petersd6d010b2001-06-21 02:49:55 +0000857 self.assertEqual((a, b, c), (42, 42, 42))
858
859 f = open(TESTFN, "w")
860 lines = ("a\n", "bb\n", "ccc\n")
861 try:
862 for line in lines:
863 f.write(line)
864 finally:
865 f.close()
866 f = open(TESTFN, "r")
867 try:
868 a, b, c = f
869 self.assertEqual((a, b, c), lines)
870 finally:
871 f.close()
872 try:
873 unlink(TESTFN)
874 except OSError:
875 pass
876
877 (a, b), (c,) = IteratingSequenceClass(2), {42: 24}
878 self.assertEqual((a, b, c), (0, 1, 42))
879
Guido van Rossumbb8f59a2001-12-03 19:33:25 +0000880
Benjamin Peterson945c5792010-06-22 20:34:34 +0000881 @cpython_only
882 def test_ref_counting_behavior(self):
Guido van Rossumbb8f59a2001-12-03 19:33:25 +0000883 class C(object):
884 count = 0
885 def __new__(cls):
886 cls.count += 1
887 return object.__new__(cls)
888 def __del__(self):
889 cls = self.__class__
890 assert cls.count > 0
891 cls.count -= 1
892 x = C()
893 self.assertEqual(C.count, 1)
894 del x
895 self.assertEqual(C.count, 0)
896 l = [C(), C(), C()]
897 self.assertEqual(C.count, 3)
898 try:
899 a, b = iter(l)
900 except ValueError:
901 pass
902 del l
903 self.assertEqual(C.count, 0)
Fred Drake2e2be372001-09-20 21:33:42 +0000904
Guido van Rossum674eae62002-07-16 21:48:11 +0000905
906 # Make sure StopIteration is a "sink state".
907 # This tests various things that weren't sink states in Python 2.2.1,
908 # plus various things that always were fine.
909
910 def test_sinkstate_list(self):
911 # This used to fail
Guido van Rossum805365e2007-05-07 22:24:25 +0000912 a = list(range(5))
Guido van Rossum674eae62002-07-16 21:48:11 +0000913 b = iter(a)
Guido van Rossum805365e2007-05-07 22:24:25 +0000914 self.assertEqual(list(b), list(range(5)))
Guido van Rossum674eae62002-07-16 21:48:11 +0000915 a.extend(range(5, 10))
916 self.assertEqual(list(b), [])
917
918 def test_sinkstate_tuple(self):
919 a = (0, 1, 2, 3, 4)
920 b = iter(a)
Guido van Rossum805365e2007-05-07 22:24:25 +0000921 self.assertEqual(list(b), list(range(5)))
Guido van Rossum674eae62002-07-16 21:48:11 +0000922 self.assertEqual(list(b), [])
923
924 def test_sinkstate_string(self):
925 a = "abcde"
926 b = iter(a)
927 self.assertEqual(list(b), ['a', 'b', 'c', 'd', 'e'])
928 self.assertEqual(list(b), [])
929
930 def test_sinkstate_sequence(self):
931 # This used to fail
932 a = SequenceClass(5)
933 b = iter(a)
Guido van Rossum805365e2007-05-07 22:24:25 +0000934 self.assertEqual(list(b), list(range(5)))
Guido van Rossum674eae62002-07-16 21:48:11 +0000935 a.n = 10
936 self.assertEqual(list(b), [])
937
938 def test_sinkstate_callable(self):
939 # This used to fail
940 def spam(state=[0]):
941 i = state[0]
942 state[0] = i+1
943 if i == 10:
Collin Winter3add4d72007-08-29 23:37:32 +0000944 raise AssertionError("shouldn't have gotten this far")
Guido van Rossum674eae62002-07-16 21:48:11 +0000945 return i
946 b = iter(spam, 5)
Guido van Rossum805365e2007-05-07 22:24:25 +0000947 self.assertEqual(list(b), list(range(5)))
Guido van Rossum674eae62002-07-16 21:48:11 +0000948 self.assertEqual(list(b), [])
949
950 def test_sinkstate_dict(self):
951 # XXX For a more thorough test, see towards the end of:
952 # http://mail.python.org/pipermail/python-dev/2002-July/026512.html
953 a = {1:1, 2:2, 0:0, 4:4, 3:3}
Guido van Rossumcc2b0162007-02-11 06:12:03 +0000954 for b in iter(a), a.keys(), a.items(), a.values():
Guido van Rossum674eae62002-07-16 21:48:11 +0000955 b = iter(a)
956 self.assertEqual(len(list(b)), 5)
957 self.assertEqual(list(b), [])
958
959 def test_sinkstate_yield(self):
960 def gen():
961 for i in range(5):
962 yield i
963 b = gen()
Guido van Rossum805365e2007-05-07 22:24:25 +0000964 self.assertEqual(list(b), list(range(5)))
Guido van Rossum674eae62002-07-16 21:48:11 +0000965 self.assertEqual(list(b), [])
966
967 def test_sinkstate_range(self):
Guido van Rossum805365e2007-05-07 22:24:25 +0000968 a = range(5)
Guido van Rossum674eae62002-07-16 21:48:11 +0000969 b = iter(a)
Guido van Rossum805365e2007-05-07 22:24:25 +0000970 self.assertEqual(list(b), list(range(5)))
Guido van Rossum674eae62002-07-16 21:48:11 +0000971 self.assertEqual(list(b), [])
972
973 def test_sinkstate_enumerate(self):
974 a = range(5)
975 e = enumerate(a)
976 b = iter(e)
Guido van Rossum801f0d72006-08-24 19:48:10 +0000977 self.assertEqual(list(b), list(zip(range(5), range(5))))
Guido van Rossum674eae62002-07-16 21:48:11 +0000978 self.assertEqual(list(b), [])
979
Amaury Forgeot d'Arcf343e012009-01-12 23:58:21 +0000980 def test_3720(self):
981 # Avoid a crash, when an iterator deletes its next() method.
982 class BadIterator(object):
983 def __iter__(self):
984 return self
985 def __next__(self):
986 del BadIterator.__next__
987 return 1
988
989 try:
990 for i in BadIterator() :
991 pass
992 except TypeError:
993 pass
994
Ezio Melotti739e1792012-11-18 23:16:02 +0200995 def test_extending_list_with_iterator_does_not_segfault(self):
996 # The code to extend a list with an iterator has a fair
997 # amount of nontrivial logic in terms of guessing how
998 # much memory to allocate in advance, "stealing" refs,
999 # and then shrinking at the end. This is a basic smoke
1000 # test for that scenario.
1001 def gen():
1002 for i in range(500):
1003 yield i
1004 lst = [0] * 500
1005 for i in range(240):
1006 lst.pop(0)
1007 lst.extend(gen())
1008 self.assertEqual(len(lst), 760)
1009
Serhiy Storchaka4faf5c52015-05-21 20:50:25 +03001010 @cpython_only
1011 def test_iter_overflow(self):
1012 # Test for the issue 22939
1013 it = iter(UnlimitedSequenceClass())
1014 # Manually set `it_index` to PY_SSIZE_T_MAX-2 without a loop
1015 it.__setstate__(sys.maxsize - 2)
1016 self.assertEqual(next(it), sys.maxsize - 2)
1017 self.assertEqual(next(it), sys.maxsize - 1)
1018 with self.assertRaises(OverflowError):
1019 next(it)
1020 # Check that Overflow error is always raised
1021 with self.assertRaises(OverflowError):
1022 next(it)
1023
1024 def test_iter_neg_setstate(self):
1025 it = iter(UnlimitedSequenceClass())
1026 it.__setstate__(-42)
1027 self.assertEqual(next(it), 0)
1028 self.assertEqual(next(it), 1)
1029
Serhiy Storchakafbb1c5e2016-03-30 20:40:02 +03001030 def test_free_after_iterating(self):
1031 check_free_after_iterating(self, iter, SequenceClass, (0,))
1032
Guido van Rossum97c1adf2016-08-18 09:22:23 -07001033 def test_error_iter(self):
1034 for typ in (DefaultIterClass, NoIterClass):
1035 self.assertRaises(TypeError, iter, typ())
Miss Islington (bot)353c4ba2020-06-22 01:20:56 -07001036 self.assertRaises(ZeroDivisionError, iter, BadIterableClass())
Guido van Rossum97c1adf2016-08-18 09:22:23 -07001037
Guido van Rossum674eae62002-07-16 21:48:11 +00001038
Fred Drake2e2be372001-09-20 21:33:42 +00001039def test_main():
1040 run_unittest(TestCase)
1041
1042
1043if __name__ == "__main__":
1044 test_main()