blob: 0e39e8356de15ab597a5985c37adfe7200540b3c [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,
87 NewStyle, xrange(10), Classic]
88 for x in tests:
89 self.assert_(copy.copy(x) is x, `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 x = []
178 x.append(x)
179 y = copy.deepcopy(x)
180 self.assertEqual(y, x)
181 self.assert_(y is not x)
182 self.assert_(y[0] is not x[0])
183 self.assert_(y is y[0])
184
185 def test_deepcopy_issubclass(self):
186 # XXX Note: there's no way to test the TypeError coming out of
187 # issubclass() -- this can only happen when an extension
188 # module defines a "type" that doesn't formally inherit from
189 # type.
190 class Meta(type):
191 pass
192 class C:
193 __metaclass__ = Meta
194 self.assertEqual(copy.deepcopy(C), C)
195
196 def test_deepcopy_deepcopy(self):
197 class C(object):
198 def __init__(self, foo):
199 self.foo = foo
200 def __deepcopy__(self, memo=None):
201 return C(self.foo)
202 x = C(42)
203 y = copy.deepcopy(x)
204 self.assertEqual(y.__class__, x.__class__)
205 self.assertEqual(y.foo, x.foo)
206
Guido van Rossumc06e3ac2003-02-07 17:30:18 +0000207 def test_deepcopy_registry(self):
208 class C(object):
209 def __new__(cls, foo):
210 obj = object.__new__(cls)
211 obj.foo = foo
212 return obj
213 def pickle_C(obj):
214 return (C, (obj.foo,))
215 x = C(42)
216 self.assertRaises(TypeError, copy.deepcopy, x)
217 copy_reg.pickle(C, pickle_C, C)
218 y = copy.deepcopy(x)
219
Guido van Rossume6908832003-02-19 01:19:28 +0000220 def test_deepcopy_reduce_ex(self):
221 class C(object):
222 def __reduce_ex__(self, proto):
223 return ""
224 def __reduce__(self):
225 raise test_support.TestFailed, "shouldn't call this"
226 x = C()
227 y = copy.deepcopy(x)
228 self.assert_(y is x)
229
Guido van Rossum581cb932003-02-06 17:52:15 +0000230 def test_deepcopy_reduce(self):
231 class C(object):
232 def __reduce__(self):
233 return ""
234 x = C()
235 y = copy.deepcopy(x)
236 self.assert_(y is x)
237
238 def test_deepcopy_cant(self):
Guido van Rossume6908832003-02-19 01:19:28 +0000239 class C(object):
Guido van Rossum581cb932003-02-06 17:52:15 +0000240 def __getattribute__(self, name):
Guido van Rossume6908832003-02-19 01:19:28 +0000241 if name.startswith("__reduce"):
Guido van Rossum581cb932003-02-06 17:52:15 +0000242 raise AttributeError, name
243 return object.__getattribute__(self, name)
244 x = C()
245 self.assertRaises(copy.Error, copy.deepcopy, x)
246
247 # Type-specific _deepcopy_xxx() methods
248
249 def test_deepcopy_atomic(self):
250 class Classic:
251 pass
252 class NewStyle(object):
253 pass
254 def f():
255 pass
256 tests = [None, 42, 2L**100, 3.14, True, False, 1j,
257 "hello", u"hello\u1234", f.func_code,
Guido van Rossum1dca4822003-02-07 17:53:23 +0000258 NewStyle, xrange(10), Classic]
Guido van Rossum581cb932003-02-06 17:52:15 +0000259 for x in tests:
260 self.assert_(copy.deepcopy(x) is x, `x`)
261
262 def test_deepcopy_list(self):
263 x = [[1, 2], 3]
264 y = copy.deepcopy(x)
265 self.assertEqual(y, x)
266 self.assert_(x is not y)
267 self.assert_(x[0] is not y[0])
268
269 def test_deepcopy_tuple(self):
270 x = ([1, 2], 3)
271 y = copy.deepcopy(x)
272 self.assertEqual(y, x)
273 self.assert_(x is not y)
274 self.assert_(x[0] is not y[0])
275
276 def test_deepcopy_dict(self):
277 x = {"foo": [1, 2], "bar": 3}
278 y = copy.deepcopy(x)
279 self.assertEqual(y, x)
280 self.assert_(x is not y)
281 self.assert_(x["foo"] is not y["foo"])
282
283 def test_deepcopy_keepalive(self):
284 memo = {}
285 x = 42
286 y = copy.deepcopy(x, memo)
287 self.assert_(memo[id(x)] is x)
288
289 def test_deepcopy_inst_vanilla(self):
290 class C:
291 def __init__(self, foo):
292 self.foo = foo
293 def __cmp__(self, other):
294 return cmp(self.foo, other.foo)
295 x = C([42])
296 y = copy.deepcopy(x)
297 self.assertEqual(y, x)
298 self.assert_(y.foo is not x.foo)
299
300 def test_deepcopy_inst_deepcopy(self):
301 class C:
302 def __init__(self, foo):
303 self.foo = foo
304 def __deepcopy__(self, memo):
305 return C(copy.deepcopy(self.foo, memo))
306 def __cmp__(self, other):
307 return cmp(self.foo, other.foo)
308 x = C([42])
309 y = copy.deepcopy(x)
310 self.assertEqual(y, x)
311 self.assert_(y is not x)
312 self.assert_(y.foo is not x.foo)
313
314 def test_deepcopy_inst_getinitargs(self):
315 class C:
316 def __init__(self, foo):
317 self.foo = foo
318 def __getinitargs__(self):
319 return (self.foo,)
320 def __cmp__(self, other):
321 return cmp(self.foo, other.foo)
322 x = C([42])
323 y = copy.deepcopy(x)
324 self.assertEqual(y, x)
325 self.assert_(y is not x)
326 self.assert_(y.foo is not x.foo)
327
328 def test_deepcopy_inst_getstate(self):
329 class C:
330 def __init__(self, foo):
331 self.foo = foo
332 def __getstate__(self):
333 return {"foo": self.foo}
334 def __cmp__(self, other):
335 return cmp(self.foo, other.foo)
336 x = C([42])
337 y = copy.deepcopy(x)
338 self.assertEqual(y, x)
339 self.assert_(y is not x)
340 self.assert_(y.foo is not x.foo)
341
342 def test_deepcopy_inst_setstate(self):
343 class C:
344 def __init__(self, foo):
345 self.foo = foo
346 def __setstate__(self, state):
347 self.foo = state["foo"]
348 def __cmp__(self, other):
349 return cmp(self.foo, other.foo)
350 x = C([42])
351 y = copy.deepcopy(x)
352 self.assertEqual(y, x)
353 self.assert_(y is not x)
354 self.assert_(y.foo is not x.foo)
355
356 def test_deepcopy_inst_getstate_setstate(self):
357 class C:
358 def __init__(self, foo):
359 self.foo = foo
360 def __getstate__(self):
361 return self.foo
362 def __setstate__(self, state):
363 self.foo = state
364 def __cmp__(self, other):
365 return cmp(self.foo, other.foo)
366 x = C([42])
367 y = copy.deepcopy(x)
368 self.assertEqual(y, x)
369 self.assert_(y is not x)
370 self.assert_(y.foo is not x.foo)
371
372 # _reconstruct()
373
374 def test_reconstruct_string(self):
375 class C(object):
376 def __reduce__(self):
377 return ""
378 x = C()
379 y = copy.copy(x)
380 self.assert_(y is x)
381 y = copy.deepcopy(x)
382 self.assert_(y is x)
383
384 def test_reconstruct_nostate(self):
385 class C(object):
386 def __reduce__(self):
387 return (C, ())
388 x = C()
389 x.foo = 42
390 y = copy.copy(x)
391 self.assert_(y.__class__ is x.__class__)
392 y = copy.deepcopy(x)
393 self.assert_(y.__class__ is x.__class__)
394
395 def test_reconstruct_state(self):
396 class C(object):
397 def __reduce__(self):
398 return (C, (), self.__dict__)
399 def __cmp__(self, other):
400 return cmp(self.__dict__, other.__dict__)
401 x = C()
402 x.foo = [42]
403 y = copy.copy(x)
404 self.assertEqual(y, x)
405 y = copy.deepcopy(x)
406 self.assertEqual(y, x)
407 self.assert_(y.foo is not x.foo)
408
409 def test_reconstruct_state_setstate(self):
410 class C(object):
411 def __reduce__(self):
412 return (C, (), self.__dict__)
413 def __setstate__(self, state):
414 self.__dict__.update(state)
415 def __cmp__(self, other):
416 return cmp(self.__dict__, other.__dict__)
417 x = C()
418 x.foo = [42]
419 y = copy.copy(x)
420 self.assertEqual(y, x)
421 y = copy.deepcopy(x)
422 self.assertEqual(y, x)
423 self.assert_(y.foo is not x.foo)
424
Guido van Rossum90e05b02003-02-06 18:18:23 +0000425 # Additions for Python 2.3 and pickle protocol 2
426
427 def test_reduce_4tuple(self):
428 class C(list):
429 def __reduce__(self):
430 return (C, (), self.__dict__, iter(self))
431 def __cmp__(self, other):
432 return (cmp(list(self), list(other)) or
433 cmp(self.__dict__, other.__dict__))
434 x = C([[1, 2], 3])
435 y = copy.copy(x)
436 self.assertEqual(x, y)
437 self.assert_(x is not y)
438 self.assert_(x[0] is y[0])
439 y = copy.deepcopy(x)
440 self.assertEqual(x, y)
441 self.assert_(x is not y)
442 self.assert_(x[0] is not y[0])
443
444 def test_reduce_5tuple(self):
445 class C(dict):
446 def __reduce__(self):
447 return (C, (), self.__dict__, None, self.iteritems())
448 def __cmp__(self, other):
449 return (cmp(dict(self), list(dict)) or
450 cmp(self.__dict__, other.__dict__))
451 x = C([("foo", [1, 2]), ("bar", 3)])
452 y = copy.copy(x)
453 self.assertEqual(x, y)
454 self.assert_(x is not y)
455 self.assert_(x["foo"] is y["foo"])
456 y = copy.deepcopy(x)
457 self.assertEqual(x, y)
458 self.assert_(x is not y)
459 self.assert_(x["foo"] is not y["foo"])
460
Guido van Rossumc7557582003-02-06 19:53:22 +0000461 def test_copy_slots(self):
462 class C(object):
463 __slots__ = ["foo"]
464 x = C()
465 x.foo = [42]
466 y = copy.copy(x)
467 self.assert_(x.foo is y.foo)
468
469 def test_deepcopy_slots(self):
470 class C(object):
471 __slots__ = ["foo"]
472 x = C()
473 x.foo = [42]
474 y = copy.deepcopy(x)
475 self.assertEqual(x.foo, y.foo)
476 self.assert_(x.foo is not y.foo)
477
478 def test_copy_list_subclass(self):
479 class C(list):
480 pass
481 x = C([[1, 2], 3])
482 x.foo = [4, 5]
483 y = copy.copy(x)
484 self.assertEqual(list(x), list(y))
485 self.assertEqual(x.foo, y.foo)
486 self.assert_(x[0] is y[0])
487 self.assert_(x.foo is y.foo)
488
489 def test_deepcopy_list_subclass(self):
490 class C(list):
491 pass
492 x = C([[1, 2], 3])
493 x.foo = [4, 5]
494 y = copy.deepcopy(x)
495 self.assertEqual(list(x), list(y))
496 self.assertEqual(x.foo, y.foo)
497 self.assert_(x[0] is not y[0])
498 self.assert_(x.foo is not y.foo)
499
Guido van Rossum85233bf2003-02-06 21:25:12 +0000500 def test_copy_tuple_subclass(self):
501 class C(tuple):
502 pass
503 x = C([1, 2, 3])
504 self.assertEqual(tuple(x), (1, 2, 3))
505 y = copy.copy(x)
506 self.assertEqual(tuple(y), (1, 2, 3))
507
508 def test_deepcopy_tuple_subclass(self):
509 class C(tuple):
510 pass
511 x = C([[1, 2], 3])
512 self.assertEqual(tuple(x), ([1, 2], 3))
513 y = copy.deepcopy(x)
514 self.assertEqual(tuple(y), ([1, 2], 3))
515 self.assert_(x is not y)
516 self.assert_(x[0] is not y[0])
517
Guido van Rossum581cb932003-02-06 17:52:15 +0000518def test_main():
Walter Dörwald21d3a322003-05-01 17:45:56 +0000519 test_support.run_unittest(TestCopy)
Guido van Rossum581cb932003-02-06 17:52:15 +0000520
521if __name__ == "__main__":
522 test_main()