summaryrefslogtreecommitdiffstats
path: root/Lib
diff options
context:
space:
mode:
authorAntoine Pitrou <solipsis@pitrou.net>2009-05-15 16:54:52 (GMT)
committerAntoine Pitrou <solipsis@pitrou.net>2009-05-15 16:54:52 (GMT)
commit775fd66d7bd74cdedef536ff4f8c134ba718678f (patch)
tree4f0f3a10518bb130dd9000fda2f1f5b2e4899d5f /Lib
parent52035a04abc8b75c1481064639150e4089cd80c7 (diff)
downloadcpython-775fd66d7bd74cdedef536ff4f8c134ba718678f.zip
cpython-775fd66d7bd74cdedef536ff4f8c134ba718678f.tar.gz
cpython-775fd66d7bd74cdedef536ff4f8c134ba718678f.tar.bz2
Issue #2116: Weak references and weak dictionaries now support copy()ing and deepcopy()ing.
Diffstat (limited to 'Lib')
-rw-r--r--Lib/copy.py4
-rw-r--r--Lib/test/test_copy.py88
-rw-r--r--Lib/weakref.py22
3 files changed, 113 insertions, 1 deletions
diff --git a/Lib/copy.py b/Lib/copy.py
index 3f2033f..d3db93d 100644
--- a/Lib/copy.py
+++ b/Lib/copy.py
@@ -49,6 +49,7 @@ __getstate__() and __setstate__(). See the documentation for module
"""
import types
+import weakref
from copy_reg import dispatch_table
class Error(Exception):
@@ -102,7 +103,7 @@ def _copy_immutable(x):
for t in (type(None), int, long, float, bool, str, tuple,
frozenset, type, xrange, types.ClassType,
types.BuiltinFunctionType, type(Ellipsis),
- types.FunctionType):
+ types.FunctionType, weakref.ref):
d[t] = _copy_immutable
for name in ("ComplexType", "UnicodeType", "CodeType"):
t = getattr(types, name, None)
@@ -220,6 +221,7 @@ d[xrange] = _deepcopy_atomic
d[types.ClassType] = _deepcopy_atomic
d[types.BuiltinFunctionType] = _deepcopy_atomic
d[types.FunctionType] = _deepcopy_atomic
+d[weakref.ref] = _deepcopy_atomic
def _deepcopy_list(x, memo):
y = []
diff --git a/Lib/test/test_copy.py b/Lib/test/test_copy.py
index be334cc..a8be887 100644
--- a/Lib/test/test_copy.py
+++ b/Lib/test/test_copy.py
@@ -2,6 +2,8 @@
import copy
import copy_reg
+import weakref
+import operator
import unittest
from test import test_support
@@ -585,6 +587,92 @@ class TestCopy(unittest.TestCase):
bar = lambda: None
self.assertEqual(copy.deepcopy(bar), bar)
+ def _check_weakref(self, _copy):
+ class C(object):
+ pass
+ obj = C()
+ x = weakref.ref(obj)
+ y = _copy(x)
+ self.assertTrue(y is x)
+ del obj
+ y = _copy(x)
+ self.assertTrue(y is x)
+
+ def test_copy_weakref(self):
+ self._check_weakref(copy.copy)
+
+ def test_deepcopy_weakref(self):
+ self._check_weakref(copy.deepcopy)
+
+ def _check_copy_weakdict(self, _dicttype):
+ class C(object):
+ pass
+ a, b, c, d = [C() for i in xrange(4)]
+ u = _dicttype()
+ u[a] = b
+ u[c] = d
+ v = copy.copy(u)
+ self.assertFalse(v is u)
+ self.assertEqual(v, u)
+ self.assertEqual(v[a], b)
+ self.assertEqual(v[c], d)
+ self.assertEqual(len(v), 2)
+ del c, d
+ self.assertEqual(len(v), 1)
+ x, y = C(), C()
+ # The underlying containers are decoupled
+ v[x] = y
+ self.assertFalse(x in u)
+
+ def test_copy_weakkeydict(self):
+ self._check_copy_weakdict(weakref.WeakKeyDictionary)
+
+ def test_copy_weakvaluedict(self):
+ self._check_copy_weakdict(weakref.WeakValueDictionary)
+
+ def test_deepcopy_weakkeydict(self):
+ class C(object):
+ def __init__(self, i):
+ self.i = i
+ a, b, c, d = [C(i) for i in xrange(4)]
+ u = weakref.WeakKeyDictionary()
+ u[a] = b
+ u[c] = d
+ # Keys aren't copied, values are
+ v = copy.deepcopy(u)
+ self.assertNotEqual(v, u)
+ self.assertEqual(len(v), 2)
+ self.assertFalse(v[a] is b)
+ self.assertFalse(v[c] is d)
+ self.assertEqual(v[a].i, b.i)
+ self.assertEqual(v[c].i, d.i)
+ del c
+ self.assertEqual(len(v), 1)
+
+ def test_deepcopy_weakvaluedict(self):
+ class C(object):
+ def __init__(self, i):
+ self.i = i
+ a, b, c, d = [C(i) for i in xrange(4)]
+ u = weakref.WeakValueDictionary()
+ u[a] = b
+ u[c] = d
+ # Keys are copied, values aren't
+ v = copy.deepcopy(u)
+ self.assertNotEqual(v, u)
+ self.assertEqual(len(v), 2)
+ (x, y), (z, t) = sorted(v.items(), key=lambda (k, v): k.i)
+ self.assertFalse(x is a)
+ self.assertEqual(x.i, a.i)
+ self.assertTrue(y is b)
+ self.assertFalse(z is c)
+ self.assertEqual(z.i, c.i)
+ self.assertTrue(t is d)
+ del x, y, z, t
+ del d
+ self.assertEqual(len(v), 1)
+
+
def global_foo(x, y): return x+y
def test_main():
diff --git a/Lib/weakref.py b/Lib/weakref.py
index 78b74ad..84d81a2 100644
--- a/Lib/weakref.py
+++ b/Lib/weakref.py
@@ -85,6 +85,17 @@ class WeakValueDictionary(UserDict.UserDict):
new[key] = o
return new
+ __copy__ = copy
+
+ def __deepcopy__(self, memo):
+ from copy import deepcopy
+ new = self.__class__()
+ for key, wr in self.data.items():
+ o = wr()
+ if o is not None:
+ new[deepcopy(key, memo)] = o
+ return new
+
def get(self, key, default=None):
try:
wr = self.data[key]
@@ -256,6 +267,17 @@ class WeakKeyDictionary(UserDict.UserDict):
new[o] = value
return new
+ __copy__ = copy
+
+ def __deepcopy__(self, memo):
+ from copy import deepcopy
+ new = self.__class__()
+ for key, value in self.data.items():
+ o = key()
+ if o is not None:
+ new[o] = deepcopy(value, memo)
+ return new
+
def get(self, key, default=None):
return self.data.get(ref(key),default)