1 | """Unit tests for the copy module."""
|
---|
2 |
|
---|
3 | import copy
|
---|
4 | import copy_reg
|
---|
5 | import weakref
|
---|
6 |
|
---|
7 | import unittest
|
---|
8 | from test import test_support
|
---|
9 |
|
---|
10 | class 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 |
|
---|
706 | def global_foo(x, y): return x+y
|
---|
707 |
|
---|
708 | def test_main():
|
---|
709 | test_support.run_unittest(TestCopy)
|
---|
710 |
|
---|
711 | if __name__ == "__main__":
|
---|
712 | test_main()
|
---|