1# Test iterators. 2 3import sys 4import unittest 5from test.support import run_unittest, TESTFN, unlink, cpython_only 6from test.support import check_free_after_iterating, ALWAYS_EQ, NEVER_EQ 7import pickle 8import collections.abc 9 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 29 def __next__(self): 30 res = self.i 31 if res >= self.n: 32 raise StopIteration 33 self.i = res + 1 34 return res 35 def __iter__(self): 36 return self 37 38class IteratingSequenceClass: 39 def __init__(self, n): 40 self.n = n 41 def __iter__(self): 42 return BasicIterClass(self.n) 43 44class 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 52class 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 61class SequenceProxyClass: 62 def __init__(self, s): 63 self.s = s 64 def __getitem__(self, i): 65 return self.s[i] 66 67class UnlimitedSequenceClass: 68 def __getitem__(self, i): 69 return i 70 71class DefaultIterClass: 72 pass 73 74class NoIterClass: 75 def __getitem__(self, i): 76 return i 77 __iter__ = None 78 79class BadIterableClass: 80 def __iter__(self): 81 raise ZeroDivisionError 82 83# Main test suite 84 85class TestCase(unittest.TestCase): 86 87 # Helper to check that an iterator returns a given sequence 88 def check_iterator(self, it, seq, pickle=True): 89 if pickle: 90 self.check_pickle(it, seq) 91 res = [] 92 while 1: 93 try: 94 val = next(it) 95 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 101 def check_for_loop(self, expr, seq, pickle=True): 102 if pickle: 103 self.check_pickle(iter(expr), seq) 104 res = [] 105 for val in expr: 106 res.append(val) 107 self.assertEqual(res, seq) 108 109 # Helper to check picklability 110 def check_pickle(self, itorg, seq): 111 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) 119 120 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:]) 128 129 # Test basic use of iter() function 130 def test_iter_basic(self): 131 self.check_iterator(iter(range(10)), list(range(10))) 132 133 # Test that iter(iter(x)) is the same as iter(x) 134 def test_iter_idempotency(self): 135 seq = list(range(10)) 136 it = iter(seq) 137 it2 = iter(it) 138 self.assertTrue(it is it2) 139 140 # Test that for loops over iterators work 141 def test_iter_for_loop(self): 142 self.check_for_loop(iter(range(10)), list(range(10))) 143 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): 169 self.check_for_loop(IteratingSequenceClass(10), list(range(10))) 170 171 # Test a class with __iter__ with explicit iter() 172 def test_iter_class_iter(self): 173 self.check_iterator(iter(IteratingSequenceClass(10)), list(range(10))) 174 175 # Test for loop on a sequence class without __iter__ 176 def test_seq_class_for(self): 177 self.check_for_loop(SequenceClass(10), list(range(10))) 178 179 # Test iter() on a sequence class without __iter__ 180 def test_seq_class_iter(self): 181 self.check_iterator(iter(SequenceClass(10)), list(range(10))) 182 183 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 219 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 230 # 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 237 # 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 248 self.check_iterator(iter(C(), 10), list(range(10)), pickle=False) 249 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 256 self.check_iterator(iter(spam, 10), list(range(10)), pickle=False) 257 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 266 self.check_iterator(iter(spam, 20), list(range(10)), pickle=False) 267 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: 281 self.assertEqual(res, list(range(10))) 282 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: 297 self.assertEqual(res, list(range(10))) 298 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) 308 self.check_for_loop(MySequenceClass(20), list(range(10)), pickle=False) 309 310 # Test a big range 311 def test_iter_big_range(self): 312 self.check_for_loop(iter(range(10000)), list(range(10000))) 313 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): 320 self.check_for_loop(iter((0,1,2,3,4,5,6,7,8,9)), list(range(10))) 321 322 # Test a range 323 def test_iter_range(self): 324 self.check_for_loop(iter(range(10)), list(range(10))) 325 326 # Test a string 327 def test_iter_string(self): 328 self.check_for_loop(iter("abcde"), ["a", "b", "c", "d", "e"]) 329 330 # Test a directory 331 def test_iter_dict(self): 332 dict = {} 333 for i in range(10): 334 dict[i] = None 335 self.check_for_loop(dict, list(dict.keys())) 336 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: 347 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) 349 finally: 350 f.close() 351 try: 352 unlink(TESTFN) 353 except OSError: 354 pass 355 356 # Test list()'s use of iterators. 357 def test_builtin_list(self): 358 self.assertEqual(list(SequenceClass(5)), list(range(5))) 359 self.assertEqual(list(SequenceClass(0)), []) 360 self.assertEqual(list(()), []) 361 362 d = {"one": 1, "two": 2, "three": 3} 363 self.assertEqual(list(d), list(d.keys())) 364 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) 378 self.assertEqual(list(f), 379 ["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 387 # 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) 411 self.assertEqual(tuple(f), 412 ("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 420 # Test filter()'s use of iterators. 421 def test_builtin_filter(self): 422 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"]) 427 428 d = {"one": 1, "two": 2, "three": 3} 429 self.assertEqual(list(filter(None, d)), list(d.keys())) 430 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 437 def __bool__(self): 438 return self.truth 439 bTrue = Boolean(True) 440 bFalse = Boolean(False) 441 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 452 def __next__(self): 453 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 461 seq = Seq(*([bTrue, bFalse] * 25)) 462 self.assertEqual(list(filter(lambda x: not x, seq)), [bFalse]*25) 463 self.assertEqual(list(filter(lambda x: not x, iter(seq))), [bFalse]*25) 464 465 # 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") 475 self.assertEqual(max(d.values()), 3) 476 self.assertEqual(min(iter(d.values())), 1) 477 478 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 497 # Test map()'s use of iterators. 498 def test_builtin_map(self): 499 self.assertEqual(list(map(lambda x: x+1, SequenceClass(5))), 500 list(range(1, 6))) 501 502 d = {"one": 1, "two": 2, "three": 3} 503 self.assertEqual(list(map(lambda k, d=d: (k, d[k]), d)), 504 list(d.items())) 505 dkeys = list(d.keys()) 506 expected = [(i < len(d) and dkeys[i] or None, 507 i, 508 i < len(d) and dkeys[i] or None) 509 for i in range(3)] 510 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: 519 self.assertEqual(list(map(len, f)), list(range(1, 21, 2))) 520 finally: 521 f.close() 522 try: 523 unlink(TESTFN) 524 except OSError: 525 pass 526 527 # Test zip()'s use of iterators. 528 def test_builtin_zip(self): 529 self.assertEqual(list(zip()), []) 530 self.assertEqual(list(zip(*[])), []) 531 self.assertEqual(list(zip(*[(1, 2), 'ab'])), [(1, 'a'), (2, 'b')]) 532 533 self.assertRaises(TypeError, zip, None) 534 self.assertRaises(TypeError, zip, range(10), 42) 535 self.assertRaises(TypeError, zip, range(10), zip) 536 537 self.assertEqual(list(zip(IteratingSequenceClass(3))), 538 [(0,), (1,), (2,)]) 539 self.assertEqual(list(zip(SequenceClass(3))), 540 [(0,), (1,), (2,)]) 541 542 d = {"one": 1, "two": 2, "three": 3} 543 self.assertEqual(list(d.items()), list(zip(d, d.values()))) 544 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 553 def __next__(self): 554 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: 565 self.assertEqual(list(zip(IntsFrom(0), f, IntsFrom(-100))), 566 [(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 576 self.assertEqual(list(zip(range(5))), [(i,) for i in range(5)]) 577 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 593 def lzip(*args): 594 return list(zip(*args)) 595 596 self.assertEqual(len(Guess3Len5()), 3) 597 self.assertEqual(len(Guess30Len5()), 30) 598 self.assertEqual(lzip(NoGuessLen5()), lzip(range(5))) 599 self.assertEqual(lzip(Guess3Len5()), lzip(range(5))) 600 self.assertEqual(lzip(Guess30Len5()), lzip(range(5))) 601 602 expected = [(i, i) for i in range(5)] 603 for x in NoGuessLen5(), Guess3Len5(), Guess30Len5(): 604 for y in NoGuessLen5(), Guess3Len5(), Guess30Len5(): 605 self.assertEqual(lzip(x, y), expected) 606 607 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 619 def __next__(self): 620 i = self.i 621 self.i = i+1 622 if i == 2: 623 return "fooled you!" 624 return next(self.it) 625 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)) 640 self.assertEqual(got, "a\n - b\n - fooled you! - c\n") 641 finally: 642 f.close() 643 try: 644 unlink(TESTFN) 645 except OSError: 646 pass 647 648 # Test iterators with 'x in y' and 'x not in y'. 649 def test_in_and_not_in(self): 650 for sc5 in IteratingSequenceClass(5), SequenceClass(5): 651 for i in range(5): 652 self.assertIn(i, sc5) 653 for i in "abc", -1, 5, 42.42, (3, 4), [], {1: 1}, 3-12j, sc5: 654 self.assertNotIn(i, sc5) 655 656 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 663 self.assertRaises(TypeError, lambda: 3 in 12) 664 self.assertRaises(TypeError, lambda: 3 not in map) 665 self.assertRaises(ZeroDivisionError, lambda: 3 in BadIterableClass()) 666 667 d = {"one": 1, "two": 2, "three": 3, 1j: 2j} 668 for k in d: 669 self.assertIn(k, d) 670 self.assertNotIn(k, d.values()) 671 for v in d.values(): 672 self.assertIn(v, d.values()) 673 self.assertNotIn(v, d) 674 for k, v in d.items(): 675 self.assertIn((k, v), d.items()) 676 self.assertNotIn((v, k), d.items()) 677 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) 687 self.assertNotIn(chunk, f) 688 f.seek(0, 0) 689 self.assertIn((chunk + "\n"), f) 690 finally: 691 f.close() 692 try: 693 unlink(TESTFN) 694 except OSError: 695 pass 696 697 # 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) 711 self.assertEqual(countOf(d.values(), 3), 3) 712 self.assertEqual(countOf(d.values(), 2j), 1) 713 self.assertEqual(countOf(d.values(), 1j), 0) 714 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 732 # 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) 748 self.assertRaises(ZeroDivisionError, indexOf, BadIterableClass(), 1) 749 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 774 # Test iterators with file.writelines(). 775 def test_writelines(self): 776 f = open(TESTFN, "w") 777 778 try: 779 self.assertRaises(TypeError, f.writelines, None) 780 self.assertRaises(TypeError, f.writelines, 42) 781 782 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 794 def __next__(self): 795 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) 811 812 f.writelines(Whatever(6, 6+2000)) 813 f.close() 814 815 f = open(TESTFN) 816 expected = [str(i) + "\n" for i in range(1, 2006)] 817 self.assertEqual(list(f), expected) 818 819 finally: 820 f.close() 821 try: 822 unlink(TESTFN) 823 except OSError: 824 pass 825 826 827 # 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 856 a, b, c = {1: 42, 2: 42, 3: 42}.values() 857 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 880 881 @cpython_only 882 def test_ref_counting_behavior(self): 883 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) 904 905 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 912 a = list(range(5)) 913 b = iter(a) 914 self.assertEqual(list(b), list(range(5))) 915 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) 921 self.assertEqual(list(b), list(range(5))) 922 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) 934 self.assertEqual(list(b), list(range(5))) 935 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: 944 raise AssertionError("shouldn't have gotten this far") 945 return i 946 b = iter(spam, 5) 947 self.assertEqual(list(b), list(range(5))) 948 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} 954 for b in iter(a), a.keys(), a.items(), a.values(): 955 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() 964 self.assertEqual(list(b), list(range(5))) 965 self.assertEqual(list(b), []) 966 967 def test_sinkstate_range(self): 968 a = range(5) 969 b = iter(a) 970 self.assertEqual(list(b), list(range(5))) 971 self.assertEqual(list(b), []) 972 973 def test_sinkstate_enumerate(self): 974 a = range(5) 975 e = enumerate(a) 976 b = iter(e) 977 self.assertEqual(list(b), list(zip(range(5), range(5)))) 978 self.assertEqual(list(b), []) 979 980 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 995 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 1010 @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 1030 def test_free_after_iterating(self): 1031 check_free_after_iterating(self, iter, SequenceClass, (0,)) 1032 1033 def test_error_iter(self): 1034 for typ in (DefaultIterClass, NoIterClass): 1035 self.assertRaises(TypeError, iter, typ()) 1036 self.assertRaises(ZeroDivisionError, iter, BadIterableClass()) 1037 1038 1039def test_main(): 1040 run_unittest(TestCase) 1041 1042 1043if __name__ == "__main__": 1044 test_main() 1045