1 # Test iterators. 2 3 import unittest 4 from test.test_support import run_unittest, TESTFN, unlink, have_unicode, \ 5 check_py3k_warnings, cpython_only 6 7 # Test result of triple loop (too big to inline) 8 TRIPLETS = [(0, 0, 0), (0, 0, 1), (0, 0, 2), 9 (0, 1, 0), (0, 1, 1), (0, 1, 2), 10 (0, 2, 0), (0, 2, 1), (0, 2, 2), 11 12 (1, 0, 0), (1, 0, 1), (1, 0, 2), 13 (1, 1, 0), (1, 1, 1), (1, 1, 2), 14 (1, 2, 0), (1, 2, 1), (1, 2, 2), 15 16 (2, 0, 0), (2, 0, 1), (2, 0, 2), 17 (2, 1, 0), (2, 1, 1), (2, 1, 2), 18 (2, 2, 0), (2, 2, 1), (2, 2, 2)] 19 20 # Helper classes 21 22 class BasicIterClass: 23 def __init__(self, n): 24 self.n = n 25 self.i = 0 26 def next(self): 27 res = self.i 28 if res >= self.n: 29 raise StopIteration 30 self.i = res + 1 31 return res 32 33 class IteratingSequenceClass: 34 def __init__(self, n): 35 self.n = n 36 def __iter__(self): 37 return BasicIterClass(self.n) 38 39 class SequenceClass: 40 def __init__(self, n): 41 self.n = n 42 def __getitem__(self, i): 43 if 0 <= i < self.n: 44 return i 45 else: 46 raise IndexError 47 48 # Main test suite 49 50 class TestCase(unittest.TestCase): 51 52 # Helper to check that an iterator returns a given sequence 53 def check_iterator(self, it, seq): 54 res = [] 55 while 1: 56 try: 57 val = it.next() 58 except StopIteration: 59 break 60 res.append(val) 61 self.assertEqual(res, seq) 62 63 # Helper to check that a for loop generates a given sequence 64 def check_for_loop(self, expr, seq): 65 res = [] 66 for val in expr: 67 res.append(val) 68 self.assertEqual(res, seq) 69 70 # Test basic use of iter() function 71 def test_iter_basic(self): 72 self.check_iterator(iter(range(10)), range(10)) 73 74 # Test that iter(iter(x)) is the same as iter(x) 75 def test_iter_idempotency(self): 76 seq = range(10) 77 it = iter(seq) 78 it2 = iter(it) 79 self.assertTrue(it is it2) 80 81 # Test that for loops over iterators work 82 def test_iter_for_loop(self): 83 self.check_for_loop(iter(range(10)), range(10)) 84 85 # Test several independent iterators over the same list 86 def test_iter_independence(self): 87 seq = range(3) 88 res = [] 89 for i in iter(seq): 90 for j in iter(seq): 91 for k in iter(seq): 92 res.append((i, j, k)) 93 self.assertEqual(res, TRIPLETS) 94 95 # Test triple list comprehension using iterators 96 def test_nested_comprehensions_iter(self): 97 seq = range(3) 98 res = [(i, j, k) 99 for i in iter(seq) for j in iter(seq) for k in iter(seq)] 100 self.assertEqual(res, TRIPLETS) 101 102 # Test triple list comprehension without iterators 103 def test_nested_comprehensions_for(self): 104 seq = range(3) 105 res = [(i, j, k) for i in seq for j in seq for k in seq] 106 self.assertEqual(res, TRIPLETS) 107 108 # Test a class with __iter__ in a for loop 109 def test_iter_class_for(self): 110 self.check_for_loop(IteratingSequenceClass(10), range(10)) 111 112 # Test a class with __iter__ with explicit iter() 113 def test_iter_class_iter(self): 114 self.check_iterator(iter(IteratingSequenceClass(10)), range(10)) 115 116 # Test for loop on a sequence class without __iter__ 117 def test_seq_class_for(self): 118 self.check_for_loop(SequenceClass(10), range(10)) 119 120 # Test iter() on a sequence class without __iter__ 121 def test_seq_class_iter(self): 122 self.check_iterator(iter(SequenceClass(10)), range(10)) 123 124 # Test a new_style class with __iter__ but no next() method 125 def test_new_style_iter_class(self): 126 class IterClass(object): 127 def __iter__(self): 128 return self 129 self.assertRaises(TypeError, iter, IterClass()) 130 131 # Test two-argument iter() with callable instance 132 def test_iter_callable(self): 133 class C: 134 def __init__(self): 135 self.i = 0 136 def __call__(self): 137 i = self.i 138 self.i = i + 1 139 if i > 100: 140 raise IndexError # Emergency stop 141 return i 142 self.check_iterator(iter(C(), 10), range(10)) 143 144 # Test two-argument iter() with function 145 def test_iter_function(self): 146 def spam(state=[0]): 147 i = state[0] 148 state[0] = i+1 149 return i 150 self.check_iterator(iter(spam, 10), range(10)) 151 152 # Test two-argument iter() with function that raises StopIteration 153 def test_iter_function_stop(self): 154 def spam(state=[0]): 155 i = state[0] 156 if i == 10: 157 raise StopIteration 158 state[0] = i+1 159 return i 160 self.check_iterator(iter(spam, 20), range(10)) 161 162 # Test exception propagation through function iterator 163 def test_exception_function(self): 164 def spam(state=[0]): 165 i = state[0] 166 state[0] = i+1 167 if i == 10: 168 raise RuntimeError 169 return i 170 res = [] 171 try: 172 for x in iter(spam, 20): 173 res.append(x) 174 except RuntimeError: 175 self.assertEqual(res, range(10)) 176 else: 177 self.fail("should have raised RuntimeError") 178 179 # Test exception propagation through sequence iterator 180 def test_exception_sequence(self): 181 class MySequenceClass(SequenceClass): 182 def __getitem__(self, i): 183 if i == 10: 184 raise RuntimeError 185 return SequenceClass.__getitem__(self, i) 186 res = [] 187 try: 188 for x in MySequenceClass(20): 189 res.append(x) 190 except RuntimeError: 191 self.assertEqual(res, range(10)) 192 else: 193 self.fail("should have raised RuntimeError") 194 195 # Test for StopIteration from __getitem__ 196 def test_stop_sequence(self): 197 class MySequenceClass(SequenceClass): 198 def __getitem__(self, i): 199 if i == 10: 200 raise StopIteration 201 return SequenceClass.__getitem__(self, i) 202 self.check_for_loop(MySequenceClass(20), range(10)) 203 204 # Test a big range 205 def test_iter_big_range(self): 206 self.check_for_loop(iter(range(10000)), range(10000)) 207 208 # Test an empty list 209 def test_iter_empty(self): 210 self.check_for_loop(iter([]), []) 211 212 # Test a tuple 213 def test_iter_tuple(self): 214 self.check_for_loop(iter((0,1,2,3,4,5,6,7,8,9)), range(10)) 215 216 # Test an xrange 217 def test_iter_xrange(self): 218 self.check_for_loop(iter(xrange(10)), range(10)) 219 220 # Test a string 221 def test_iter_string(self): 222 self.check_for_loop(iter("abcde"), ["a", "b", "c", "d", "e"]) 223 224 # Test a Unicode string 225 if have_unicode: 226 def test_iter_unicode(self): 227 self.check_for_loop(iter(unicode("abcde")), 228 [unicode("a"), unicode("b"), unicode("c"), 229 unicode("d"), unicode("e")]) 230 231 # Test a directory 232 def test_iter_dict(self): 233 dict = {} 234 for i in range(10): 235 dict[i] = None 236 self.check_for_loop(dict, dict.keys()) 237 238 # Test a file 239 def test_iter_file(self): 240 f = open(TESTFN, "w") 241 try: 242 for i in range(5): 243 f.write("%d\n" % i) 244 finally: 245 f.close() 246 f = open(TESTFN, "r") 247 try: 248 self.check_for_loop(f, ["0\n", "1\n", "2\n", "3\n", "4\n"]) 249 self.check_for_loop(f, []) 250 finally: 251 f.close() 252 try: 253 unlink(TESTFN) 254 except OSError: 255 pass 256 257 # Test list()'s use of iterators. 258 def test_builtin_list(self): 259 self.assertEqual(list(SequenceClass(5)), range(5)) 260 self.assertEqual(list(SequenceClass(0)), []) 261 self.assertEqual(list(()), []) 262 self.assertEqual(list(range(10, -1, -1)), range(10, -1, -1)) 263 264 d = {"one": 1, "two": 2, "three": 3} 265 self.assertEqual(list(d), d.keys()) 266 267 self.assertRaises(TypeError, list, list) 268 self.assertRaises(TypeError, list, 42) 269 270 f = open(TESTFN, "w") 271 try: 272 for i in range(5): 273 f.write("%d\n" % i) 274 finally: 275 f.close() 276 f = open(TESTFN, "r") 277 try: 278 self.assertEqual(list(f), ["0\n", "1\n", "2\n", "3\n", "4\n"]) 279 f.seek(0, 0) 280 self.assertEqual(list(f), 281 ["0\n", "1\n", "2\n", "3\n", "4\n"]) 282 finally: 283 f.close() 284 try: 285 unlink(TESTFN) 286 except OSError: 287 pass 288 289 # Test tuples()'s use of iterators. 290 def test_builtin_tuple(self): 291 self.assertEqual(tuple(SequenceClass(5)), (0, 1, 2, 3, 4)) 292 self.assertEqual(tuple(SequenceClass(0)), ()) 293 self.assertEqual(tuple([]), ()) 294 self.assertEqual(tuple(()), ()) 295 self.assertEqual(tuple("abc"), ("a", "b", "c")) 296 297 d = {"one": 1, "two": 2, "three": 3} 298 self.assertEqual(tuple(d), tuple(d.keys())) 299 300 self.assertRaises(TypeError, tuple, list) 301 self.assertRaises(TypeError, tuple, 42) 302 303 f = open(TESTFN, "w") 304 try: 305 for i in range(5): 306 f.write("%d\n" % i) 307 finally: 308 f.close() 309 f = open(TESTFN, "r") 310 try: 311 self.assertEqual(tuple(f), ("0\n", "1\n", "2\n", "3\n", "4\n")) 312 f.seek(0, 0) 313 self.assertEqual(tuple(f), 314 ("0\n", "1\n", "2\n", "3\n", "4\n")) 315 finally: 316 f.close() 317 try: 318 unlink(TESTFN) 319 except OSError: 320 pass 321 322 # Test filter()'s use of iterators. 323 def test_builtin_filter(self): 324 self.assertEqual(filter(None, SequenceClass(5)), range(1, 5)) 325 self.assertEqual(filter(None, SequenceClass(0)), []) 326 self.assertEqual(filter(None, ()), ()) 327 self.assertEqual(filter(None, "abc"), "abc") 328 329 d = {"one": 1, "two": 2, "three": 3} 330 self.assertEqual(filter(None, d), d.keys()) 331 332 self.assertRaises(TypeError, filter, None, list) 333 self.assertRaises(TypeError, filter, None, 42) 334 335 class Boolean: 336 def __init__(self, truth): 337 self.truth = truth 338 def __nonzero__(self): 339 return self.truth 340 bTrue = Boolean(1) 341 bFalse = Boolean(0) 342 343 class Seq: 344 def __init__(self, *args): 345 self.vals = args 346 def __iter__(self): 347 class SeqIter: 348 def __init__(self, vals): 349 self.vals = vals 350 self.i = 0 351 def __iter__(self): 352 return self 353 def next(self): 354 i = self.i 355 self.i = i + 1 356 if i < len(self.vals): 357 return self.vals[i] 358 else: 359 raise StopIteration 360 return SeqIter(self.vals) 361 362 seq = Seq(*([bTrue, bFalse] * 25)) 363 self.assertEqual(filter(lambda x: not x, seq), [bFalse]*25) 364 self.assertEqual(filter(lambda x: not x, iter(seq)), [bFalse]*25) 365 366 # Test max() and min()'s use of iterators. 367 def test_builtin_max_min(self): 368 self.assertEqual(max(SequenceClass(5)), 4) 369 self.assertEqual(min(SequenceClass(5)), 0) 370 self.assertEqual(max(8, -1), 8) 371 self.assertEqual(min(8, -1), -1) 372 373 d = {"one": 1, "two": 2, "three": 3} 374 self.assertEqual(max(d), "two") 375 self.assertEqual(min(d), "one") 376 self.assertEqual(max(d.itervalues()), 3) 377 self.assertEqual(min(iter(d.itervalues())), 1) 378 379 f = open(TESTFN, "w") 380 try: 381 f.write("medium line\n") 382 f.write("xtra large line\n") 383 f.write("itty-bitty line\n") 384 finally: 385 f.close() 386 f = open(TESTFN, "r") 387 try: 388 self.assertEqual(min(f), "itty-bitty line\n") 389 f.seek(0, 0) 390 self.assertEqual(max(f), "xtra large line\n") 391 finally: 392 f.close() 393 try: 394 unlink(TESTFN) 395 except OSError: 396 pass 397 398 # Test map()'s use of iterators. 399 def test_builtin_map(self): 400 self.assertEqual(map(lambda x: x+1, SequenceClass(5)), range(1, 6)) 401 402 d = {"one": 1, "two": 2, "three": 3} 403 self.assertEqual(map(lambda k, d=d: (k, d[k]), d), d.items()) 404 dkeys = d.keys() 405 expected = [(i < len(d) and dkeys[i] or None, 406 i, 407 i < len(d) and dkeys[i] or None) 408 for i in range(5)] 409 410 # Deprecated map(None, ...) 411 with check_py3k_warnings(): 412 self.assertEqual(map(None, SequenceClass(5)), range(5)) 413 self.assertEqual(map(None, d), d.keys()) 414 self.assertEqual(map(None, d, 415 SequenceClass(5), 416 iter(d.iterkeys())), 417 expected) 418 419 f = open(TESTFN, "w") 420 try: 421 for i in range(10): 422 f.write("xy" * i + "\n") # line i has len 2*i+1 423 finally: 424 f.close() 425 f = open(TESTFN, "r") 426 try: 427 self.assertEqual(map(len, f), range(1, 21, 2)) 428 finally: 429 f.close() 430 try: 431 unlink(TESTFN) 432 except OSError: 433 pass 434 435 # Test zip()'s use of iterators. 436 def test_builtin_zip(self): 437 self.assertEqual(zip(), []) 438 self.assertEqual(zip(*[]), []) 439 self.assertEqual(zip(*[(1, 2), 'ab']), [(1, 'a'), (2, 'b')]) 440 441 self.assertRaises(TypeError, zip, None) 442 self.assertRaises(TypeError, zip, range(10), 42) 443 self.assertRaises(TypeError, zip, range(10), zip) 444 445 self.assertEqual(zip(IteratingSequenceClass(3)), 446 [(0,), (1,), (2,)]) 447 self.assertEqual(zip(SequenceClass(3)), 448 [(0,), (1,), (2,)]) 449 450 d = {"one": 1, "two": 2, "three": 3} 451 self.assertEqual(d.items(), zip(d, d.itervalues())) 452 453 # Generate all ints starting at constructor arg. 454 class IntsFrom: 455 def __init__(self, start): 456 self.i = start 457 458 def __iter__(self): 459 return self 460 461 def next(self): 462 i = self.i 463 self.i = i+1 464 return i 465 466 f = open(TESTFN, "w") 467 try: 468 f.write("a\n" "bbb\n" "cc\n") 469 finally: 470 f.close() 471 f = open(TESTFN, "r") 472 try: 473 self.assertEqual(zip(IntsFrom(0), f, IntsFrom(-100)), 474 [(0, "a\n", -100), 475 (1, "bbb\n", -99), 476 (2, "cc\n", -98)]) 477 finally: 478 f.close() 479 try: 480 unlink(TESTFN) 481 except OSError: 482 pass 483 484 self.assertEqual(zip(xrange(5)), [(i,) for i in range(5)]) 485 486 # Classes that lie about their lengths. 487 class NoGuessLen5: 488 def __getitem__(self, i): 489 if i >= 5: 490 raise IndexError 491 return i 492 493 class Guess3Len5(NoGuessLen5): 494 def __len__(self): 495 return 3 496 497 class Guess30Len5(NoGuessLen5): 498 def __len__(self): 499 return 30 500 501 self.assertEqual(len(Guess3Len5()), 3) 502 self.assertEqual(len(Guess30Len5()), 30) 503 self.assertEqual(zip(NoGuessLen5()), zip(range(5))) 504 self.assertEqual(zip(Guess3Len5()), zip(range(5))) 505 self.assertEqual(zip(Guess30Len5()), zip(range(5))) 506 507 expected = [(i, i) for i in range(5)] 508 for x in NoGuessLen5(), Guess3Len5(), Guess30Len5(): 509 for y in NoGuessLen5(), Guess3Len5(), Guess30Len5(): 510 self.assertEqual(zip(x, y), expected) 511 512 # Test reduces()'s use of iterators. 513 def test_deprecated_builtin_reduce(self): 514 with check_py3k_warnings(): 515 self._test_builtin_reduce() 516 517 def _test_builtin_reduce(self): 518 from operator import add 519 self.assertEqual(reduce(add, SequenceClass(5)), 10) 520 self.assertEqual(reduce(add, SequenceClass(5), 42), 52) 521 self.assertRaises(TypeError, reduce, add, SequenceClass(0)) 522 self.assertEqual(reduce(add, SequenceClass(0), 42), 42) 523 self.assertEqual(reduce(add, SequenceClass(1)), 0) 524 self.assertEqual(reduce(add, SequenceClass(1), 42), 42) 525 526 d = {"one": 1, "two": 2, "three": 3} 527 self.assertEqual(reduce(add, d), "".join(d.keys())) 528 529 # This test case will be removed if we don't have Unicode 530 def test_unicode_join_endcase(self): 531 532 # This class inserts a Unicode object into its argument's natural 533 # iteration, in the 3rd position. 534 class OhPhooey: 535 def __init__(self, seq): 536 self.it = iter(seq) 537 self.i = 0 538 539 def __iter__(self): 540 return self 541 542 def next(self): 543 i = self.i 544 self.i = i+1 545 if i == 2: 546 return unicode("fooled you!") 547 return self.it.next() 548 549 f = open(TESTFN, "w") 550 try: 551 f.write("a\n" + "b\n" + "c\n") 552 finally: 553 f.close() 554 555 f = open(TESTFN, "r") 556 # Nasty: string.join(s) can't know whether unicode.join() is needed 557 # until it's seen all of s's elements. But in this case, f's 558 # iterator cannot be restarted. So what we're testing here is 559 # whether string.join() can manage to remember everything it's seen 560 # and pass that on to unicode.join(). 561 try: 562 got = " - ".join(OhPhooey(f)) 563 self.assertEqual(got, unicode("a\n - b\n - fooled you! - c\n")) 564 finally: 565 f.close() 566 try: 567 unlink(TESTFN) 568 except OSError: 569 pass 570 if not have_unicode: 571 def test_unicode_join_endcase(self): pass 572 573 # Test iterators with 'x in y' and 'x not in y'. 574 def test_in_and_not_in(self): 575 for sc5 in IteratingSequenceClass(5), SequenceClass(5): 576 for i in range(5): 577 self.assertIn(i, sc5) 578 for i in "abc", -1, 5, 42.42, (3, 4), [], {1: 1}, 3-12j, sc5: 579 self.assertNotIn(i, sc5) 580 581 self.assertRaises(TypeError, lambda: 3 in 12) 582 self.assertRaises(TypeError, lambda: 3 not in map) 583 584 d = {"one": 1, "two": 2, "three": 3, 1j: 2j} 585 for k in d: 586 self.assertIn(k, d) 587 self.assertNotIn(k, d.itervalues()) 588 for v in d.values(): 589 self.assertIn(v, d.itervalues()) 590 self.assertNotIn(v, d) 591 for k, v in d.iteritems(): 592 self.assertIn((k, v), d.iteritems()) 593 self.assertNotIn((v, k), d.iteritems()) 594 595 f = open(TESTFN, "w") 596 try: 597 f.write("a\n" "b\n" "c\n") 598 finally: 599 f.close() 600 f = open(TESTFN, "r") 601 try: 602 for chunk in "abc": 603 f.seek(0, 0) 604 self.assertNotIn(chunk, f) 605 f.seek(0, 0) 606 self.assertIn((chunk + "\n"), f) 607 finally: 608 f.close() 609 try: 610 unlink(TESTFN) 611 except OSError: 612 pass 613 614 # Test iterators with operator.countOf (PySequence_Count). 615 def test_countOf(self): 616 from operator import countOf 617 self.assertEqual(countOf([1,2,2,3,2,5], 2), 3) 618 self.assertEqual(countOf((1,2,2,3,2,5), 2), 3) 619 self.assertEqual(countOf("122325", "2"), 3) 620 self.assertEqual(countOf("122325", "6"), 0) 621 622 self.assertRaises(TypeError, countOf, 42, 1) 623 self.assertRaises(TypeError, countOf, countOf, countOf) 624 625 d = {"one": 3, "two": 3, "three": 3, 1j: 2j} 626 for k in d: 627 self.assertEqual(countOf(d, k), 1) 628 self.assertEqual(countOf(d.itervalues(), 3), 3) 629 self.assertEqual(countOf(d.itervalues(), 2j), 1) 630 self.assertEqual(countOf(d.itervalues(), 1j), 0) 631 632 f = open(TESTFN, "w") 633 try: 634 f.write("a\n" "b\n" "c\n" "b\n") 635 finally: 636 f.close() 637 f = open(TESTFN, "r") 638 try: 639 for letter, count in ("a", 1), ("b", 2), ("c", 1), ("d", 0): 640 f.seek(0, 0) 641 self.assertEqual(countOf(f, letter + "\n"), count) 642 finally: 643 f.close() 644 try: 645 unlink(TESTFN) 646 except OSError: 647 pass 648 649 # Test iterators with operator.indexOf (PySequence_Index). 650 def test_indexOf(self): 651 from operator import indexOf 652 self.assertEqual(indexOf([1,2,2,3,2,5], 1), 0) 653 self.assertEqual(indexOf((1,2,2,3,2,5), 2), 1) 654 self.assertEqual(indexOf((1,2,2,3,2,5), 3), 3) 655 self.assertEqual(indexOf((1,2,2,3,2,5), 5), 5) 656 self.assertRaises(ValueError, indexOf, (1,2,2,3,2,5), 0) 657 self.assertRaises(ValueError, indexOf, (1,2,2,3,2,5), 6) 658 659 self.assertEqual(indexOf("122325", "2"), 1) 660 self.assertEqual(indexOf("122325", "5"), 5) 661 self.assertRaises(ValueError, indexOf, "122325", "6") 662 663 self.assertRaises(TypeError, indexOf, 42, 1) 664 self.assertRaises(TypeError, indexOf, indexOf, indexOf) 665 666 f = open(TESTFN, "w") 667 try: 668 f.write("a\n" "b\n" "c\n" "d\n" "e\n") 669 finally: 670 f.close() 671 f = open(TESTFN, "r") 672 try: 673 fiter = iter(f) 674 self.assertEqual(indexOf(fiter, "b\n"), 1) 675 self.assertEqual(indexOf(fiter, "d\n"), 1) 676 self.assertEqual(indexOf(fiter, "e\n"), 0) 677 self.assertRaises(ValueError, indexOf, fiter, "a\n") 678 finally: 679 f.close() 680 try: 681 unlink(TESTFN) 682 except OSError: 683 pass 684 685 iclass = IteratingSequenceClass(3) 686 for i in range(3): 687 self.assertEqual(indexOf(iclass, i), i) 688 self.assertRaises(ValueError, indexOf, iclass, -1) 689 690 # Test iterators with file.writelines(). 691 def test_writelines(self): 692 f = file(TESTFN, "w") 693 694 try: 695 self.assertRaises(TypeError, f.writelines, None) 696 self.assertRaises(TypeError, f.writelines, 42) 697 698 f.writelines(["1\n", "2\n"]) 699 f.writelines(("3\n", "4\n")) 700 f.writelines({'5\n': None}) 701 f.writelines({}) 702 703 # Try a big chunk too. 704 class Iterator: 705 def __init__(self, start, finish): 706 self.start = start 707 self.finish = finish 708 self.i = self.start 709 710 def next(self): 711 if self.i >= self.finish: 712 raise StopIteration 713 result = str(self.i) + '\n' 714 self.i += 1 715 return result 716 717 def __iter__(self): 718 return self 719 720 class Whatever: 721 def __init__(self, start, finish): 722 self.start = start 723 self.finish = finish 724 725 def __iter__(self): 726 return Iterator(self.start, self.finish) 727 728 f.writelines(Whatever(6, 6+2000)) 729 f.close() 730 731 f = file(TESTFN) 732 expected = [str(i) + "\n" for i in range(1, 2006)] 733 self.assertEqual(list(f), expected) 734 735 finally: 736 f.close() 737 try: 738 unlink(TESTFN) 739 except OSError: 740 pass 741 742 743 # Test iterators on RHS of unpacking assignments. 744 def test_unpack_iter(self): 745 a, b = 1, 2 746 self.assertEqual((a, b), (1, 2)) 747 748 a, b, c = IteratingSequenceClass(3) 749 self.assertEqual((a, b, c), (0, 1, 2)) 750 751 try: # too many values 752 a, b = IteratingSequenceClass(3) 753 except ValueError: 754 pass 755 else: 756 self.fail("should have raised ValueError") 757 758 try: # not enough values 759 a, b, c = IteratingSequenceClass(2) 760 except ValueError: 761 pass 762 else: 763 self.fail("should have raised ValueError") 764 765 try: # not iterable 766 a, b, c = len 767 except TypeError: 768 pass 769 else: 770 self.fail("should have raised TypeError") 771 772 a, b, c = {1: 42, 2: 42, 3: 42}.itervalues() 773 self.assertEqual((a, b, c), (42, 42, 42)) 774 775 f = open(TESTFN, "w") 776 lines = ("a\n", "bb\n", "ccc\n") 777 try: 778 for line in lines: 779 f.write(line) 780 finally: 781 f.close() 782 f = open(TESTFN, "r") 783 try: 784 a, b, c = f 785 self.assertEqual((a, b, c), lines) 786 finally: 787 f.close() 788 try: 789 unlink(TESTFN) 790 except OSError: 791 pass 792 793 (a, b), (c,) = IteratingSequenceClass(2), {42: 24} 794 self.assertEqual((a, b, c), (0, 1, 42)) 795 796 797 @cpython_only 798 def test_ref_counting_behavior(self): 799 class C(object): 800 count = 0 801 def __new__(cls): 802 cls.count += 1 803 return object.__new__(cls) 804 def __del__(self): 805 cls = self.__class__ 806 assert cls.count > 0 807 cls.count -= 1 808 x = C() 809 self.assertEqual(C.count, 1) 810 del x 811 self.assertEqual(C.count, 0) 812 l = [C(), C(), C()] 813 self.assertEqual(C.count, 3) 814 try: 815 a, b = iter(l) 816 except ValueError: 817 pass 818 del l 819 self.assertEqual(C.count, 0) 820 821 822 # Make sure StopIteration is a "sink state". 823 # This tests various things that weren't sink states in Python 2.2.1, 824 # plus various things that always were fine. 825 826 def test_sinkstate_list(self): 827 # This used to fail 828 a = range(5) 829 b = iter(a) 830 self.assertEqual(list(b), range(5)) 831 a.extend(range(5, 10)) 832 self.assertEqual(list(b), []) 833 834 def test_sinkstate_tuple(self): 835 a = (0, 1, 2, 3, 4) 836 b = iter(a) 837 self.assertEqual(list(b), range(5)) 838 self.assertEqual(list(b), []) 839 840 def test_sinkstate_string(self): 841 a = "abcde" 842 b = iter(a) 843 self.assertEqual(list(b), ['a', 'b', 'c', 'd', 'e']) 844 self.assertEqual(list(b), []) 845 846 def test_sinkstate_sequence(self): 847 # This used to fail 848 a = SequenceClass(5) 849 b = iter(a) 850 self.assertEqual(list(b), range(5)) 851 a.n = 10 852 self.assertEqual(list(b), []) 853 854 def test_sinkstate_callable(self): 855 # This used to fail 856 def spam(state=[0]): 857 i = state[0] 858 state[0] = i+1 859 if i == 10: 860 raise AssertionError, "shouldn't have gotten this far" 861 return i 862 b = iter(spam, 5) 863 self.assertEqual(list(b), range(5)) 864 self.assertEqual(list(b), []) 865 866 def test_sinkstate_dict(self): 867 # XXX For a more thorough test, see towards the end of: 868 # http://mail.python.org/pipermail/python-dev/2002-July/026512.html 869 a = {1:1, 2:2, 0:0, 4:4, 3:3} 870 for b in iter(a), a.iterkeys(), a.iteritems(), a.itervalues(): 871 b = iter(a) 872 self.assertEqual(len(list(b)), 5) 873 self.assertEqual(list(b), []) 874 875 def test_sinkstate_yield(self): 876 def gen(): 877 for i in range(5): 878 yield i 879 b = gen() 880 self.assertEqual(list(b), range(5)) 881 self.assertEqual(list(b), []) 882 883 def test_sinkstate_range(self): 884 a = xrange(5) 885 b = iter(a) 886 self.assertEqual(list(b), range(5)) 887 self.assertEqual(list(b), []) 888 889 def test_sinkstate_enumerate(self): 890 a = range(5) 891 e = enumerate(a) 892 b = iter(e) 893 self.assertEqual(list(b), zip(range(5), range(5))) 894 self.assertEqual(list(b), []) 895 896 def test_3720(self): 897 # Avoid a crash, when an iterator deletes its next() method. 898 class BadIterator(object): 899 def __iter__(self): 900 return self 901 def next(self): 902 del BadIterator.next 903 return 1 904 905 try: 906 for i in BadIterator() : 907 pass 908 except TypeError: 909 pass 910 911 def test_extending_list_with_iterator_does_not_segfault(self): 912 # The code to extend a list with an iterator has a fair 913 # amount of nontrivial logic in terms of guessing how 914 # much memory to allocate in advance, "stealing" refs, 915 # and then shrinking at the end. This is a basic smoke 916 # test for that scenario. 917 def gen(): 918 for i in range(500): 919 yield i 920 lst = [0] * 500 921 for i in range(240): 922 lst.pop(0) 923 lst.extend(gen()) 924 self.assertEqual(len(lst), 760) 925 926 927 def test_main(): 928 run_unittest(TestCase) 929 930 931 if __name__ == "__main__": 932 test_main() 933