Commit | Line | Data |
---|---|---|
920dae64 AT |
1 | """Unit tests for the copy module.""" |
2 | ||
3 | import sys | |
4 | import copy | |
5 | import copy_reg | |
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.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, 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.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 __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 | # tests for copying extension types, iff module trycopy is installed | |
170 | def test_copy_classictype(self): | |
171 | from _testcapi import make_copyable | |
172 | x = make_copyable([23]) | |
173 | y = copy.copy(x) | |
174 | self.assertEqual(x, y) | |
175 | self.assertEqual(x.tag, y.tag) | |
176 | self.assert_(x is not y) | |
177 | self.assert_(x.tag is y.tag) | |
178 | ||
179 | def test_deepcopy_classictype(self): | |
180 | from _testcapi import make_copyable | |
181 | x = make_copyable([23]) | |
182 | y = copy.deepcopy(x) | |
183 | self.assertEqual(x, y) | |
184 | self.assertEqual(x.tag, y.tag) | |
185 | self.assert_(x is not y) | |
186 | self.assert_(x.tag is not y.tag) | |
187 | ||
188 | # regression tests for class-vs-instance and metaclass-confusion | |
189 | def test_copy_classoverinstance(self): | |
190 | class C(object): | |
191 | def __init__(self, v): | |
192 | self.v = v | |
193 | def __cmp__(self, other): | |
194 | return -cmp(other, self.v) | |
195 | def __copy__(self): | |
196 | return self.__class__(self.v) | |
197 | x = C(23) | |
198 | self.assertEqual(copy.copy(x), x) | |
199 | x.__copy__ = lambda: 42 | |
200 | self.assertEqual(copy.copy(x), x) | |
201 | ||
202 | def test_deepcopy_classoverinstance(self): | |
203 | class C(object): | |
204 | def __init__(self, v): | |
205 | self.v = v | |
206 | def __cmp__(self, other): | |
207 | return -cmp(other, self.v) | |
208 | def __deepcopy__(self, memo): | |
209 | return self.__class__(copy.deepcopy(self.v, memo)) | |
210 | x = C(23) | |
211 | self.assertEqual(copy.deepcopy(x), x) | |
212 | x.__deepcopy__ = lambda memo: 42 | |
213 | self.assertEqual(copy.deepcopy(x), x) | |
214 | ||
215 | ||
216 | def test_copy_metaclassconfusion(self): | |
217 | class MyOwnError(copy.Error): | |
218 | pass | |
219 | class Meta(type): | |
220 | def __copy__(cls): | |
221 | raise MyOwnError("can't copy classes w/this metaclass") | |
222 | class C: | |
223 | __metaclass__ = Meta | |
224 | def __init__(self, tag): | |
225 | self.tag = tag | |
226 | def __cmp__(self, other): | |
227 | return -cmp(other, self.tag) | |
228 | # the metaclass can forbid shallow copying of its classes | |
229 | self.assertRaises(MyOwnError, copy.copy, C) | |
230 | # check that there is no interference with instances | |
231 | x = C(23) | |
232 | self.assertEqual(copy.copy(x), x) | |
233 | ||
234 | def test_deepcopy_metaclassconfusion(self): | |
235 | class MyOwnError(copy.Error): | |
236 | pass | |
237 | class Meta(type): | |
238 | def __deepcopy__(cls, memo): | |
239 | raise MyOwnError("can't deepcopy classes w/this metaclass") | |
240 | class C: | |
241 | __metaclass__ = Meta | |
242 | def __init__(self, tag): | |
243 | self.tag = tag | |
244 | def __cmp__(self, other): | |
245 | return -cmp(other, self.tag) | |
246 | # types are ALWAYS deepcopied atomically, no matter what | |
247 | self.assertEqual(copy.deepcopy(C), C) | |
248 | # check that there is no interference with instances | |
249 | x = C(23) | |
250 | self.assertEqual(copy.deepcopy(x), x) | |
251 | ||
252 | def _nomro(self): | |
253 | class C(type): | |
254 | def __getattribute__(self, attr): | |
255 | if attr == '__mro__': | |
256 | raise AttributeError, "What, *me*, a __mro__? Nevah!" | |
257 | return super(C, self).__getattribute__(attr) | |
258 | class D(object): | |
259 | __metaclass__ = C | |
260 | return D() | |
261 | ||
262 | def test_copy_mro(self): | |
263 | x = self._nomro() | |
264 | y = copy.copy(x) | |
265 | ||
266 | def test_deepcopy_mro(self): | |
267 | x = self._nomro() | |
268 | y = copy.deepcopy(x) | |
269 | ||
270 | # The deepcopy() method | |
271 | ||
272 | def test_deepcopy_basic(self): | |
273 | x = 42 | |
274 | y = copy.deepcopy(x) | |
275 | self.assertEqual(y, x) | |
276 | ||
277 | def test_deepcopy_memo(self): | |
278 | # Tests of reflexive objects are under type-specific sections below. | |
279 | # This tests only repetitions of objects. | |
280 | x = [] | |
281 | x = [x, x] | |
282 | y = copy.deepcopy(x) | |
283 | self.assertEqual(y, x) | |
284 | self.assert_(y is not x) | |
285 | self.assert_(y[0] is not x[0]) | |
286 | self.assert_(y[0] is y[1]) | |
287 | ||
288 | def test_deepcopy_issubclass(self): | |
289 | # XXX Note: there's no way to test the TypeError coming out of | |
290 | # issubclass() -- this can only happen when an extension | |
291 | # module defines a "type" that doesn't formally inherit from | |
292 | # type. | |
293 | class Meta(type): | |
294 | pass | |
295 | class C: | |
296 | __metaclass__ = Meta | |
297 | self.assertEqual(copy.deepcopy(C), C) | |
298 | ||
299 | def test_deepcopy_deepcopy(self): | |
300 | class C(object): | |
301 | def __init__(self, foo): | |
302 | self.foo = foo | |
303 | def __deepcopy__(self, memo=None): | |
304 | return C(self.foo) | |
305 | x = C(42) | |
306 | y = copy.deepcopy(x) | |
307 | self.assertEqual(y.__class__, x.__class__) | |
308 | self.assertEqual(y.foo, x.foo) | |
309 | ||
310 | def test_deepcopy_registry(self): | |
311 | class C(object): | |
312 | def __new__(cls, foo): | |
313 | obj = object.__new__(cls) | |
314 | obj.foo = foo | |
315 | return obj | |
316 | def pickle_C(obj): | |
317 | return (C, (obj.foo,)) | |
318 | x = C(42) | |
319 | self.assertRaises(TypeError, copy.deepcopy, x) | |
320 | copy_reg.pickle(C, pickle_C, C) | |
321 | y = copy.deepcopy(x) | |
322 | ||
323 | def test_deepcopy_reduce_ex(self): | |
324 | class C(object): | |
325 | def __reduce_ex__(self, proto): | |
326 | return "" | |
327 | def __reduce__(self): | |
328 | raise test_support.TestFailed, "shouldn't call this" | |
329 | x = C() | |
330 | y = copy.deepcopy(x) | |
331 | self.assert_(y is x) | |
332 | ||
333 | def test_deepcopy_reduce(self): | |
334 | class C(object): | |
335 | def __reduce__(self): | |
336 | return "" | |
337 | x = C() | |
338 | y = copy.deepcopy(x) | |
339 | self.assert_(y is x) | |
340 | ||
341 | def test_deepcopy_cant(self): | |
342 | class C(object): | |
343 | def __getattribute__(self, name): | |
344 | if name.startswith("__reduce"): | |
345 | raise AttributeError, name | |
346 | return object.__getattribute__(self, name) | |
347 | x = C() | |
348 | self.assertRaises(copy.Error, copy.deepcopy, x) | |
349 | ||
350 | # Type-specific _deepcopy_xxx() methods | |
351 | ||
352 | def test_deepcopy_atomic(self): | |
353 | class Classic: | |
354 | pass | |
355 | class NewStyle(object): | |
356 | pass | |
357 | def f(): | |
358 | pass | |
359 | tests = [None, 42, 2L**100, 3.14, True, False, 1j, | |
360 | "hello", u"hello\u1234", f.func_code, | |
361 | NewStyle, xrange(10), Classic, max] | |
362 | for x in tests: | |
363 | self.assert_(copy.deepcopy(x) is x, repr(x)) | |
364 | ||
365 | def test_deepcopy_list(self): | |
366 | x = [[1, 2], 3] | |
367 | y = copy.deepcopy(x) | |
368 | self.assertEqual(y, x) | |
369 | self.assert_(x is not y) | |
370 | self.assert_(x[0] is not y[0]) | |
371 | ||
372 | def test_deepcopy_reflexive_list(self): | |
373 | x = [] | |
374 | x.append(x) | |
375 | y = copy.deepcopy(x) | |
376 | self.assertRaises(RuntimeError, cmp, y, x) | |
377 | self.assert_(y is not x) | |
378 | self.assert_(y[0] is y) | |
379 | self.assertEqual(len(y), 1) | |
380 | ||
381 | def test_deepcopy_tuple(self): | |
382 | x = ([1, 2], 3) | |
383 | y = copy.deepcopy(x) | |
384 | self.assertEqual(y, x) | |
385 | self.assert_(x is not y) | |
386 | self.assert_(x[0] is not y[0]) | |
387 | ||
388 | def test_deepcopy_reflexive_tuple(self): | |
389 | x = ([],) | |
390 | x[0].append(x) | |
391 | y = copy.deepcopy(x) | |
392 | self.assertRaises(RuntimeError, cmp, y, x) | |
393 | self.assert_(y is not x) | |
394 | self.assert_(y[0] is not x[0]) | |
395 | self.assert_(y[0][0] is y) | |
396 | ||
397 | def test_deepcopy_dict(self): | |
398 | x = {"foo": [1, 2], "bar": 3} | |
399 | y = copy.deepcopy(x) | |
400 | self.assertEqual(y, x) | |
401 | self.assert_(x is not y) | |
402 | self.assert_(x["foo"] is not y["foo"]) | |
403 | ||
404 | def test_deepcopy_reflexive_dict(self): | |
405 | x = {} | |
406 | x['foo'] = x | |
407 | y = copy.deepcopy(x) | |
408 | self.assertRaises(RuntimeError, cmp, y, x) | |
409 | self.assert_(y is not x) | |
410 | self.assert_(y['foo'] is y) | |
411 | self.assertEqual(len(y), 1) | |
412 | ||
413 | def test_deepcopy_keepalive(self): | |
414 | memo = {} | |
415 | x = 42 | |
416 | y = copy.deepcopy(x, memo) | |
417 | self.assert_(memo[id(x)] is x) | |
418 | ||
419 | def test_deepcopy_inst_vanilla(self): | |
420 | class C: | |
421 | def __init__(self, foo): | |
422 | self.foo = foo | |
423 | def __cmp__(self, other): | |
424 | return cmp(self.foo, other.foo) | |
425 | x = C([42]) | |
426 | y = copy.deepcopy(x) | |
427 | self.assertEqual(y, x) | |
428 | self.assert_(y.foo is not x.foo) | |
429 | ||
430 | def test_deepcopy_inst_deepcopy(self): | |
431 | class C: | |
432 | def __init__(self, foo): | |
433 | self.foo = foo | |
434 | def __deepcopy__(self, memo): | |
435 | return C(copy.deepcopy(self.foo, memo)) | |
436 | def __cmp__(self, other): | |
437 | return cmp(self.foo, other.foo) | |
438 | x = C([42]) | |
439 | y = copy.deepcopy(x) | |
440 | self.assertEqual(y, x) | |
441 | self.assert_(y is not x) | |
442 | self.assert_(y.foo is not x.foo) | |
443 | ||
444 | def test_deepcopy_inst_getinitargs(self): | |
445 | class C: | |
446 | def __init__(self, foo): | |
447 | self.foo = foo | |
448 | def __getinitargs__(self): | |
449 | return (self.foo,) | |
450 | def __cmp__(self, other): | |
451 | return cmp(self.foo, other.foo) | |
452 | x = C([42]) | |
453 | y = copy.deepcopy(x) | |
454 | self.assertEqual(y, x) | |
455 | self.assert_(y is not x) | |
456 | self.assert_(y.foo is not x.foo) | |
457 | ||
458 | def test_deepcopy_inst_getstate(self): | |
459 | class C: | |
460 | def __init__(self, foo): | |
461 | self.foo = foo | |
462 | def __getstate__(self): | |
463 | return {"foo": self.foo} | |
464 | def __cmp__(self, other): | |
465 | return cmp(self.foo, other.foo) | |
466 | x = C([42]) | |
467 | y = copy.deepcopy(x) | |
468 | self.assertEqual(y, x) | |
469 | self.assert_(y is not x) | |
470 | self.assert_(y.foo is not x.foo) | |
471 | ||
472 | def test_deepcopy_inst_setstate(self): | |
473 | class C: | |
474 | def __init__(self, foo): | |
475 | self.foo = foo | |
476 | def __setstate__(self, state): | |
477 | self.foo = state["foo"] | |
478 | def __cmp__(self, other): | |
479 | return cmp(self.foo, other.foo) | |
480 | x = C([42]) | |
481 | y = copy.deepcopy(x) | |
482 | self.assertEqual(y, x) | |
483 | self.assert_(y is not x) | |
484 | self.assert_(y.foo is not x.foo) | |
485 | ||
486 | def test_deepcopy_inst_getstate_setstate(self): | |
487 | class C: | |
488 | def __init__(self, foo): | |
489 | self.foo = foo | |
490 | def __getstate__(self): | |
491 | return self.foo | |
492 | def __setstate__(self, state): | |
493 | self.foo = state | |
494 | def __cmp__(self, other): | |
495 | return cmp(self.foo, other.foo) | |
496 | x = C([42]) | |
497 | y = copy.deepcopy(x) | |
498 | self.assertEqual(y, x) | |
499 | self.assert_(y is not x) | |
500 | self.assert_(y.foo is not x.foo) | |
501 | ||
502 | def test_deepcopy_reflexive_inst(self): | |
503 | class C: | |
504 | pass | |
505 | x = C() | |
506 | x.foo = x | |
507 | y = copy.deepcopy(x) | |
508 | self.assert_(y is not x) | |
509 | self.assert_(y.foo is y) | |
510 | ||
511 | # _reconstruct() | |
512 | ||
513 | def test_reconstruct_string(self): | |
514 | class C(object): | |
515 | def __reduce__(self): | |
516 | return "" | |
517 | x = C() | |
518 | y = copy.copy(x) | |
519 | self.assert_(y is x) | |
520 | y = copy.deepcopy(x) | |
521 | self.assert_(y is x) | |
522 | ||
523 | def test_reconstruct_nostate(self): | |
524 | class C(object): | |
525 | def __reduce__(self): | |
526 | return (C, ()) | |
527 | x = C() | |
528 | x.foo = 42 | |
529 | y = copy.copy(x) | |
530 | self.assert_(y.__class__ is x.__class__) | |
531 | y = copy.deepcopy(x) | |
532 | self.assert_(y.__class__ is x.__class__) | |
533 | ||
534 | def test_reconstruct_state(self): | |
535 | class C(object): | |
536 | def __reduce__(self): | |
537 | return (C, (), self.__dict__) | |
538 | def __cmp__(self, other): | |
539 | return cmp(self.__dict__, other.__dict__) | |
540 | x = C() | |
541 | x.foo = [42] | |
542 | y = copy.copy(x) | |
543 | self.assertEqual(y, x) | |
544 | y = copy.deepcopy(x) | |
545 | self.assertEqual(y, x) | |
546 | self.assert_(y.foo is not x.foo) | |
547 | ||
548 | def test_reconstruct_state_setstate(self): | |
549 | class C(object): | |
550 | def __reduce__(self): | |
551 | return (C, (), self.__dict__) | |
552 | def __setstate__(self, state): | |
553 | self.__dict__.update(state) | |
554 | def __cmp__(self, other): | |
555 | return cmp(self.__dict__, other.__dict__) | |
556 | x = C() | |
557 | x.foo = [42] | |
558 | y = copy.copy(x) | |
559 | self.assertEqual(y, x) | |
560 | y = copy.deepcopy(x) | |
561 | self.assertEqual(y, x) | |
562 | self.assert_(y.foo is not x.foo) | |
563 | ||
564 | def test_reconstruct_reflexive(self): | |
565 | class C(object): | |
566 | pass | |
567 | x = C() | |
568 | x.foo = x | |
569 | y = copy.deepcopy(x) | |
570 | self.assert_(y is not x) | |
571 | self.assert_(y.foo is y) | |
572 | ||
573 | # Additions for Python 2.3 and pickle protocol 2 | |
574 | ||
575 | def test_reduce_4tuple(self): | |
576 | class C(list): | |
577 | def __reduce__(self): | |
578 | return (C, (), self.__dict__, iter(self)) | |
579 | def __cmp__(self, other): | |
580 | return (cmp(list(self), list(other)) or | |
581 | cmp(self.__dict__, other.__dict__)) | |
582 | x = C([[1, 2], 3]) | |
583 | y = copy.copy(x) | |
584 | self.assertEqual(x, y) | |
585 | self.assert_(x is not y) | |
586 | self.assert_(x[0] is y[0]) | |
587 | y = copy.deepcopy(x) | |
588 | self.assertEqual(x, y) | |
589 | self.assert_(x is not y) | |
590 | self.assert_(x[0] is not y[0]) | |
591 | ||
592 | def test_reduce_5tuple(self): | |
593 | class C(dict): | |
594 | def __reduce__(self): | |
595 | return (C, (), self.__dict__, None, self.iteritems()) | |
596 | def __cmp__(self, other): | |
597 | return (cmp(dict(self), list(dict)) or | |
598 | cmp(self.__dict__, other.__dict__)) | |
599 | x = C([("foo", [1, 2]), ("bar", 3)]) | |
600 | y = copy.copy(x) | |
601 | self.assertEqual(x, y) | |
602 | self.assert_(x is not y) | |
603 | self.assert_(x["foo"] is y["foo"]) | |
604 | y = copy.deepcopy(x) | |
605 | self.assertEqual(x, y) | |
606 | self.assert_(x is not y) | |
607 | self.assert_(x["foo"] is not y["foo"]) | |
608 | ||
609 | def test_copy_slots(self): | |
610 | class C(object): | |
611 | __slots__ = ["foo"] | |
612 | x = C() | |
613 | x.foo = [42] | |
614 | y = copy.copy(x) | |
615 | self.assert_(x.foo is y.foo) | |
616 | ||
617 | def test_deepcopy_slots(self): | |
618 | class C(object): | |
619 | __slots__ = ["foo"] | |
620 | x = C() | |
621 | x.foo = [42] | |
622 | y = copy.deepcopy(x) | |
623 | self.assertEqual(x.foo, y.foo) | |
624 | self.assert_(x.foo is not y.foo) | |
625 | ||
626 | def test_copy_list_subclass(self): | |
627 | class C(list): | |
628 | pass | |
629 | x = C([[1, 2], 3]) | |
630 | x.foo = [4, 5] | |
631 | y = copy.copy(x) | |
632 | self.assertEqual(list(x), list(y)) | |
633 | self.assertEqual(x.foo, y.foo) | |
634 | self.assert_(x[0] is y[0]) | |
635 | self.assert_(x.foo is y.foo) | |
636 | ||
637 | def test_deepcopy_list_subclass(self): | |
638 | class C(list): | |
639 | pass | |
640 | x = C([[1, 2], 3]) | |
641 | x.foo = [4, 5] | |
642 | y = copy.deepcopy(x) | |
643 | self.assertEqual(list(x), list(y)) | |
644 | self.assertEqual(x.foo, y.foo) | |
645 | self.assert_(x[0] is not y[0]) | |
646 | self.assert_(x.foo is not y.foo) | |
647 | ||
648 | def test_copy_tuple_subclass(self): | |
649 | class C(tuple): | |
650 | pass | |
651 | x = C([1, 2, 3]) | |
652 | self.assertEqual(tuple(x), (1, 2, 3)) | |
653 | y = copy.copy(x) | |
654 | self.assertEqual(tuple(y), (1, 2, 3)) | |
655 | ||
656 | def test_deepcopy_tuple_subclass(self): | |
657 | class C(tuple): | |
658 | pass | |
659 | x = C([[1, 2], 3]) | |
660 | self.assertEqual(tuple(x), ([1, 2], 3)) | |
661 | y = copy.deepcopy(x) | |
662 | self.assertEqual(tuple(y), ([1, 2], 3)) | |
663 | self.assert_(x is not y) | |
664 | self.assert_(x[0] is not y[0]) | |
665 | ||
666 | def test_getstate_exc(self): | |
667 | class EvilState(object): | |
668 | def __getstate__(self): | |
669 | raise ValueError, "ain't got no stickin' state" | |
670 | self.assertRaises(ValueError, copy.copy, EvilState()) | |
671 | ||
672 | def test_main(): | |
673 | test_support.run_unittest(TestCopy) | |
674 | ||
675 | if __name__ == "__main__": | |
676 | test_main() |