1"""Unit tests for the copy module.""" 2 3import copy 4import copyreg 5import weakref 6import abc 7from operator import le, lt, ge, gt, eq, ne 8 9import unittest 10from test import support 11 12order_comparisons = le, lt, ge, gt 13equality_comparisons = eq, ne 14comparisons = order_comparisons + equality_comparisons 15 16class TestCopy(unittest.TestCase): 17 18 # Attempt full line coverage of copy.py from top to bottom 19 20 def test_exceptions(self): 21 self.assertIs(copy.Error, copy.error) 22 self.assertTrue(issubclass(copy.Error, Exception)) 23 24 # The copy() method 25 26 def test_copy_basic(self): 27 x = 42 28 y = copy.copy(x) 29 self.assertEqual(x, y) 30 31 def test_copy_copy(self): 32 class C(object): 33 def __init__(self, foo): 34 self.foo = foo 35 def __copy__(self): 36 return C(self.foo) 37 x = C(42) 38 y = copy.copy(x) 39 self.assertEqual(y.__class__, x.__class__) 40 self.assertEqual(y.foo, x.foo) 41 42 def test_copy_registry(self): 43 class C(object): 44 def __new__(cls, foo): 45 obj = object.__new__(cls) 46 obj.foo = foo 47 return obj 48 def pickle_C(obj): 49 return (C, (obj.foo,)) 50 x = C(42) 51 self.assertRaises(TypeError, copy.copy, x) 52 copyreg.pickle(C, pickle_C, C) 53 y = copy.copy(x) 54 55 def test_copy_reduce_ex(self): 56 class C(object): 57 def __reduce_ex__(self, proto): 58 c.append(1) 59 return "" 60 def __reduce__(self): 61 self.fail("shouldn't call this") 62 c = [] 63 x = C() 64 y = copy.copy(x) 65 self.assertIs(y, x) 66 self.assertEqual(c, [1]) 67 68 def test_copy_reduce(self): 69 class C(object): 70 def __reduce__(self): 71 c.append(1) 72 return "" 73 c = [] 74 x = C() 75 y = copy.copy(x) 76 self.assertIs(y, x) 77 self.assertEqual(c, [1]) 78 79 def test_copy_cant(self): 80 class C(object): 81 def __getattribute__(self, name): 82 if name.startswith("__reduce"): 83 raise AttributeError(name) 84 return object.__getattribute__(self, name) 85 x = C() 86 self.assertRaises(copy.Error, copy.copy, x) 87 88 # Type-specific _copy_xxx() methods 89 90 def test_copy_atomic(self): 91 class Classic: 92 pass 93 class NewStyle(object): 94 pass 95 def f(): 96 pass 97 class WithMetaclass(metaclass=abc.ABCMeta): 98 pass 99 tests = [None, ..., NotImplemented, 100 42, 2**100, 3.14, True, False, 1j, 101 "hello", "hello\u1234", f.__code__, 102 b"world", bytes(range(256)), range(10), slice(1, 10, 2), 103 NewStyle, Classic, max, WithMetaclass, property()] 104 for x in tests: 105 self.assertIs(copy.copy(x), x) 106 107 def test_copy_list(self): 108 x = [1, 2, 3] 109 y = copy.copy(x) 110 self.assertEqual(y, x) 111 self.assertIsNot(y, x) 112 x = [] 113 y = copy.copy(x) 114 self.assertEqual(y, x) 115 self.assertIsNot(y, x) 116 117 def test_copy_tuple(self): 118 x = (1, 2, 3) 119 self.assertIs(copy.copy(x), x) 120 x = () 121 self.assertIs(copy.copy(x), x) 122 x = (1, 2, 3, []) 123 self.assertIs(copy.copy(x), x) 124 125 def test_copy_dict(self): 126 x = {"foo": 1, "bar": 2} 127 y = copy.copy(x) 128 self.assertEqual(y, x) 129 self.assertIsNot(y, x) 130 x = {} 131 y = copy.copy(x) 132 self.assertEqual(y, x) 133 self.assertIsNot(y, x) 134 135 def test_copy_set(self): 136 x = {1, 2, 3} 137 y = copy.copy(x) 138 self.assertEqual(y, x) 139 self.assertIsNot(y, x) 140 x = set() 141 y = copy.copy(x) 142 self.assertEqual(y, x) 143 self.assertIsNot(y, x) 144 145 def test_copy_frozenset(self): 146 x = frozenset({1, 2, 3}) 147 self.assertIs(copy.copy(x), x) 148 x = frozenset() 149 self.assertIs(copy.copy(x), x) 150 151 def test_copy_bytearray(self): 152 x = bytearray(b'abc') 153 y = copy.copy(x) 154 self.assertEqual(y, x) 155 self.assertIsNot(y, x) 156 x = bytearray() 157 y = copy.copy(x) 158 self.assertEqual(y, x) 159 self.assertIsNot(y, x) 160 161 def test_copy_inst_vanilla(self): 162 class C: 163 def __init__(self, foo): 164 self.foo = foo 165 def __eq__(self, other): 166 return self.foo == other.foo 167 x = C(42) 168 self.assertEqual(copy.copy(x), x) 169 170 def test_copy_inst_copy(self): 171 class C: 172 def __init__(self, foo): 173 self.foo = foo 174 def __copy__(self): 175 return C(self.foo) 176 def __eq__(self, other): 177 return self.foo == other.foo 178 x = C(42) 179 self.assertEqual(copy.copy(x), x) 180 181 def test_copy_inst_getinitargs(self): 182 class C: 183 def __init__(self, foo): 184 self.foo = foo 185 def __getinitargs__(self): 186 return (self.foo,) 187 def __eq__(self, other): 188 return self.foo == other.foo 189 x = C(42) 190 self.assertEqual(copy.copy(x), x) 191 192 def test_copy_inst_getnewargs(self): 193 class C(int): 194 def __new__(cls, foo): 195 self = int.__new__(cls) 196 self.foo = foo 197 return self 198 def __getnewargs__(self): 199 return self.foo, 200 def __eq__(self, other): 201 return self.foo == other.foo 202 x = C(42) 203 y = copy.copy(x) 204 self.assertIsInstance(y, C) 205 self.assertEqual(y, x) 206 self.assertIsNot(y, x) 207 self.assertEqual(y.foo, x.foo) 208 209 def test_copy_inst_getnewargs_ex(self): 210 class C(int): 211 def __new__(cls, *, foo): 212 self = int.__new__(cls) 213 self.foo = foo 214 return self 215 def __getnewargs_ex__(self): 216 return (), {'foo': self.foo} 217 def __eq__(self, other): 218 return self.foo == other.foo 219 x = C(foo=42) 220 y = copy.copy(x) 221 self.assertIsInstance(y, C) 222 self.assertEqual(y, x) 223 self.assertIsNot(y, x) 224 self.assertEqual(y.foo, x.foo) 225 226 def test_copy_inst_getstate(self): 227 class C: 228 def __init__(self, foo): 229 self.foo = foo 230 def __getstate__(self): 231 return {"foo": self.foo} 232 def __eq__(self, other): 233 return self.foo == other.foo 234 x = C(42) 235 self.assertEqual(copy.copy(x), x) 236 237 def test_copy_inst_setstate(self): 238 class C: 239 def __init__(self, foo): 240 self.foo = foo 241 def __setstate__(self, state): 242 self.foo = state["foo"] 243 def __eq__(self, other): 244 return self.foo == other.foo 245 x = C(42) 246 self.assertEqual(copy.copy(x), x) 247 248 def test_copy_inst_getstate_setstate(self): 249 class C: 250 def __init__(self, foo): 251 self.foo = foo 252 def __getstate__(self): 253 return self.foo 254 def __setstate__(self, state): 255 self.foo = state 256 def __eq__(self, other): 257 return self.foo == other.foo 258 x = C(42) 259 self.assertEqual(copy.copy(x), x) 260 # State with boolean value is false (issue #25718) 261 x = C(0.0) 262 self.assertEqual(copy.copy(x), x) 263 264 # The deepcopy() method 265 266 def test_deepcopy_basic(self): 267 x = 42 268 y = copy.deepcopy(x) 269 self.assertEqual(y, x) 270 271 def test_deepcopy_memo(self): 272 # Tests of reflexive objects are under type-specific sections below. 273 # This tests only repetitions of objects. 274 x = [] 275 x = [x, x] 276 y = copy.deepcopy(x) 277 self.assertEqual(y, x) 278 self.assertIsNot(y, x) 279 self.assertIsNot(y[0], x[0]) 280 self.assertIs(y[0], y[1]) 281 282 def test_deepcopy_issubclass(self): 283 # XXX Note: there's no way to test the TypeError coming out of 284 # issubclass() -- this can only happen when an extension 285 # module defines a "type" that doesn't formally inherit from 286 # type. 287 class Meta(type): 288 pass 289 class C(metaclass=Meta): 290 pass 291 self.assertEqual(copy.deepcopy(C), C) 292 293 def test_deepcopy_deepcopy(self): 294 class C(object): 295 def __init__(self, foo): 296 self.foo = foo 297 def __deepcopy__(self, memo=None): 298 return C(self.foo) 299 x = C(42) 300 y = copy.deepcopy(x) 301 self.assertEqual(y.__class__, x.__class__) 302 self.assertEqual(y.foo, x.foo) 303 304 def test_deepcopy_registry(self): 305 class C(object): 306 def __new__(cls, foo): 307 obj = object.__new__(cls) 308 obj.foo = foo 309 return obj 310 def pickle_C(obj): 311 return (C, (obj.foo,)) 312 x = C(42) 313 self.assertRaises(TypeError, copy.deepcopy, x) 314 copyreg.pickle(C, pickle_C, C) 315 y = copy.deepcopy(x) 316 317 def test_deepcopy_reduce_ex(self): 318 class C(object): 319 def __reduce_ex__(self, proto): 320 c.append(1) 321 return "" 322 def __reduce__(self): 323 self.fail("shouldn't call this") 324 c = [] 325 x = C() 326 y = copy.deepcopy(x) 327 self.assertIs(y, x) 328 self.assertEqual(c, [1]) 329 330 def test_deepcopy_reduce(self): 331 class C(object): 332 def __reduce__(self): 333 c.append(1) 334 return "" 335 c = [] 336 x = C() 337 y = copy.deepcopy(x) 338 self.assertIs(y, x) 339 self.assertEqual(c, [1]) 340 341 def test_deepcopy_cant(self): 342 class C(object): 343 def __getattribute__(self, name): 344 if name.startswith("__reduce"): 345 raise AttributeError(name) 346 return object.__getattribute__(self, name) 347 x = C() 348 self.assertRaises(copy.Error, copy.deepcopy, x) 349 350 # Type-specific _deepcopy_xxx() methods 351 352 def test_deepcopy_atomic(self): 353 class Classic: 354 pass 355 class NewStyle(object): 356 pass 357 def f(): 358 pass 359 tests = [None, 42, 2**100, 3.14, True, False, 1j, 360 "hello", "hello\u1234", f.__code__, 361 NewStyle, range(10), Classic, max, property()] 362 for x in tests: 363 self.assertIs(copy.deepcopy(x), x) 364 365 def test_deepcopy_list(self): 366 x = [[1, 2], 3] 367 y = copy.deepcopy(x) 368 self.assertEqual(y, x) 369 self.assertIsNot(x, y) 370 self.assertIsNot(x[0], y[0]) 371 372 def test_deepcopy_reflexive_list(self): 373 x = [] 374 x.append(x) 375 y = copy.deepcopy(x) 376 for op in comparisons: 377 self.assertRaises(RecursionError, op, y, x) 378 self.assertIsNot(y, x) 379 self.assertIs(y[0], y) 380 self.assertEqual(len(y), 1) 381 382 def test_deepcopy_empty_tuple(self): 383 x = () 384 y = copy.deepcopy(x) 385 self.assertIs(x, y) 386 387 def test_deepcopy_tuple(self): 388 x = ([1, 2], 3) 389 y = copy.deepcopy(x) 390 self.assertEqual(y, x) 391 self.assertIsNot(x, y) 392 self.assertIsNot(x[0], y[0]) 393 394 def test_deepcopy_tuple_of_immutables(self): 395 x = ((1, 2), 3) 396 y = copy.deepcopy(x) 397 self.assertIs(x, y) 398 399 def test_deepcopy_reflexive_tuple(self): 400 x = ([],) 401 x[0].append(x) 402 y = copy.deepcopy(x) 403 for op in comparisons: 404 self.assertRaises(RecursionError, op, y, x) 405 self.assertIsNot(y, x) 406 self.assertIsNot(y[0], x[0]) 407 self.assertIs(y[0][0], y) 408 409 def test_deepcopy_dict(self): 410 x = {"foo": [1, 2], "bar": 3} 411 y = copy.deepcopy(x) 412 self.assertEqual(y, x) 413 self.assertIsNot(x, y) 414 self.assertIsNot(x["foo"], y["foo"]) 415 416 def test_deepcopy_reflexive_dict(self): 417 x = {} 418 x['foo'] = x 419 y = copy.deepcopy(x) 420 for op in order_comparisons: 421 self.assertRaises(TypeError, op, y, x) 422 for op in equality_comparisons: 423 self.assertRaises(RecursionError, op, y, x) 424 self.assertIsNot(y, x) 425 self.assertIs(y['foo'], y) 426 self.assertEqual(len(y), 1) 427 428 def test_deepcopy_keepalive(self): 429 memo = {} 430 x = [] 431 y = copy.deepcopy(x, memo) 432 self.assertIs(memo[id(memo)][0], x) 433 434 def test_deepcopy_dont_memo_immutable(self): 435 memo = {} 436 x = [1, 2, 3, 4] 437 y = copy.deepcopy(x, memo) 438 self.assertEqual(y, x) 439 # There's the entry for the new list, and the keep alive. 440 self.assertEqual(len(memo), 2) 441 442 memo = {} 443 x = [(1, 2)] 444 y = copy.deepcopy(x, memo) 445 self.assertEqual(y, x) 446 # Tuples with immutable contents are immutable for deepcopy. 447 self.assertEqual(len(memo), 2) 448 449 def test_deepcopy_inst_vanilla(self): 450 class C: 451 def __init__(self, foo): 452 self.foo = foo 453 def __eq__(self, other): 454 return self.foo == other.foo 455 x = C([42]) 456 y = copy.deepcopy(x) 457 self.assertEqual(y, x) 458 self.assertIsNot(y.foo, x.foo) 459 460 def test_deepcopy_inst_deepcopy(self): 461 class C: 462 def __init__(self, foo): 463 self.foo = foo 464 def __deepcopy__(self, memo): 465 return C(copy.deepcopy(self.foo, memo)) 466 def __eq__(self, other): 467 return self.foo == other.foo 468 x = C([42]) 469 y = copy.deepcopy(x) 470 self.assertEqual(y, x) 471 self.assertIsNot(y, x) 472 self.assertIsNot(y.foo, x.foo) 473 474 def test_deepcopy_inst_getinitargs(self): 475 class C: 476 def __init__(self, foo): 477 self.foo = foo 478 def __getinitargs__(self): 479 return (self.foo,) 480 def __eq__(self, other): 481 return self.foo == other.foo 482 x = C([42]) 483 y = copy.deepcopy(x) 484 self.assertEqual(y, x) 485 self.assertIsNot(y, x) 486 self.assertIsNot(y.foo, x.foo) 487 488 def test_deepcopy_inst_getnewargs(self): 489 class C(int): 490 def __new__(cls, foo): 491 self = int.__new__(cls) 492 self.foo = foo 493 return self 494 def __getnewargs__(self): 495 return self.foo, 496 def __eq__(self, other): 497 return self.foo == other.foo 498 x = C([42]) 499 y = copy.deepcopy(x) 500 self.assertIsInstance(y, C) 501 self.assertEqual(y, x) 502 self.assertIsNot(y, x) 503 self.assertEqual(y.foo, x.foo) 504 self.assertIsNot(y.foo, x.foo) 505 506 def test_deepcopy_inst_getnewargs_ex(self): 507 class C(int): 508 def __new__(cls, *, foo): 509 self = int.__new__(cls) 510 self.foo = foo 511 return self 512 def __getnewargs_ex__(self): 513 return (), {'foo': self.foo} 514 def __eq__(self, other): 515 return self.foo == other.foo 516 x = C(foo=[42]) 517 y = copy.deepcopy(x) 518 self.assertIsInstance(y, C) 519 self.assertEqual(y, x) 520 self.assertIsNot(y, x) 521 self.assertEqual(y.foo, x.foo) 522 self.assertIsNot(y.foo, x.foo) 523 524 def test_deepcopy_inst_getstate(self): 525 class C: 526 def __init__(self, foo): 527 self.foo = foo 528 def __getstate__(self): 529 return {"foo": self.foo} 530 def __eq__(self, other): 531 return self.foo == other.foo 532 x = C([42]) 533 y = copy.deepcopy(x) 534 self.assertEqual(y, x) 535 self.assertIsNot(y, x) 536 self.assertIsNot(y.foo, x.foo) 537 538 def test_deepcopy_inst_setstate(self): 539 class C: 540 def __init__(self, foo): 541 self.foo = foo 542 def __setstate__(self, state): 543 self.foo = state["foo"] 544 def __eq__(self, other): 545 return self.foo == other.foo 546 x = C([42]) 547 y = copy.deepcopy(x) 548 self.assertEqual(y, x) 549 self.assertIsNot(y, x) 550 self.assertIsNot(y.foo, x.foo) 551 552 def test_deepcopy_inst_getstate_setstate(self): 553 class C: 554 def __init__(self, foo): 555 self.foo = foo 556 def __getstate__(self): 557 return self.foo 558 def __setstate__(self, state): 559 self.foo = state 560 def __eq__(self, other): 561 return self.foo == other.foo 562 x = C([42]) 563 y = copy.deepcopy(x) 564 self.assertEqual(y, x) 565 self.assertIsNot(y, x) 566 self.assertIsNot(y.foo, x.foo) 567 # State with boolean value is false (issue #25718) 568 x = C([]) 569 y = copy.deepcopy(x) 570 self.assertEqual(y, x) 571 self.assertIsNot(y, x) 572 self.assertIsNot(y.foo, x.foo) 573 574 def test_deepcopy_reflexive_inst(self): 575 class C: 576 pass 577 x = C() 578 x.foo = x 579 y = copy.deepcopy(x) 580 self.assertIsNot(y, x) 581 self.assertIs(y.foo, y) 582 583 # _reconstruct() 584 585 def test_reconstruct_string(self): 586 class C(object): 587 def __reduce__(self): 588 return "" 589 x = C() 590 y = copy.copy(x) 591 self.assertIs(y, x) 592 y = copy.deepcopy(x) 593 self.assertIs(y, x) 594 595 def test_reconstruct_nostate(self): 596 class C(object): 597 def __reduce__(self): 598 return (C, ()) 599 x = C() 600 x.foo = 42 601 y = copy.copy(x) 602 self.assertIs(y.__class__, x.__class__) 603 y = copy.deepcopy(x) 604 self.assertIs(y.__class__, x.__class__) 605 606 def test_reconstruct_state(self): 607 class C(object): 608 def __reduce__(self): 609 return (C, (), self.__dict__) 610 def __eq__(self, other): 611 return self.__dict__ == other.__dict__ 612 x = C() 613 x.foo = [42] 614 y = copy.copy(x) 615 self.assertEqual(y, x) 616 y = copy.deepcopy(x) 617 self.assertEqual(y, x) 618 self.assertIsNot(y.foo, x.foo) 619 620 def test_reconstruct_state_setstate(self): 621 class C(object): 622 def __reduce__(self): 623 return (C, (), self.__dict__) 624 def __setstate__(self, state): 625 self.__dict__.update(state) 626 def __eq__(self, other): 627 return self.__dict__ == other.__dict__ 628 x = C() 629 x.foo = [42] 630 y = copy.copy(x) 631 self.assertEqual(y, x) 632 y = copy.deepcopy(x) 633 self.assertEqual(y, x) 634 self.assertIsNot(y.foo, x.foo) 635 636 def test_reconstruct_reflexive(self): 637 class C(object): 638 pass 639 x = C() 640 x.foo = x 641 y = copy.deepcopy(x) 642 self.assertIsNot(y, x) 643 self.assertIs(y.foo, y) 644 645 # Additions for Python 2.3 and pickle protocol 2 646 647 def test_reduce_4tuple(self): 648 class C(list): 649 def __reduce__(self): 650 return (C, (), self.__dict__, iter(self)) 651 def __eq__(self, other): 652 return (list(self) == list(other) and 653 self.__dict__ == other.__dict__) 654 x = C([[1, 2], 3]) 655 y = copy.copy(x) 656 self.assertEqual(x, y) 657 self.assertIsNot(x, y) 658 self.assertIs(x[0], y[0]) 659 y = copy.deepcopy(x) 660 self.assertEqual(x, y) 661 self.assertIsNot(x, y) 662 self.assertIsNot(x[0], y[0]) 663 664 def test_reduce_5tuple(self): 665 class C(dict): 666 def __reduce__(self): 667 return (C, (), self.__dict__, None, self.items()) 668 def __eq__(self, other): 669 return (dict(self) == dict(other) and 670 self.__dict__ == other.__dict__) 671 x = C([("foo", [1, 2]), ("bar", 3)]) 672 y = copy.copy(x) 673 self.assertEqual(x, y) 674 self.assertIsNot(x, y) 675 self.assertIs(x["foo"], y["foo"]) 676 y = copy.deepcopy(x) 677 self.assertEqual(x, y) 678 self.assertIsNot(x, y) 679 self.assertIsNot(x["foo"], y["foo"]) 680 681 def test_copy_slots(self): 682 class C(object): 683 __slots__ = ["foo"] 684 x = C() 685 x.foo = [42] 686 y = copy.copy(x) 687 self.assertIs(x.foo, y.foo) 688 689 def test_deepcopy_slots(self): 690 class C(object): 691 __slots__ = ["foo"] 692 x = C() 693 x.foo = [42] 694 y = copy.deepcopy(x) 695 self.assertEqual(x.foo, y.foo) 696 self.assertIsNot(x.foo, y.foo) 697 698 def test_deepcopy_dict_subclass(self): 699 class C(dict): 700 def __init__(self, d=None): 701 if not d: 702 d = {} 703 self._keys = list(d.keys()) 704 super().__init__(d) 705 def __setitem__(self, key, item): 706 super().__setitem__(key, item) 707 if key not in self._keys: 708 self._keys.append(key) 709 x = C(d={'foo':0}) 710 y = copy.deepcopy(x) 711 self.assertEqual(x, y) 712 self.assertEqual(x._keys, y._keys) 713 self.assertIsNot(x, y) 714 x['bar'] = 1 715 self.assertNotEqual(x, y) 716 self.assertNotEqual(x._keys, y._keys) 717 718 def test_copy_list_subclass(self): 719 class C(list): 720 pass 721 x = C([[1, 2], 3]) 722 x.foo = [4, 5] 723 y = copy.copy(x) 724 self.assertEqual(list(x), list(y)) 725 self.assertEqual(x.foo, y.foo) 726 self.assertIs(x[0], y[0]) 727 self.assertIs(x.foo, y.foo) 728 729 def test_deepcopy_list_subclass(self): 730 class C(list): 731 pass 732 x = C([[1, 2], 3]) 733 x.foo = [4, 5] 734 y = copy.deepcopy(x) 735 self.assertEqual(list(x), list(y)) 736 self.assertEqual(x.foo, y.foo) 737 self.assertIsNot(x[0], y[0]) 738 self.assertIsNot(x.foo, y.foo) 739 740 def test_copy_tuple_subclass(self): 741 class C(tuple): 742 pass 743 x = C([1, 2, 3]) 744 self.assertEqual(tuple(x), (1, 2, 3)) 745 y = copy.copy(x) 746 self.assertEqual(tuple(y), (1, 2, 3)) 747 748 def test_deepcopy_tuple_subclass(self): 749 class C(tuple): 750 pass 751 x = C([[1, 2], 3]) 752 self.assertEqual(tuple(x), ([1, 2], 3)) 753 y = copy.deepcopy(x) 754 self.assertEqual(tuple(y), ([1, 2], 3)) 755 self.assertIsNot(x, y) 756 self.assertIsNot(x[0], y[0]) 757 758 def test_getstate_exc(self): 759 class EvilState(object): 760 def __getstate__(self): 761 raise ValueError("ain't got no stickin' state") 762 self.assertRaises(ValueError, copy.copy, EvilState()) 763 764 def test_copy_function(self): 765 self.assertEqual(copy.copy(global_foo), global_foo) 766 def foo(x, y): return x+y 767 self.assertEqual(copy.copy(foo), foo) 768 bar = lambda: None 769 self.assertEqual(copy.copy(bar), bar) 770 771 def test_deepcopy_function(self): 772 self.assertEqual(copy.deepcopy(global_foo), global_foo) 773 def foo(x, y): return x+y 774 self.assertEqual(copy.deepcopy(foo), foo) 775 bar = lambda: None 776 self.assertEqual(copy.deepcopy(bar), bar) 777 778 def _check_weakref(self, _copy): 779 class C(object): 780 pass 781 obj = C() 782 x = weakref.ref(obj) 783 y = _copy(x) 784 self.assertIs(y, x) 785 del obj 786 y = _copy(x) 787 self.assertIs(y, x) 788 789 def test_copy_weakref(self): 790 self._check_weakref(copy.copy) 791 792 def test_deepcopy_weakref(self): 793 self._check_weakref(copy.deepcopy) 794 795 def _check_copy_weakdict(self, _dicttype): 796 class C(object): 797 pass 798 a, b, c, d = [C() for i in range(4)] 799 u = _dicttype() 800 u[a] = b 801 u[c] = d 802 v = copy.copy(u) 803 self.assertIsNot(v, u) 804 self.assertEqual(v, u) 805 self.assertEqual(v[a], b) 806 self.assertEqual(v[c], d) 807 self.assertEqual(len(v), 2) 808 del c, d 809 support.gc_collect() # For PyPy or other GCs. 810 self.assertEqual(len(v), 1) 811 x, y = C(), C() 812 # The underlying containers are decoupled 813 v[x] = y 814 self.assertNotIn(x, u) 815 816 def test_copy_weakkeydict(self): 817 self._check_copy_weakdict(weakref.WeakKeyDictionary) 818 819 def test_copy_weakvaluedict(self): 820 self._check_copy_weakdict(weakref.WeakValueDictionary) 821 822 def test_deepcopy_weakkeydict(self): 823 class C(object): 824 def __init__(self, i): 825 self.i = i 826 a, b, c, d = [C(i) for i in range(4)] 827 u = weakref.WeakKeyDictionary() 828 u[a] = b 829 u[c] = d 830 # Keys aren't copied, values are 831 v = copy.deepcopy(u) 832 self.assertNotEqual(v, u) 833 self.assertEqual(len(v), 2) 834 self.assertIsNot(v[a], b) 835 self.assertIsNot(v[c], d) 836 self.assertEqual(v[a].i, b.i) 837 self.assertEqual(v[c].i, d.i) 838 del c 839 support.gc_collect() # For PyPy or other GCs. 840 self.assertEqual(len(v), 1) 841 842 def test_deepcopy_weakvaluedict(self): 843 class C(object): 844 def __init__(self, i): 845 self.i = i 846 a, b, c, d = [C(i) for i in range(4)] 847 u = weakref.WeakValueDictionary() 848 u[a] = b 849 u[c] = d 850 # Keys are copied, values aren't 851 v = copy.deepcopy(u) 852 self.assertNotEqual(v, u) 853 self.assertEqual(len(v), 2) 854 (x, y), (z, t) = sorted(v.items(), key=lambda pair: pair[0].i) 855 self.assertIsNot(x, a) 856 self.assertEqual(x.i, a.i) 857 self.assertIs(y, b) 858 self.assertIsNot(z, c) 859 self.assertEqual(z.i, c.i) 860 self.assertIs(t, d) 861 del x, y, z, t 862 del d 863 support.gc_collect() # For PyPy or other GCs. 864 self.assertEqual(len(v), 1) 865 866 def test_deepcopy_bound_method(self): 867 class Foo(object): 868 def m(self): 869 pass 870 f = Foo() 871 f.b = f.m 872 g = copy.deepcopy(f) 873 self.assertEqual(g.m, g.b) 874 self.assertIs(g.b.__self__, g) 875 g.b() 876 877 878def global_foo(x, y): return x+y 879 880if __name__ == "__main__": 881 unittest.main() 882