1"""Unit tests for the copy module.""" 2 3import copy 4import copy_reg 5import weakref 6 7import unittest 8from test import test_support 9 10class TestCopy(unittest.TestCase): 11 12 # Attempt full line coverage of copy.py from top to bottom 13 14 def test_exceptions(self): 15 self.assertTrue(copy.Error is copy.error) 16 self.assertTrue(issubclass(copy.Error, Exception)) 17 18 # The copy() method 19 20 def test_copy_basic(self): 21 x = 42 22 y = copy.copy(x) 23 self.assertEqual(x, y) 24 25 def test_copy_copy(self): 26 class C(object): 27 def __init__(self, foo): 28 self.foo = foo 29 def __copy__(self): 30 return C(self.foo) 31 x = C(42) 32 y = copy.copy(x) 33 self.assertEqual(y.__class__, x.__class__) 34 self.assertEqual(y.foo, x.foo) 35 36 def test_copy_registry(self): 37 class C(object): 38 def __new__(cls, foo): 39 obj = object.__new__(cls) 40 obj.foo = foo 41 return obj 42 def pickle_C(obj): 43 return (C, (obj.foo,)) 44 x = C(42) 45 self.assertRaises(TypeError, copy.copy, x) 46 copy_reg.pickle(C, pickle_C, C) 47 y = copy.copy(x) 48 49 def test_copy_reduce_ex(self): 50 class C(object): 51 def __reduce_ex__(self, proto): 52 return "" 53 def __reduce__(self): 54 raise test_support.TestFailed, "shouldn't call this" 55 x = C() 56 y = copy.copy(x) 57 self.assertTrue(y is x) 58 59 def test_copy_reduce(self): 60 class C(object): 61 def __reduce__(self): 62 return "" 63 x = C() 64 y = copy.copy(x) 65 self.assertTrue(y is x) 66 67 def test_copy_cant(self): 68 class C(object): 69 def __getattribute__(self, name): 70 if name.startswith("__reduce"): 71 raise AttributeError, name 72 return object.__getattribute__(self, name) 73 x = C() 74 self.assertRaises(copy.Error, copy.copy, x) 75 76 # Type-specific _copy_xxx() methods 77 78 def test_copy_atomic(self): 79 class Classic: 80 pass 81 class NewStyle(object): 82 pass 83 def f(): 84 pass 85 tests = [None, 42, 2L**100, 3.14, True, False, 1j, 86 "hello", u"hello\u1234", f.func_code, 87 NewStyle, xrange(10), Classic, max] 88 for x in tests: 89 self.assertTrue(copy.copy(x) is x, repr(x)) 90 91 def test_copy_list(self): 92 x = [1, 2, 3] 93 self.assertEqual(copy.copy(x), x) 94 95 def test_copy_tuple(self): 96 x = (1, 2, 3) 97 self.assertEqual(copy.copy(x), x) 98 99 def test_copy_dict(self): 100 x = {"foo": 1, "bar": 2} 101 self.assertEqual(copy.copy(x), x) 102 103 def test_copy_inst_vanilla(self): 104 class C: 105 def __init__(self, foo): 106 self.foo = foo 107 def __cmp__(self, other): 108 return cmp(self.foo, other.foo) 109 x = C(42) 110 self.assertEqual(copy.copy(x), x) 111 112 def test_copy_inst_copy(self): 113 class C: 114 def __init__(self, foo): 115 self.foo = foo 116 def __copy__(self): 117 return C(self.foo) 118 def __cmp__(self, other): 119 return cmp(self.foo, other.foo) 120 x = C(42) 121 self.assertEqual(copy.copy(x), x) 122 123 def test_copy_inst_getinitargs(self): 124 class C: 125 def __init__(self, foo): 126 self.foo = foo 127 def __getinitargs__(self): 128 return (self.foo,) 129 def __cmp__(self, other): 130 return cmp(self.foo, other.foo) 131 x = C(42) 132 self.assertEqual(copy.copy(x), x) 133 134 def test_copy_inst_getstate(self): 135 class C: 136 def __init__(self, foo): 137 self.foo = foo 138 def __getstate__(self): 139 return {"foo": self.foo} 140 def __cmp__(self, other): 141 return cmp(self.foo, other.foo) 142 x = C(42) 143 self.assertEqual(copy.copy(x), x) 144 145 def test_copy_inst_setstate(self): 146 class C: 147 def __init__(self, foo): 148 self.foo = foo 149 def __setstate__(self, state): 150 self.foo = state["foo"] 151 def __cmp__(self, other): 152 return cmp(self.foo, other.foo) 153 x = C(42) 154 self.assertEqual(copy.copy(x), x) 155 156 def test_copy_inst_getstate_setstate(self): 157 class C: 158 def __init__(self, foo): 159 self.foo = foo 160 def __getstate__(self): 161 return self.foo 162 def __setstate__(self, state): 163 self.foo = state 164 def __cmp__(self, other): 165 return cmp(self.foo, other.foo) 166 x = C(42) 167 self.assertEqual(copy.copy(x), x) 168 169 # The deepcopy() method 170 171 def test_deepcopy_basic(self): 172 x = 42 173 y = copy.deepcopy(x) 174 self.assertEqual(y, x) 175 176 def test_deepcopy_memo(self): 177 # Tests of reflexive objects are under type-specific sections below. 178 # This tests only repetitions of objects. 179 x = [] 180 x = [x, x] 181 y = copy.deepcopy(x) 182 self.assertEqual(y, x) 183 self.assertTrue(y is not x) 184 self.assertTrue(y[0] is not x[0]) 185 self.assertTrue(y[0] is y[1]) 186 187 def test_deepcopy_issubclass(self): 188 # XXX Note: there's no way to test the TypeError coming out of 189 # issubclass() -- this can only happen when an extension 190 # module defines a "type" that doesn't formally inherit from 191 # type. 192 class Meta(type): 193 pass 194 class C: 195 __metaclass__ = Meta 196 self.assertEqual(copy.deepcopy(C), C) 197 198 def test_deepcopy_deepcopy(self): 199 class C(object): 200 def __init__(self, foo): 201 self.foo = foo 202 def __deepcopy__(self, memo=None): 203 return C(self.foo) 204 x = C(42) 205 y = copy.deepcopy(x) 206 self.assertEqual(y.__class__, x.__class__) 207 self.assertEqual(y.foo, x.foo) 208 209 def test_deepcopy_registry(self): 210 class C(object): 211 def __new__(cls, foo): 212 obj = object.__new__(cls) 213 obj.foo = foo 214 return obj 215 def pickle_C(obj): 216 return (C, (obj.foo,)) 217 x = C(42) 218 self.assertRaises(TypeError, copy.deepcopy, x) 219 copy_reg.pickle(C, pickle_C, C) 220 y = copy.deepcopy(x) 221 222 def test_deepcopy_reduce_ex(self): 223 class C(object): 224 def __reduce_ex__(self, proto): 225 return "" 226 def __reduce__(self): 227 raise test_support.TestFailed, "shouldn't call this" 228 x = C() 229 y = copy.deepcopy(x) 230 self.assertTrue(y is x) 231 232 def test_deepcopy_reduce(self): 233 class C(object): 234 def __reduce__(self): 235 return "" 236 x = C() 237 y = copy.deepcopy(x) 238 self.assertTrue(y is x) 239 240 def test_deepcopy_cant(self): 241 class C(object): 242 def __getattribute__(self, name): 243 if name.startswith("__reduce"): 244 raise AttributeError, name 245 return object.__getattribute__(self, name) 246 x = C() 247 self.assertRaises(copy.Error, copy.deepcopy, x) 248 249 # Type-specific _deepcopy_xxx() methods 250 251 def test_deepcopy_atomic(self): 252 class Classic: 253 pass 254 class NewStyle(object): 255 pass 256 def f(): 257 pass 258 tests = [None, 42, 2L**100, 3.14, True, False, 1j, 259 "hello", u"hello\u1234", f.func_code, 260 NewStyle, xrange(10), Classic, max] 261 for x in tests: 262 self.assertTrue(copy.deepcopy(x) is x, repr(x)) 263 264 def test_deepcopy_list(self): 265 x = [[1, 2], 3] 266 y = copy.deepcopy(x) 267 self.assertEqual(y, x) 268 self.assertTrue(x is not y) 269 self.assertTrue(x[0] is not y[0]) 270 271 def test_deepcopy_reflexive_list(self): 272 x = [] 273 x.append(x) 274 y = copy.deepcopy(x) 275 self.assertRaises(RuntimeError, cmp, y, x) 276 self.assertTrue(y is not x) 277 self.assertTrue(y[0] is y) 278 self.assertEqual(len(y), 1) 279 280 def test_deepcopy_tuple(self): 281 x = ([1, 2], 3) 282 y = copy.deepcopy(x) 283 self.assertEqual(y, x) 284 self.assertTrue(x is not y) 285 self.assertTrue(x[0] is not y[0]) 286 287 def test_deepcopy_reflexive_tuple(self): 288 x = ([],) 289 x[0].append(x) 290 y = copy.deepcopy(x) 291 self.assertRaises(RuntimeError, cmp, y, x) 292 self.assertTrue(y is not x) 293 self.assertTrue(y[0] is not x[0]) 294 self.assertTrue(y[0][0] is y) 295 296 def test_deepcopy_dict(self): 297 x = {"foo": [1, 2], "bar": 3} 298 y = copy.deepcopy(x) 299 self.assertEqual(y, x) 300 self.assertTrue(x is not y) 301 self.assertTrue(x["foo"] is not y["foo"]) 302 303 def test_deepcopy_reflexive_dict(self): 304 x = {} 305 x['foo'] = x 306 y = copy.deepcopy(x) 307 self.assertRaises(RuntimeError, cmp, y, x) 308 self.assertTrue(y is not x) 309 self.assertTrue(y['foo'] is y) 310 self.assertEqual(len(y), 1) 311 312 def test_deepcopy_keepalive(self): 313 memo = {} 314 x = 42 315 y = copy.deepcopy(x, memo) 316 self.assertTrue(memo[id(x)] is x) 317 318 def test_deepcopy_inst_vanilla(self): 319 class C: 320 def __init__(self, foo): 321 self.foo = foo 322 def __cmp__(self, other): 323 return cmp(self.foo, other.foo) 324 x = C([42]) 325 y = copy.deepcopy(x) 326 self.assertEqual(y, x) 327 self.assertTrue(y.foo is not x.foo) 328 329 def test_deepcopy_inst_deepcopy(self): 330 class C: 331 def __init__(self, foo): 332 self.foo = foo 333 def __deepcopy__(self, memo): 334 return C(copy.deepcopy(self.foo, memo)) 335 def __cmp__(self, other): 336 return cmp(self.foo, other.foo) 337 x = C([42]) 338 y = copy.deepcopy(x) 339 self.assertEqual(y, x) 340 self.assertTrue(y is not x) 341 self.assertTrue(y.foo is not x.foo) 342 343 def test_deepcopy_inst_getinitargs(self): 344 class C: 345 def __init__(self, foo): 346 self.foo = foo 347 def __getinitargs__(self): 348 return (self.foo,) 349 def __cmp__(self, other): 350 return cmp(self.foo, other.foo) 351 x = C([42]) 352 y = copy.deepcopy(x) 353 self.assertEqual(y, x) 354 self.assertTrue(y is not x) 355 self.assertTrue(y.foo is not x.foo) 356 357 def test_deepcopy_inst_getstate(self): 358 class C: 359 def __init__(self, foo): 360 self.foo = foo 361 def __getstate__(self): 362 return {"foo": self.foo} 363 def __cmp__(self, other): 364 return cmp(self.foo, other.foo) 365 x = C([42]) 366 y = copy.deepcopy(x) 367 self.assertEqual(y, x) 368 self.assertTrue(y is not x) 369 self.assertTrue(y.foo is not x.foo) 370 371 def test_deepcopy_inst_setstate(self): 372 class C: 373 def __init__(self, foo): 374 self.foo = foo 375 def __setstate__(self, state): 376 self.foo = state["foo"] 377 def __cmp__(self, other): 378 return cmp(self.foo, other.foo) 379 x = C([42]) 380 y = copy.deepcopy(x) 381 self.assertEqual(y, x) 382 self.assertTrue(y is not x) 383 self.assertTrue(y.foo is not x.foo) 384 385 def test_deepcopy_inst_getstate_setstate(self): 386 class C: 387 def __init__(self, foo): 388 self.foo = foo 389 def __getstate__(self): 390 return self.foo 391 def __setstate__(self, state): 392 self.foo = state 393 def __cmp__(self, other): 394 return cmp(self.foo, other.foo) 395 x = C([42]) 396 y = copy.deepcopy(x) 397 self.assertEqual(y, x) 398 self.assertTrue(y is not x) 399 self.assertTrue(y.foo is not x.foo) 400 401 def test_deepcopy_reflexive_inst(self): 402 class C: 403 pass 404 x = C() 405 x.foo = x 406 y = copy.deepcopy(x) 407 self.assertTrue(y is not x) 408 self.assertTrue(y.foo is y) 409 410 # _reconstruct() 411 412 def test_reconstruct_string(self): 413 class C(object): 414 def __reduce__(self): 415 return "" 416 x = C() 417 y = copy.copy(x) 418 self.assertTrue(y is x) 419 y = copy.deepcopy(x) 420 self.assertTrue(y is x) 421 422 def test_reconstruct_nostate(self): 423 class C(object): 424 def __reduce__(self): 425 return (C, ()) 426 x = C() 427 x.foo = 42 428 y = copy.copy(x) 429 self.assertTrue(y.__class__ is x.__class__) 430 y = copy.deepcopy(x) 431 self.assertTrue(y.__class__ is x.__class__) 432 433 def test_reconstruct_state(self): 434 class C(object): 435 def __reduce__(self): 436 return (C, (), self.__dict__) 437 def __cmp__(self, other): 438 return cmp(self.__dict__, other.__dict__) 439 __hash__ = None # Silence Py3k warning 440 x = C() 441 x.foo = [42] 442 y = copy.copy(x) 443 self.assertEqual(y, x) 444 y = copy.deepcopy(x) 445 self.assertEqual(y, x) 446 self.assertTrue(y.foo is not x.foo) 447 448 def test_reconstruct_state_setstate(self): 449 class C(object): 450 def __reduce__(self): 451 return (C, (), self.__dict__) 452 def __setstate__(self, state): 453 self.__dict__.update(state) 454 def __cmp__(self, other): 455 return cmp(self.__dict__, other.__dict__) 456 __hash__ = None # Silence Py3k warning 457 x = C() 458 x.foo = [42] 459 y = copy.copy(x) 460 self.assertEqual(y, x) 461 y = copy.deepcopy(x) 462 self.assertEqual(y, x) 463 self.assertTrue(y.foo is not x.foo) 464 465 def test_reconstruct_reflexive(self): 466 class C(object): 467 pass 468 x = C() 469 x.foo = x 470 y = copy.deepcopy(x) 471 self.assertTrue(y is not x) 472 self.assertTrue(y.foo is y) 473 474 # Additions for Python 2.3 and pickle protocol 2 475 476 def test_reduce_4tuple(self): 477 class C(list): 478 def __reduce__(self): 479 return (C, (), self.__dict__, iter(self)) 480 def __cmp__(self, other): 481 return (cmp(list(self), list(other)) or 482 cmp(self.__dict__, other.__dict__)) 483 __hash__ = None # Silence Py3k warning 484 x = C([[1, 2], 3]) 485 y = copy.copy(x) 486 self.assertEqual(x, y) 487 self.assertTrue(x is not y) 488 self.assertTrue(x[0] is y[0]) 489 y = copy.deepcopy(x) 490 self.assertEqual(x, y) 491 self.assertTrue(x is not y) 492 self.assertTrue(x[0] is not y[0]) 493 494 def test_reduce_5tuple(self): 495 class C(dict): 496 def __reduce__(self): 497 return (C, (), self.__dict__, None, self.iteritems()) 498 def __cmp__(self, other): 499 return (cmp(dict(self), list(dict)) or 500 cmp(self.__dict__, other.__dict__)) 501 __hash__ = None # Silence Py3k warning 502 x = C([("foo", [1, 2]), ("bar", 3)]) 503 y = copy.copy(x) 504 self.assertEqual(x, y) 505 self.assertTrue(x is not y) 506 self.assertTrue(x["foo"] is y["foo"]) 507 y = copy.deepcopy(x) 508 self.assertEqual(x, y) 509 self.assertTrue(x is not y) 510 self.assertTrue(x["foo"] is not y["foo"]) 511 512 def test_copy_slots(self): 513 class C(object): 514 __slots__ = ["foo"] 515 x = C() 516 x.foo = [42] 517 y = copy.copy(x) 518 self.assertTrue(x.foo is y.foo) 519 520 def test_deepcopy_slots(self): 521 class C(object): 522 __slots__ = ["foo"] 523 x = C() 524 x.foo = [42] 525 y = copy.deepcopy(x) 526 self.assertEqual(x.foo, y.foo) 527 self.assertTrue(x.foo is not y.foo) 528 529 def test_deepcopy_dict_subclass(self): 530 class C(dict): 531 def __init__(self, d=None): 532 if not d: 533 d = {} 534 self._keys = list(d.keys()) 535 dict.__init__(self, d) 536 def __setitem__(self, key, item): 537 dict.__setitem__(self, key, item) 538 if key not in self._keys: 539 self._keys.append(key) 540 x = C(d={'foo':0}) 541 y = copy.deepcopy(x) 542 self.assertEqual(x, y) 543 self.assertEqual(x._keys, y._keys) 544 self.assertTrue(x is not y) 545 x['bar'] = 1 546 self.assertNotEqual(x, y) 547 self.assertNotEqual(x._keys, y._keys) 548 549 def test_copy_list_subclass(self): 550 class C(list): 551 pass 552 x = C([[1, 2], 3]) 553 x.foo = [4, 5] 554 y = copy.copy(x) 555 self.assertEqual(list(x), list(y)) 556 self.assertEqual(x.foo, y.foo) 557 self.assertTrue(x[0] is y[0]) 558 self.assertTrue(x.foo is y.foo) 559 560 def test_deepcopy_list_subclass(self): 561 class C(list): 562 pass 563 x = C([[1, 2], 3]) 564 x.foo = [4, 5] 565 y = copy.deepcopy(x) 566 self.assertEqual(list(x), list(y)) 567 self.assertEqual(x.foo, y.foo) 568 self.assertTrue(x[0] is not y[0]) 569 self.assertTrue(x.foo is not y.foo) 570 571 def test_copy_tuple_subclass(self): 572 class C(tuple): 573 pass 574 x = C([1, 2, 3]) 575 self.assertEqual(tuple(x), (1, 2, 3)) 576 y = copy.copy(x) 577 self.assertEqual(tuple(y), (1, 2, 3)) 578 579 def test_deepcopy_tuple_subclass(self): 580 class C(tuple): 581 pass 582 x = C([[1, 2], 3]) 583 self.assertEqual(tuple(x), ([1, 2], 3)) 584 y = copy.deepcopy(x) 585 self.assertEqual(tuple(y), ([1, 2], 3)) 586 self.assertTrue(x is not y) 587 self.assertTrue(x[0] is not y[0]) 588 589 def test_getstate_exc(self): 590 class EvilState(object): 591 def __getstate__(self): 592 raise ValueError, "ain't got no stickin' state" 593 self.assertRaises(ValueError, copy.copy, EvilState()) 594 595 def test_copy_function(self): 596 self.assertEqual(copy.copy(global_foo), global_foo) 597 def foo(x, y): return x+y 598 self.assertEqual(copy.copy(foo), foo) 599 bar = lambda: None 600 self.assertEqual(copy.copy(bar), bar) 601 602 def test_deepcopy_function(self): 603 self.assertEqual(copy.deepcopy(global_foo), global_foo) 604 def foo(x, y): return x+y 605 self.assertEqual(copy.deepcopy(foo), foo) 606 bar = lambda: None 607 self.assertEqual(copy.deepcopy(bar), bar) 608 609 def _check_weakref(self, _copy): 610 class C(object): 611 pass 612 obj = C() 613 x = weakref.ref(obj) 614 y = _copy(x) 615 self.assertTrue(y is x) 616 del obj 617 y = _copy(x) 618 self.assertTrue(y is x) 619 620 def test_copy_weakref(self): 621 self._check_weakref(copy.copy) 622 623 def test_deepcopy_weakref(self): 624 self._check_weakref(copy.deepcopy) 625 626 def _check_copy_weakdict(self, _dicttype): 627 class C(object): 628 pass 629 a, b, c, d = [C() for i in xrange(4)] 630 u = _dicttype() 631 u[a] = b 632 u[c] = d 633 v = copy.copy(u) 634 self.assertFalse(v is u) 635 self.assertEqual(v, u) 636 self.assertEqual(v[a], b) 637 self.assertEqual(v[c], d) 638 self.assertEqual(len(v), 2) 639 del c, d 640 self.assertEqual(len(v), 1) 641 x, y = C(), C() 642 # The underlying containers are decoupled 643 v[x] = y 644 self.assertNotIn(x, u) 645 646 def test_copy_weakkeydict(self): 647 self._check_copy_weakdict(weakref.WeakKeyDictionary) 648 649 def test_copy_weakvaluedict(self): 650 self._check_copy_weakdict(weakref.WeakValueDictionary) 651 652 def test_deepcopy_weakkeydict(self): 653 class C(object): 654 def __init__(self, i): 655 self.i = i 656 a, b, c, d = [C(i) for i in xrange(4)] 657 u = weakref.WeakKeyDictionary() 658 u[a] = b 659 u[c] = d 660 # Keys aren't copied, values are 661 v = copy.deepcopy(u) 662 self.assertNotEqual(v, u) 663 self.assertEqual(len(v), 2) 664 self.assertFalse(v[a] is b) 665 self.assertFalse(v[c] is d) 666 self.assertEqual(v[a].i, b.i) 667 self.assertEqual(v[c].i, d.i) 668 del c 669 self.assertEqual(len(v), 1) 670 671 def test_deepcopy_weakvaluedict(self): 672 class C(object): 673 def __init__(self, i): 674 self.i = i 675 a, b, c, d = [C(i) for i in xrange(4)] 676 u = weakref.WeakValueDictionary() 677 u[a] = b 678 u[c] = d 679 # Keys are copied, values aren't 680 v = copy.deepcopy(u) 681 self.assertNotEqual(v, u) 682 self.assertEqual(len(v), 2) 683 (x, y), (z, t) = sorted(v.items(), key=lambda pair: pair[0].i) 684 self.assertFalse(x is a) 685 self.assertEqual(x.i, a.i) 686 self.assertTrue(y is b) 687 self.assertFalse(z is c) 688 self.assertEqual(z.i, c.i) 689 self.assertTrue(t is d) 690 del x, y, z, t 691 del d 692 self.assertEqual(len(v), 1) 693 694 def test_deepcopy_bound_method(self): 695 class Foo(object): 696 def m(self): 697 pass 698 f = Foo() 699 f.b = f.m 700 g = copy.deepcopy(f) 701 self.assertEqual(g.m, g.b) 702 self.assertTrue(g.b.im_self is g) 703 g.b() 704 705 706def global_foo(x, y): return x+y 707 708def test_main(): 709 test_support.run_unittest(TestCopy) 710 711if __name__ == "__main__": 712 test_main() 713