test_copy.py revision 3add4d78ff9f5de02e2c0de09efe9a9b5317539f
1"""Unit tests for the copy module.""" 2 3import sys 4import copy 5import copy_reg 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.assert_(copy.Error is copy.error) 16 self.assert_(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.assert_(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.assert_(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, 2**100, 3.14, True, False, 1j, 86 "hello", "hello\u1234", f.__code__, 87 NewStyle, range(10), Classic, max] 88 for x in tests: 89 self.assert_(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 __eq__(self, other): 108 return 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 __eq__(self, other): 119 return 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 __eq__(self, other): 130 return 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 __eq__(self, other): 141 return 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 __eq__(self, other): 152 return 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 __eq__(self, other): 165 return 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.assert_(y is not x) 184 self.assert_(y[0] is not x[0]) 185 self.assert_(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(metaclass=Meta): 195 pass 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.assert_(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.assert_(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, 2**100, 3.14, True, False, 1j, 259 "hello", "hello\u1234", f.__code__, 260 NewStyle, range(10), Classic, max] 261 for x in tests: 262 self.assert_(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.assert_(x is not y) 269 self.assert_(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.assert_(y is not x) 277 self.assert_(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.assert_(x is not y) 285 self.assert_(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.assert_(y is not x) 293 self.assert_(y[0] is not x[0]) 294 self.assert_(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.assert_(x is not y) 301 self.assert_(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(TypeError, cmp, y, x) 308 self.assert_(y is not x) 309 self.assert_(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.assert_(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 __eq__(self, other): 323 return self.foo == other.foo 324 x = C([42]) 325 y = copy.deepcopy(x) 326 self.assertEqual(y, x) 327 self.assert_(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 __eq__(self, other): 336 return self.foo == other.foo 337 x = C([42]) 338 y = copy.deepcopy(x) 339 self.assertEqual(y, x) 340 self.assert_(y is not x) 341 self.assert_(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 __eq__(self, other): 350 return self.foo == other.foo 351 x = C([42]) 352 y = copy.deepcopy(x) 353 self.assertEqual(y, x) 354 self.assert_(y is not x) 355 self.assert_(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 __eq__(self, other): 364 return self.foo == other.foo 365 x = C([42]) 366 y = copy.deepcopy(x) 367 self.assertEqual(y, x) 368 self.assert_(y is not x) 369 self.assert_(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 __eq__(self, other): 378 return self.foo == other.foo 379 x = C([42]) 380 y = copy.deepcopy(x) 381 self.assertEqual(y, x) 382 self.assert_(y is not x) 383 self.assert_(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 __eq__(self, other): 394 return self.foo == other.foo 395 x = C([42]) 396 y = copy.deepcopy(x) 397 self.assertEqual(y, x) 398 self.assert_(y is not x) 399 self.assert_(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.assert_(y is not x) 408 self.assert_(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.assert_(y is x) 419 y = copy.deepcopy(x) 420 self.assert_(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.assert_(y.__class__ is x.__class__) 430 y = copy.deepcopy(x) 431 self.assert_(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 __eq__(self, other): 438 return self.__dict__ == other.__dict__ 439 x = C() 440 x.foo = [42] 441 y = copy.copy(x) 442 self.assertEqual(y, x) 443 y = copy.deepcopy(x) 444 self.assertEqual(y, x) 445 self.assert_(y.foo is not x.foo) 446 447 def test_reconstruct_state_setstate(self): 448 class C(object): 449 def __reduce__(self): 450 return (C, (), self.__dict__) 451 def __setstate__(self, state): 452 self.__dict__.update(state) 453 def __eq__(self, other): 454 return self.__dict__ == other.__dict__ 455 x = C() 456 x.foo = [42] 457 y = copy.copy(x) 458 self.assertEqual(y, x) 459 y = copy.deepcopy(x) 460 self.assertEqual(y, x) 461 self.assert_(y.foo is not x.foo) 462 463 def test_reconstruct_reflexive(self): 464 class C(object): 465 pass 466 x = C() 467 x.foo = x 468 y = copy.deepcopy(x) 469 self.assert_(y is not x) 470 self.assert_(y.foo is y) 471 472 # Additions for Python 2.3 and pickle protocol 2 473 474 def test_reduce_4tuple(self): 475 class C(list): 476 def __reduce__(self): 477 return (C, (), self.__dict__, iter(self)) 478 def __eq__(self, other): 479 return (list(self) == list(other) and 480 self.__dict__ == other.__dict__) 481 x = C([[1, 2], 3]) 482 y = copy.copy(x) 483 self.assertEqual(x, y) 484 self.assert_(x is not y) 485 self.assert_(x[0] is y[0]) 486 y = copy.deepcopy(x) 487 self.assertEqual(x, y) 488 self.assert_(x is not y) 489 self.assert_(x[0] is not y[0]) 490 491 def test_reduce_5tuple(self): 492 class C(dict): 493 def __reduce__(self): 494 return (C, (), self.__dict__, None, self.items()) 495 def __eq__(self, other): 496 return (dict(self) == dict(other) and 497 self.__dict__ == other.__dict__) 498 x = C([("foo", [1, 2]), ("bar", 3)]) 499 y = copy.copy(x) 500 self.assertEqual(x, y) 501 self.assert_(x is not y) 502 self.assert_(x["foo"] is y["foo"]) 503 y = copy.deepcopy(x) 504 self.assertEqual(x, y) 505 self.assert_(x is not y) 506 self.assert_(x["foo"] is not y["foo"]) 507 508 def test_copy_slots(self): 509 class C(object): 510 __slots__ = ["foo"] 511 x = C() 512 x.foo = [42] 513 y = copy.copy(x) 514 self.assert_(x.foo is y.foo) 515 516 def test_deepcopy_slots(self): 517 class C(object): 518 __slots__ = ["foo"] 519 x = C() 520 x.foo = [42] 521 y = copy.deepcopy(x) 522 self.assertEqual(x.foo, y.foo) 523 self.assert_(x.foo is not y.foo) 524 525 def test_copy_list_subclass(self): 526 class C(list): 527 pass 528 x = C([[1, 2], 3]) 529 x.foo = [4, 5] 530 y = copy.copy(x) 531 self.assertEqual(list(x), list(y)) 532 self.assertEqual(x.foo, y.foo) 533 self.assert_(x[0] is y[0]) 534 self.assert_(x.foo is y.foo) 535 536 def test_deepcopy_list_subclass(self): 537 class C(list): 538 pass 539 x = C([[1, 2], 3]) 540 x.foo = [4, 5] 541 y = copy.deepcopy(x) 542 self.assertEqual(list(x), list(y)) 543 self.assertEqual(x.foo, y.foo) 544 self.assert_(x[0] is not y[0]) 545 self.assert_(x.foo is not y.foo) 546 547 def test_copy_tuple_subclass(self): 548 class C(tuple): 549 pass 550 x = C([1, 2, 3]) 551 self.assertEqual(tuple(x), (1, 2, 3)) 552 y = copy.copy(x) 553 self.assertEqual(tuple(y), (1, 2, 3)) 554 555 def test_deepcopy_tuple_subclass(self): 556 class C(tuple): 557 pass 558 x = C([[1, 2], 3]) 559 self.assertEqual(tuple(x), ([1, 2], 3)) 560 y = copy.deepcopy(x) 561 self.assertEqual(tuple(y), ([1, 2], 3)) 562 self.assert_(x is not y) 563 self.assert_(x[0] is not y[0]) 564 565 def test_getstate_exc(self): 566 class EvilState(object): 567 def __getstate__(self): 568 raise ValueError("ain't got no stickin' state") 569 self.assertRaises(ValueError, copy.copy, EvilState()) 570 571 def test_copy_function(self): 572 self.assertEqual(copy.copy(global_foo), global_foo) 573 def foo(x, y): return x+y 574 self.assertEqual(copy.copy(foo), foo) 575 bar = lambda: None 576 self.assertEqual(copy.copy(bar), bar) 577 578 def test_deepcopy_function(self): 579 self.assertEqual(copy.deepcopy(global_foo), global_foo) 580 def foo(x, y): return x+y 581 self.assertEqual(copy.deepcopy(foo), foo) 582 bar = lambda: None 583 self.assertEqual(copy.deepcopy(bar), bar) 584 585def global_foo(x, y): return x+y 586 587def test_main(): 588 test_support.run_unittest(TestCopy) 589 590if __name__ == "__main__": 591 test_main() 592