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