blob: ff4c987eba21b65c5659a3adcf1819740ced0cea [file] [log] [blame]
Guido van Rossum581cb932003-02-06 17:52:15 +00001"""Unit tests for the copy module."""
2
3import sys
4import copy
Guido van Rossumc06e3ac2003-02-07 17:30:18 +00005import copy_reg
Guido van Rossum581cb932003-02-06 17:52:15 +00006
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
Guido van Rossumc06e3ac2003-02-07 17:30:18 +000036 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
Guido van Rossume6908832003-02-19 01:19:28 +000049 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
Guido van Rossum581cb932003-02-06 17:52:15 +000059 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):
Guido van Rossume6908832003-02-19 01:19:28 +000068 class C(object):
Guido van Rossum581cb932003-02-06 17:52:15 +000069 def __getattribute__(self, name):
Guido van Rossume6908832003-02-19 01:19:28 +000070 if name.startswith("__reduce"):
Guido van Rossum581cb932003-02-06 17:52:15 +000071 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,
Martin v. Löwisba8f5ff2003-06-14 07:10:06 +000087 NewStyle, xrange(10), Classic, max]
Guido van Rossum581cb932003-02-06 17:52:15 +000088 for x in tests:
Walter Dörwald70a6b492004-02-12 17:35:32 +000089 self.assert_(copy.copy(x) is x, repr(x))
Guido van Rossum581cb932003-02-06 17:52:15 +000090
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):
Guido van Rossum99d2c252003-06-13 19:28:47 +0000177 # Tests of reflexive objects are under type-specific sections below.
178 # This tests only repetitions of objects.
Guido van Rossum581cb932003-02-06 17:52:15 +0000179 x = []
Guido van Rossum99d2c252003-06-13 19:28:47 +0000180 x = [x, x]
Guido van Rossum581cb932003-02-06 17:52:15 +0000181 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])
Guido van Rossum99d2c252003-06-13 19:28:47 +0000185 self.assert_(y[0] is y[1])
Guido van Rossum581cb932003-02-06 17:52:15 +0000186
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
Guido van Rossumc06e3ac2003-02-07 17:30:18 +0000209 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
Guido van Rossume6908832003-02-19 01:19:28 +0000222 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
Guido van Rossum581cb932003-02-06 17:52:15 +0000232 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):
Guido van Rossume6908832003-02-19 01:19:28 +0000241 class C(object):
Guido van Rossum581cb932003-02-06 17:52:15 +0000242 def __getattribute__(self, name):
Guido van Rossume6908832003-02-19 01:19:28 +0000243 if name.startswith("__reduce"):
Guido van Rossum581cb932003-02-06 17:52:15 +0000244 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,
Martin v. Löwisba8f5ff2003-06-14 07:10:06 +0000260 NewStyle, xrange(10), Classic, max]
Guido van Rossum581cb932003-02-06 17:52:15 +0000261 for x in tests:
Walter Dörwald70a6b492004-02-12 17:35:32 +0000262 self.assert_(copy.deepcopy(x) is x, repr(x))
Guido van Rossum581cb932003-02-06 17:52:15 +0000263
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
Guido van Rossum99d2c252003-06-13 19:28:47 +0000271 def test_deepcopy_reflexive_list(self):
272 x = []
273 x.append(x)
274 y = copy.deepcopy(x)
Armin Rigo2b3eb402003-10-28 12:05:48 +0000275 self.assertRaises(RuntimeError, cmp, y, x)
Guido van Rossum99d2c252003-06-13 19:28:47 +0000276 self.assert_(y is not x)
Armin Rigo2b3eb402003-10-28 12:05:48 +0000277 self.assert_(y[0] is y)
278 self.assertEqual(len(y), 1)
Guido van Rossum99d2c252003-06-13 19:28:47 +0000279
Guido van Rossum581cb932003-02-06 17:52:15 +0000280 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
Guido van Rossum99d2c252003-06-13 19:28:47 +0000287 def test_deepcopy_reflexive_tuple(self):
288 x = ([],)
289 x[0].append(x)
290 y = copy.deepcopy(x)
Armin Rigo2b3eb402003-10-28 12:05:48 +0000291 self.assertRaises(RuntimeError, cmp, y, x)
Guido van Rossum99d2c252003-06-13 19:28:47 +0000292 self.assert_(y is not x)
293 self.assert_(y[0] is not x[0])
294 self.assert_(y[0][0] is y)
295
Guido van Rossum581cb932003-02-06 17:52:15 +0000296 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
Guido van Rossum99d2c252003-06-13 19:28:47 +0000303 def test_deepcopy_reflexive_dict(self):
304 x = {}
305 x['foo'] = x
306 y = copy.deepcopy(x)
Armin Rigo2b3eb402003-10-28 12:05:48 +0000307 self.assertRaises(RuntimeError, cmp, y, x)
Guido van Rossum99d2c252003-06-13 19:28:47 +0000308 self.assert_(y is not x)
309 self.assert_(y['foo'] is y)
Armin Rigo2b3eb402003-10-28 12:05:48 +0000310 self.assertEqual(len(y), 1)
Guido van Rossum99d2c252003-06-13 19:28:47 +0000311
Guido van Rossum581cb932003-02-06 17:52:15 +0000312 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 __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.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 __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.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 __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.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 __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.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 __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.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 __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.assert_(y is not x)
399 self.assert_(y.foo is not x.foo)
400
Guido van Rossum99d2c252003-06-13 19:28:47 +0000401 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
Guido van Rossum581cb932003-02-06 17:52:15 +0000410 # _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 __cmp__(self, other):
438 return cmp(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 __cmp__(self, other):
454 return cmp(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
Guido van Rossum99d2c252003-06-13 19:28:47 +0000463 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
Guido van Rossum90e05b02003-02-06 18:18:23 +0000472 # 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 __cmp__(self, other):
479 return (cmp(list(self), list(other)) or
480 cmp(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.iteritems())
495 def __cmp__(self, other):
496 return (cmp(dict(self), list(dict)) or
497 cmp(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
Guido van Rossumc7557582003-02-06 19:53:22 +0000508 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
Guido van Rossum85233bf2003-02-06 21:25:12 +0000547 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
Neal Norwitze2fdc612003-06-08 13:19:58 +0000565 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
Guido van Rossum1968ad32006-02-25 22:38:04 +0000571 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
Guido van Rossum581cb932003-02-06 17:52:15 +0000587def test_main():
Walter Dörwald21d3a322003-05-01 17:45:56 +0000588 test_support.run_unittest(TestCopy)
Guido van Rossum581cb932003-02-06 17:52:15 +0000589
590if __name__ == "__main__":
591 test_main()