1"""Unit tests for the copy module."""
2
3import copy
4import copyreg
5import weakref
6import abc
7from operator import le, lt, ge, gt, eq, ne
8
9import unittest
10
11order_comparisons = le, lt, ge, gt
12equality_comparisons = eq, ne
13comparisons = order_comparisons + equality_comparisons
14
15class TestCopy(unittest.TestCase):
16
17    # Attempt full line coverage of copy.py from top to bottom
18
19    def test_exceptions(self):
20        self.assertIs(copy.Error, copy.error)
21        self.assertTrue(issubclass(copy.Error, Exception))
22
23    # The copy() method
24
25    def test_copy_basic(self):
26        x = 42
27        y = copy.copy(x)
28        self.assertEqual(x, y)
29
30    def test_copy_copy(self):
31        class C(object):
32            def __init__(self, foo):
33                self.foo = foo
34            def __copy__(self):
35                return C(self.foo)
36        x = C(42)
37        y = copy.copy(x)
38        self.assertEqual(y.__class__, x.__class__)
39        self.assertEqual(y.foo, x.foo)
40
41    def test_copy_registry(self):
42        class C(object):
43            def __new__(cls, foo):
44                obj = object.__new__(cls)
45                obj.foo = foo
46                return obj
47        def pickle_C(obj):
48            return (C, (obj.foo,))
49        x = C(42)
50        self.assertRaises(TypeError, copy.copy, x)
51        copyreg.pickle(C, pickle_C, C)
52        y = copy.copy(x)
53
54    def test_copy_reduce_ex(self):
55        class C(object):
56            def __reduce_ex__(self, proto):
57                c.append(1)
58                return ""
59            def __reduce__(self):
60                self.fail("shouldn't call this")
61        c = []
62        x = C()
63        y = copy.copy(x)
64        self.assertIs(y, x)
65        self.assertEqual(c, [1])
66
67    def test_copy_reduce(self):
68        class C(object):
69            def __reduce__(self):
70                c.append(1)
71                return ""
72        c = []
73        x = C()
74        y = copy.copy(x)
75        self.assertIs(y, x)
76        self.assertEqual(c, [1])
77
78    def test_copy_cant(self):
79        class C(object):
80            def __getattribute__(self, name):
81                if name.startswith("__reduce"):
82                    raise AttributeError(name)
83                return object.__getattribute__(self, name)
84        x = C()
85        self.assertRaises(copy.Error, copy.copy, x)
86
87    # Type-specific _copy_xxx() methods
88
89    def test_copy_atomic(self):
90        class Classic:
91            pass
92        class NewStyle(object):
93            pass
94        def f():
95            pass
96        class WithMetaclass(metaclass=abc.ABCMeta):
97            pass
98        tests = [None, ..., NotImplemented,
99                 42, 2**100, 3.14, True, False, 1j,
100                 "hello", "hello\u1234", f.__code__,
101                 b"world", bytes(range(256)), range(10), slice(1, 10, 2),
102                 NewStyle, Classic, max, WithMetaclass, property()]
103        for x in tests:
104            self.assertIs(copy.copy(x), x)
105
106    def test_copy_list(self):
107        x = [1, 2, 3]
108        y = copy.copy(x)
109        self.assertEqual(y, x)
110        self.assertIsNot(y, x)
111        x = []
112        y = copy.copy(x)
113        self.assertEqual(y, x)
114        self.assertIsNot(y, x)
115
116    def test_copy_tuple(self):
117        x = (1, 2, 3)
118        self.assertIs(copy.copy(x), x)
119        x = ()
120        self.assertIs(copy.copy(x), x)
121        x = (1, 2, 3, [])
122        self.assertIs(copy.copy(x), x)
123
124    def test_copy_dict(self):
125        x = {"foo": 1, "bar": 2}
126        y = copy.copy(x)
127        self.assertEqual(y, x)
128        self.assertIsNot(y, x)
129        x = {}
130        y = copy.copy(x)
131        self.assertEqual(y, x)
132        self.assertIsNot(y, x)
133
134    def test_copy_set(self):
135        x = {1, 2, 3}
136        y = copy.copy(x)
137        self.assertEqual(y, x)
138        self.assertIsNot(y, x)
139        x = set()
140        y = copy.copy(x)
141        self.assertEqual(y, x)
142        self.assertIsNot(y, x)
143
144    def test_copy_frozenset(self):
145        x = frozenset({1, 2, 3})
146        self.assertIs(copy.copy(x), x)
147        x = frozenset()
148        self.assertIs(copy.copy(x), x)
149
150    def test_copy_bytearray(self):
151        x = bytearray(b'abc')
152        y = copy.copy(x)
153        self.assertEqual(y, x)
154        self.assertIsNot(y, x)
155        x = bytearray()
156        y = copy.copy(x)
157        self.assertEqual(y, x)
158        self.assertIsNot(y, x)
159
160    def test_copy_inst_vanilla(self):
161        class C:
162            def __init__(self, foo):
163                self.foo = foo
164            def __eq__(self, other):
165                return self.foo == other.foo
166        x = C(42)
167        self.assertEqual(copy.copy(x), x)
168
169    def test_copy_inst_copy(self):
170        class C:
171            def __init__(self, foo):
172                self.foo = foo
173            def __copy__(self):
174                return C(self.foo)
175            def __eq__(self, other):
176                return self.foo == other.foo
177        x = C(42)
178        self.assertEqual(copy.copy(x), x)
179
180    def test_copy_inst_getinitargs(self):
181        class C:
182            def __init__(self, foo):
183                self.foo = foo
184            def __getinitargs__(self):
185                return (self.foo,)
186            def __eq__(self, other):
187                return self.foo == other.foo
188        x = C(42)
189        self.assertEqual(copy.copy(x), x)
190
191    def test_copy_inst_getnewargs(self):
192        class C(int):
193            def __new__(cls, foo):
194                self = int.__new__(cls)
195                self.foo = foo
196                return self
197            def __getnewargs__(self):
198                return self.foo,
199            def __eq__(self, other):
200                return self.foo == other.foo
201        x = C(42)
202        y = copy.copy(x)
203        self.assertIsInstance(y, C)
204        self.assertEqual(y, x)
205        self.assertIsNot(y, x)
206        self.assertEqual(y.foo, x.foo)
207
208    def test_copy_inst_getnewargs_ex(self):
209        class C(int):
210            def __new__(cls, *, foo):
211                self = int.__new__(cls)
212                self.foo = foo
213                return self
214            def __getnewargs_ex__(self):
215                return (), {'foo': self.foo}
216            def __eq__(self, other):
217                return self.foo == other.foo
218        x = C(foo=42)
219        y = copy.copy(x)
220        self.assertIsInstance(y, C)
221        self.assertEqual(y, x)
222        self.assertIsNot(y, x)
223        self.assertEqual(y.foo, x.foo)
224
225    def test_copy_inst_getstate(self):
226        class C:
227            def __init__(self, foo):
228                self.foo = foo
229            def __getstate__(self):
230                return {"foo": self.foo}
231            def __eq__(self, other):
232                return self.foo == other.foo
233        x = C(42)
234        self.assertEqual(copy.copy(x), x)
235
236    def test_copy_inst_setstate(self):
237        class C:
238            def __init__(self, foo):
239                self.foo = foo
240            def __setstate__(self, state):
241                self.foo = state["foo"]
242            def __eq__(self, other):
243                return self.foo == other.foo
244        x = C(42)
245        self.assertEqual(copy.copy(x), x)
246
247    def test_copy_inst_getstate_setstate(self):
248        class C:
249            def __init__(self, foo):
250                self.foo = foo
251            def __getstate__(self):
252                return self.foo
253            def __setstate__(self, state):
254                self.foo = state
255            def __eq__(self, other):
256                return self.foo == other.foo
257        x = C(42)
258        self.assertEqual(copy.copy(x), x)
259        # State with boolean value is false (issue #25718)
260        x = C(0.0)
261        self.assertEqual(copy.copy(x), x)
262
263    # The deepcopy() method
264
265    def test_deepcopy_basic(self):
266        x = 42
267        y = copy.deepcopy(x)
268        self.assertEqual(y, x)
269
270    def test_deepcopy_memo(self):
271        # Tests of reflexive objects are under type-specific sections below.
272        # This tests only repetitions of objects.
273        x = []
274        x = [x, x]
275        y = copy.deepcopy(x)
276        self.assertEqual(y, x)
277        self.assertIsNot(y, x)
278        self.assertIsNot(y[0], x[0])
279        self.assertIs(y[0], y[1])
280
281    def test_deepcopy_issubclass(self):
282        # XXX Note: there's no way to test the TypeError coming out of
283        # issubclass() -- this can only happen when an extension
284        # module defines a "type" that doesn't formally inherit from
285        # type.
286        class Meta(type):
287            pass
288        class C(metaclass=Meta):
289            pass
290        self.assertEqual(copy.deepcopy(C), C)
291
292    def test_deepcopy_deepcopy(self):
293        class C(object):
294            def __init__(self, foo):
295                self.foo = foo
296            def __deepcopy__(self, memo=None):
297                return C(self.foo)
298        x = C(42)
299        y = copy.deepcopy(x)
300        self.assertEqual(y.__class__, x.__class__)
301        self.assertEqual(y.foo, x.foo)
302
303    def test_deepcopy_registry(self):
304        class C(object):
305            def __new__(cls, foo):
306                obj = object.__new__(cls)
307                obj.foo = foo
308                return obj
309        def pickle_C(obj):
310            return (C, (obj.foo,))
311        x = C(42)
312        self.assertRaises(TypeError, copy.deepcopy, x)
313        copyreg.pickle(C, pickle_C, C)
314        y = copy.deepcopy(x)
315
316    def test_deepcopy_reduce_ex(self):
317        class C(object):
318            def __reduce_ex__(self, proto):
319                c.append(1)
320                return ""
321            def __reduce__(self):
322                self.fail("shouldn't call this")
323        c = []
324        x = C()
325        y = copy.deepcopy(x)
326        self.assertIs(y, x)
327        self.assertEqual(c, [1])
328
329    def test_deepcopy_reduce(self):
330        class C(object):
331            def __reduce__(self):
332                c.append(1)
333                return ""
334        c = []
335        x = C()
336        y = copy.deepcopy(x)
337        self.assertIs(y, x)
338        self.assertEqual(c, [1])
339
340    def test_deepcopy_cant(self):
341        class C(object):
342            def __getattribute__(self, name):
343                if name.startswith("__reduce"):
344                    raise AttributeError(name)
345                return object.__getattribute__(self, name)
346        x = C()
347        self.assertRaises(copy.Error, copy.deepcopy, x)
348
349    # Type-specific _deepcopy_xxx() methods
350
351    def test_deepcopy_atomic(self):
352        class Classic:
353            pass
354        class NewStyle(object):
355            pass
356        def f():
357            pass
358        tests = [None, 42, 2**100, 3.14, True, False, 1j,
359                 "hello", "hello\u1234", f.__code__,
360                 NewStyle, Classic, max, property()]
361        for x in tests:
362            self.assertIs(copy.deepcopy(x), x)
363
364    def test_deepcopy_list(self):
365        x = [[1, 2], 3]
366        y = copy.deepcopy(x)
367        self.assertEqual(y, x)
368        self.assertIsNot(x, y)
369        self.assertIsNot(x[0], y[0])
370
371    def test_deepcopy_reflexive_list(self):
372        x = []
373        x.append(x)
374        y = copy.deepcopy(x)
375        for op in comparisons:
376            self.assertRaises(RecursionError, op, y, x)
377        self.assertIsNot(y, x)
378        self.assertIs(y[0], y)
379        self.assertEqual(len(y), 1)
380
381    def test_deepcopy_empty_tuple(self):
382        x = ()
383        y = copy.deepcopy(x)
384        self.assertIs(x, y)
385
386    def test_deepcopy_tuple(self):
387        x = ([1, 2], 3)
388        y = copy.deepcopy(x)
389        self.assertEqual(y, x)
390        self.assertIsNot(x, y)
391        self.assertIsNot(x[0], y[0])
392
393    def test_deepcopy_tuple_of_immutables(self):
394        x = ((1, 2), 3)
395        y = copy.deepcopy(x)
396        self.assertIs(x, y)
397
398    def test_deepcopy_reflexive_tuple(self):
399        x = ([],)
400        x[0].append(x)
401        y = copy.deepcopy(x)
402        for op in comparisons:
403            self.assertRaises(RecursionError, op, y, x)
404        self.assertIsNot(y, x)
405        self.assertIsNot(y[0], x[0])
406        self.assertIs(y[0][0], y)
407
408    def test_deepcopy_dict(self):
409        x = {"foo": [1, 2], "bar": 3}
410        y = copy.deepcopy(x)
411        self.assertEqual(y, x)
412        self.assertIsNot(x, y)
413        self.assertIsNot(x["foo"], y["foo"])
414
415    def test_deepcopy_reflexive_dict(self):
416        x = {}
417        x['foo'] = x
418        y = copy.deepcopy(x)
419        for op in order_comparisons:
420            self.assertRaises(TypeError, op, y, x)
421        for op in equality_comparisons:
422            self.assertRaises(RecursionError, op, y, x)
423        self.assertIsNot(y, x)
424        self.assertIs(y['foo'], y)
425        self.assertEqual(len(y), 1)
426
427    def test_deepcopy_keepalive(self):
428        memo = {}
429        x = []
430        y = copy.deepcopy(x, memo)
431        self.assertIs(memo[id(memo)][0], x)
432
433    def test_deepcopy_dont_memo_immutable(self):
434        memo = {}
435        x = [1, 2, 3, 4]
436        y = copy.deepcopy(x, memo)
437        self.assertEqual(y, x)
438        # There's the entry for the new list, and the keep alive.
439        self.assertEqual(len(memo), 2)
440
441        memo = {}
442        x = [(1, 2)]
443        y = copy.deepcopy(x, memo)
444        self.assertEqual(y, x)
445        # Tuples with immutable contents are immutable for deepcopy.
446        self.assertEqual(len(memo), 2)
447
448    def test_deepcopy_inst_vanilla(self):
449        class C:
450            def __init__(self, foo):
451                self.foo = foo
452            def __eq__(self, other):
453                return self.foo == other.foo
454        x = C([42])
455        y = copy.deepcopy(x)
456        self.assertEqual(y, x)
457        self.assertIsNot(y.foo, x.foo)
458
459    def test_deepcopy_inst_deepcopy(self):
460        class C:
461            def __init__(self, foo):
462                self.foo = foo
463            def __deepcopy__(self, memo):
464                return C(copy.deepcopy(self.foo, memo))
465            def __eq__(self, other):
466                return self.foo == other.foo
467        x = C([42])
468        y = copy.deepcopy(x)
469        self.assertEqual(y, x)
470        self.assertIsNot(y, x)
471        self.assertIsNot(y.foo, x.foo)
472
473    def test_deepcopy_inst_getinitargs(self):
474        class C:
475            def __init__(self, foo):
476                self.foo = foo
477            def __getinitargs__(self):
478                return (self.foo,)
479            def __eq__(self, other):
480                return self.foo == other.foo
481        x = C([42])
482        y = copy.deepcopy(x)
483        self.assertEqual(y, x)
484        self.assertIsNot(y, x)
485        self.assertIsNot(y.foo, x.foo)
486
487    def test_deepcopy_inst_getnewargs(self):
488        class C(int):
489            def __new__(cls, foo):
490                self = int.__new__(cls)
491                self.foo = foo
492                return self
493            def __getnewargs__(self):
494                return self.foo,
495            def __eq__(self, other):
496                return self.foo == other.foo
497        x = C([42])
498        y = copy.deepcopy(x)
499        self.assertIsInstance(y, C)
500        self.assertEqual(y, x)
501        self.assertIsNot(y, x)
502        self.assertEqual(y.foo, x.foo)
503        self.assertIsNot(y.foo, x.foo)
504
505    def test_deepcopy_inst_getnewargs_ex(self):
506        class C(int):
507            def __new__(cls, *, foo):
508                self = int.__new__(cls)
509                self.foo = foo
510                return self
511            def __getnewargs_ex__(self):
512                return (), {'foo': self.foo}
513            def __eq__(self, other):
514                return self.foo == other.foo
515        x = C(foo=[42])
516        y = copy.deepcopy(x)
517        self.assertIsInstance(y, C)
518        self.assertEqual(y, x)
519        self.assertIsNot(y, x)
520        self.assertEqual(y.foo, x.foo)
521        self.assertIsNot(y.foo, x.foo)
522
523    def test_deepcopy_inst_getstate(self):
524        class C:
525            def __init__(self, foo):
526                self.foo = foo
527            def __getstate__(self):
528                return {"foo": self.foo}
529            def __eq__(self, other):
530                return self.foo == other.foo
531        x = C([42])
532        y = copy.deepcopy(x)
533        self.assertEqual(y, x)
534        self.assertIsNot(y, x)
535        self.assertIsNot(y.foo, x.foo)
536
537    def test_deepcopy_inst_setstate(self):
538        class C:
539            def __init__(self, foo):
540                self.foo = foo
541            def __setstate__(self, state):
542                self.foo = state["foo"]
543            def __eq__(self, other):
544                return self.foo == other.foo
545        x = C([42])
546        y = copy.deepcopy(x)
547        self.assertEqual(y, x)
548        self.assertIsNot(y, x)
549        self.assertIsNot(y.foo, x.foo)
550
551    def test_deepcopy_inst_getstate_setstate(self):
552        class C:
553            def __init__(self, foo):
554                self.foo = foo
555            def __getstate__(self):
556                return self.foo
557            def __setstate__(self, state):
558                self.foo = state
559            def __eq__(self, other):
560                return self.foo == other.foo
561        x = C([42])
562        y = copy.deepcopy(x)
563        self.assertEqual(y, x)
564        self.assertIsNot(y, x)
565        self.assertIsNot(y.foo, x.foo)
566        # State with boolean value is false (issue #25718)
567        x = C([])
568        y = copy.deepcopy(x)
569        self.assertEqual(y, x)
570        self.assertIsNot(y, x)
571        self.assertIsNot(y.foo, x.foo)
572
573    def test_deepcopy_reflexive_inst(self):
574        class C:
575            pass
576        x = C()
577        x.foo = x
578        y = copy.deepcopy(x)
579        self.assertIsNot(y, x)
580        self.assertIs(y.foo, y)
581
582    def test_deepcopy_range(self):
583        class I(int):
584            pass
585        x = range(I(10))
586        y = copy.deepcopy(x)
587        self.assertIsNot(y, x)
588        self.assertEqual(y, x)
589        self.assertIsNot(y.stop, x.stop)
590        self.assertEqual(y.stop, x.stop)
591        self.assertIsInstance(y.stop, I)
592
593    # _reconstruct()
594
595    def test_reconstruct_string(self):
596        class C(object):
597            def __reduce__(self):
598                return ""
599        x = C()
600        y = copy.copy(x)
601        self.assertIs(y, x)
602        y = copy.deepcopy(x)
603        self.assertIs(y, x)
604
605    def test_reconstruct_nostate(self):
606        class C(object):
607            def __reduce__(self):
608                return (C, ())
609        x = C()
610        x.foo = 42
611        y = copy.copy(x)
612        self.assertIs(y.__class__, x.__class__)
613        y = copy.deepcopy(x)
614        self.assertIs(y.__class__, x.__class__)
615
616    def test_reconstruct_state(self):
617        class C(object):
618            def __reduce__(self):
619                return (C, (), self.__dict__)
620            def __eq__(self, other):
621                return self.__dict__ == other.__dict__
622        x = C()
623        x.foo = [42]
624        y = copy.copy(x)
625        self.assertEqual(y, x)
626        y = copy.deepcopy(x)
627        self.assertEqual(y, x)
628        self.assertIsNot(y.foo, x.foo)
629
630    def test_reconstruct_state_setstate(self):
631        class C(object):
632            def __reduce__(self):
633                return (C, (), self.__dict__)
634            def __setstate__(self, state):
635                self.__dict__.update(state)
636            def __eq__(self, other):
637                return self.__dict__ == other.__dict__
638        x = C()
639        x.foo = [42]
640        y = copy.copy(x)
641        self.assertEqual(y, x)
642        y = copy.deepcopy(x)
643        self.assertEqual(y, x)
644        self.assertIsNot(y.foo, x.foo)
645
646    def test_reconstruct_reflexive(self):
647        class C(object):
648            pass
649        x = C()
650        x.foo = x
651        y = copy.deepcopy(x)
652        self.assertIsNot(y, x)
653        self.assertIs(y.foo, y)
654
655    # Additions for Python 2.3 and pickle protocol 2
656
657    def test_reduce_4tuple(self):
658        class C(list):
659            def __reduce__(self):
660                return (C, (), self.__dict__, iter(self))
661            def __eq__(self, other):
662                return (list(self) == list(other) and
663                        self.__dict__ == other.__dict__)
664        x = C([[1, 2], 3])
665        y = copy.copy(x)
666        self.assertEqual(x, y)
667        self.assertIsNot(x, y)
668        self.assertIs(x[0], y[0])
669        y = copy.deepcopy(x)
670        self.assertEqual(x, y)
671        self.assertIsNot(x, y)
672        self.assertIsNot(x[0], y[0])
673
674    def test_reduce_5tuple(self):
675        class C(dict):
676            def __reduce__(self):
677                return (C, (), self.__dict__, None, self.items())
678            def __eq__(self, other):
679                return (dict(self) == dict(other) and
680                        self.__dict__ == other.__dict__)
681        x = C([("foo", [1, 2]), ("bar", 3)])
682        y = copy.copy(x)
683        self.assertEqual(x, y)
684        self.assertIsNot(x, y)
685        self.assertIs(x["foo"], y["foo"])
686        y = copy.deepcopy(x)
687        self.assertEqual(x, y)
688        self.assertIsNot(x, y)
689        self.assertIsNot(x["foo"], y["foo"])
690
691    def test_copy_slots(self):
692        class C(object):
693            __slots__ = ["foo"]
694        x = C()
695        x.foo = [42]
696        y = copy.copy(x)
697        self.assertIs(x.foo, y.foo)
698
699    def test_deepcopy_slots(self):
700        class C(object):
701            __slots__ = ["foo"]
702        x = C()
703        x.foo = [42]
704        y = copy.deepcopy(x)
705        self.assertEqual(x.foo, y.foo)
706        self.assertIsNot(x.foo, y.foo)
707
708    def test_deepcopy_dict_subclass(self):
709        class C(dict):
710            def __init__(self, d=None):
711                if not d:
712                    d = {}
713                self._keys = list(d.keys())
714                super().__init__(d)
715            def __setitem__(self, key, item):
716                super().__setitem__(key, item)
717                if key not in self._keys:
718                    self._keys.append(key)
719        x = C(d={'foo':0})
720        y = copy.deepcopy(x)
721        self.assertEqual(x, y)
722        self.assertEqual(x._keys, y._keys)
723        self.assertIsNot(x, y)
724        x['bar'] = 1
725        self.assertNotEqual(x, y)
726        self.assertNotEqual(x._keys, y._keys)
727
728    def test_copy_list_subclass(self):
729        class C(list):
730            pass
731        x = C([[1, 2], 3])
732        x.foo = [4, 5]
733        y = copy.copy(x)
734        self.assertEqual(list(x), list(y))
735        self.assertEqual(x.foo, y.foo)
736        self.assertIs(x[0], y[0])
737        self.assertIs(x.foo, y.foo)
738
739    def test_deepcopy_list_subclass(self):
740        class C(list):
741            pass
742        x = C([[1, 2], 3])
743        x.foo = [4, 5]
744        y = copy.deepcopy(x)
745        self.assertEqual(list(x), list(y))
746        self.assertEqual(x.foo, y.foo)
747        self.assertIsNot(x[0], y[0])
748        self.assertIsNot(x.foo, y.foo)
749
750    def test_copy_tuple_subclass(self):
751        class C(tuple):
752            pass
753        x = C([1, 2, 3])
754        self.assertEqual(tuple(x), (1, 2, 3))
755        y = copy.copy(x)
756        self.assertEqual(tuple(y), (1, 2, 3))
757
758    def test_deepcopy_tuple_subclass(self):
759        class C(tuple):
760            pass
761        x = C([[1, 2], 3])
762        self.assertEqual(tuple(x), ([1, 2], 3))
763        y = copy.deepcopy(x)
764        self.assertEqual(tuple(y), ([1, 2], 3))
765        self.assertIsNot(x, y)
766        self.assertIsNot(x[0], y[0])
767
768    def test_getstate_exc(self):
769        class EvilState(object):
770            def __getstate__(self):
771                raise ValueError("ain't got no stickin' state")
772        self.assertRaises(ValueError, copy.copy, EvilState())
773
774    def test_copy_function(self):
775        self.assertEqual(copy.copy(global_foo), global_foo)
776        def foo(x, y): return x+y
777        self.assertEqual(copy.copy(foo), foo)
778        bar = lambda: None
779        self.assertEqual(copy.copy(bar), bar)
780
781    def test_deepcopy_function(self):
782        self.assertEqual(copy.deepcopy(global_foo), global_foo)
783        def foo(x, y): return x+y
784        self.assertEqual(copy.deepcopy(foo), foo)
785        bar = lambda: None
786        self.assertEqual(copy.deepcopy(bar), bar)
787
788    def _check_weakref(self, _copy):
789        class C(object):
790            pass
791        obj = C()
792        x = weakref.ref(obj)
793        y = _copy(x)
794        self.assertIs(y, x)
795        del obj
796        y = _copy(x)
797        self.assertIs(y, x)
798
799    def test_copy_weakref(self):
800        self._check_weakref(copy.copy)
801
802    def test_deepcopy_weakref(self):
803        self._check_weakref(copy.deepcopy)
804
805    def _check_copy_weakdict(self, _dicttype):
806        class C(object):
807            pass
808        a, b, c, d = [C() for i in range(4)]
809        u = _dicttype()
810        u[a] = b
811        u[c] = d
812        v = copy.copy(u)
813        self.assertIsNot(v, u)
814        self.assertEqual(v, u)
815        self.assertEqual(v[a], b)
816        self.assertEqual(v[c], d)
817        self.assertEqual(len(v), 2)
818        del c, d
819        self.assertEqual(len(v), 1)
820        x, y = C(), C()
821        # The underlying containers are decoupled
822        v[x] = y
823        self.assertNotIn(x, u)
824
825    def test_copy_weakkeydict(self):
826        self._check_copy_weakdict(weakref.WeakKeyDictionary)
827
828    def test_copy_weakvaluedict(self):
829        self._check_copy_weakdict(weakref.WeakValueDictionary)
830
831    def test_deepcopy_weakkeydict(self):
832        class C(object):
833            def __init__(self, i):
834                self.i = i
835        a, b, c, d = [C(i) for i in range(4)]
836        u = weakref.WeakKeyDictionary()
837        u[a] = b
838        u[c] = d
839        # Keys aren't copied, values are
840        v = copy.deepcopy(u)
841        self.assertNotEqual(v, u)
842        self.assertEqual(len(v), 2)
843        self.assertIsNot(v[a], b)
844        self.assertIsNot(v[c], d)
845        self.assertEqual(v[a].i, b.i)
846        self.assertEqual(v[c].i, d.i)
847        del c
848        self.assertEqual(len(v), 1)
849
850    def test_deepcopy_weakvaluedict(self):
851        class C(object):
852            def __init__(self, i):
853                self.i = i
854        a, b, c, d = [C(i) for i in range(4)]
855        u = weakref.WeakValueDictionary()
856        u[a] = b
857        u[c] = d
858        # Keys are copied, values aren't
859        v = copy.deepcopy(u)
860        self.assertNotEqual(v, u)
861        self.assertEqual(len(v), 2)
862        (x, y), (z, t) = sorted(v.items(), key=lambda pair: pair[0].i)
863        self.assertIsNot(x, a)
864        self.assertEqual(x.i, a.i)
865        self.assertIs(y, b)
866        self.assertIsNot(z, c)
867        self.assertEqual(z.i, c.i)
868        self.assertIs(t, d)
869        del x, y, z, t
870        del d
871        self.assertEqual(len(v), 1)
872
873    def test_deepcopy_bound_method(self):
874        class Foo(object):
875            def m(self):
876                pass
877        f = Foo()
878        f.b = f.m
879        g = copy.deepcopy(f)
880        self.assertEqual(g.m, g.b)
881        self.assertIs(g.b.__self__, g)
882        g.b()
883
884
885def global_foo(x, y): return x+y
886
887if __name__ == "__main__":
888    unittest.main()
889