Thanks to visit codestin.com
Credit goes to github.com

Skip to content

Commit 6e61006

Browse files
committed
Merged revisions 72669 via svnmerge from
svn+ssh://[email protected]/python/trunk ........ r72669 | antoine.pitrou | 2009-05-15 18:54:52 +0200 (ven., 15 mai 2009) | 3 lines Issue #2116: Weak references and weak dictionaries now support copy()ing and deepcopy()ing. ........
1 parent bd3da6b commit 6e61006

4 files changed

Lines changed: 116 additions & 1 deletion

File tree

Lib/copy.py

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -49,6 +49,7 @@ class instances).
4949
"""
5050

5151
import types
52+
import weakref
5253
from copyreg import dispatch_table
5354

5455
class Error(Exception):
@@ -102,7 +103,7 @@ def _copy_immutable(x):
102103
for t in (type(None), int, float, bool, str, tuple,
103104
frozenset, type, range,
104105
types.BuiltinFunctionType, type(Ellipsis),
105-
types.FunctionType):
106+
types.FunctionType, weakref.ref):
106107
d[t] = _copy_immutable
107108
t = getattr(types, "CodeType", None)
108109
if t is not None:
@@ -198,6 +199,7 @@ def _deepcopy_atomic(x, memo):
198199
d[range] = _deepcopy_atomic
199200
d[types.BuiltinFunctionType] = _deepcopy_atomic
200201
d[types.FunctionType] = _deepcopy_atomic
202+
d[weakref.ref] = _deepcopy_atomic
201203

202204
def _deepcopy_list(x, memo):
203205
y = []

Lib/test/test_copy.py

Lines changed: 88 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,9 @@
22

33
import copy
44
import copyreg
5+
import weakref
56
from operator import le, lt, ge, gt, eq, ne
7+
68
import unittest
79
from test import support
810

@@ -590,6 +592,92 @@ def foo(x, y): return x+y
590592
bar = lambda: None
591593
self.assertEqual(copy.deepcopy(bar), bar)
592594

595+
def _check_weakref(self, _copy):
596+
class C(object):
597+
pass
598+
obj = C()
599+
x = weakref.ref(obj)
600+
y = _copy(x)
601+
self.assertTrue(y is x)
602+
del obj
603+
y = _copy(x)
604+
self.assertTrue(y is x)
605+
606+
def test_copy_weakref(self):
607+
self._check_weakref(copy.copy)
608+
609+
def test_deepcopy_weakref(self):
610+
self._check_weakref(copy.deepcopy)
611+
612+
def _check_copy_weakdict(self, _dicttype):
613+
class C(object):
614+
pass
615+
a, b, c, d = [C() for i in range(4)]
616+
u = _dicttype()
617+
u[a] = b
618+
u[c] = d
619+
v = copy.copy(u)
620+
self.assertFalse(v is u)
621+
self.assertEqual(v, u)
622+
self.assertEqual(v[a], b)
623+
self.assertEqual(v[c], d)
624+
self.assertEqual(len(v), 2)
625+
del c, d
626+
self.assertEqual(len(v), 1)
627+
x, y = C(), C()
628+
# The underlying containers are decoupled
629+
v[x] = y
630+
self.assertFalse(x in u)
631+
632+
def test_copy_weakkeydict(self):
633+
self._check_copy_weakdict(weakref.WeakKeyDictionary)
634+
635+
def test_copy_weakvaluedict(self):
636+
self._check_copy_weakdict(weakref.WeakValueDictionary)
637+
638+
def test_deepcopy_weakkeydict(self):
639+
class C(object):
640+
def __init__(self, i):
641+
self.i = i
642+
a, b, c, d = [C(i) for i in range(4)]
643+
u = weakref.WeakKeyDictionary()
644+
u[a] = b
645+
u[c] = d
646+
# Keys aren't copied, values are
647+
v = copy.deepcopy(u)
648+
self.assertNotEqual(v, u)
649+
self.assertEqual(len(v), 2)
650+
self.assertFalse(v[a] is b)
651+
self.assertFalse(v[c] is d)
652+
self.assertEqual(v[a].i, b.i)
653+
self.assertEqual(v[c].i, d.i)
654+
del c
655+
self.assertEqual(len(v), 1)
656+
657+
def test_deepcopy_weakvaluedict(self):
658+
class C(object):
659+
def __init__(self, i):
660+
self.i = i
661+
a, b, c, d = [C(i) for i in range(4)]
662+
u = weakref.WeakValueDictionary()
663+
u[a] = b
664+
u[c] = d
665+
# Keys are copied, values aren't
666+
v = copy.deepcopy(u)
667+
self.assertNotEqual(v, u)
668+
self.assertEqual(len(v), 2)
669+
(x, y), (z, t) = sorted(v.items(), key=lambda pair: pair[0].i)
670+
self.assertFalse(x is a)
671+
self.assertEqual(x.i, a.i)
672+
self.assertTrue(y is b)
673+
self.assertFalse(z is c)
674+
self.assertEqual(z.i, c.i)
675+
self.assertTrue(t is d)
676+
del x, y, z, t
677+
del d
678+
self.assertEqual(len(v), 1)
679+
680+
593681
def global_foo(x, y): return x+y
594682

595683
def test_main():

Lib/weakref.py

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -85,6 +85,17 @@ def copy(self):
8585
new[key] = o
8686
return new
8787

88+
__copy__ = copy
89+
90+
def __deepcopy__(self, memo):
91+
from copy import deepcopy
92+
new = self.__class__()
93+
for key, wr in self.data.items():
94+
o = wr()
95+
if o is not None:
96+
new[deepcopy(key, memo)] = o
97+
return new
98+
8899
def get(self, key, default=None):
89100
try:
90101
wr = self.data[key]
@@ -251,6 +262,17 @@ def copy(self):
251262
new[o] = value
252263
return new
253264

265+
__copy__ = copy
266+
267+
def __deepcopy__(self, memo):
268+
from copy import deepcopy
269+
new = self.__class__()
270+
for key, value in self.data.items():
271+
o = key()
272+
if o is not None:
273+
new[o] = deepcopy(value, memo)
274+
return new
275+
254276
def get(self, key, default=None):
255277
return self.data.get(ref(key),default)
256278

Misc/NEWS

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,9 @@ Core and Builtins
2323
Library
2424
-------
2525

26+
- Issue #2116: Weak references and weak dictionaries now support copy()ing and
27+
deepcopy()ing.
28+
2629
- Issue #1655: Make imaplib IPv6-capable. Patch by Derek Morr.
2730

2831
- Issue #5918: Fix a crash in the parser module.

0 commit comments

Comments
 (0)