[pypy-svn] r22897 - in pypy/dist/pypy: objspace/flow objspace/flow/test tool tool/test
cfbolz at codespeak.net
cfbolz at codespeak.net
Tue Jan 31 15:36:31 CET 2006
Author: cfbolz
Date: Tue Jan 31 15:36:29 2006
New Revision: 22897
Added:
pypy/dist/pypy/objspace/flow/test/test_picklegraph.py
pypy/dist/pypy/tool/picklesupport.py
pypy/dist/pypy/tool/test/test_picklesupport.py
Modified:
pypy/dist/pypy/objspace/flow/model.py
Log:
add __getstate__ and __setstate__ to some of the classes in flow/model.py to make bare graphs (no lltypes attached) pickleable.
Modified: pypy/dist/pypy/objspace/flow/model.py
==============================================================================
--- pypy/dist/pypy/objspace/flow/model.py (original)
+++ pypy/dist/pypy/objspace/flow/model.py Tue Jan 31 15:36:29 2006
@@ -6,6 +6,7 @@
from __future__ import generators
from pypy.tool.uid import uid, Hashable
from pypy.tool.sourcetools import PY_IDENTIFIER, nice_repr_for_func
+from pypy.tool.picklesupport import getstate_with_slots, setstate_with_slots
"""
memory size before and after introduction of __slots__
@@ -151,6 +152,9 @@
def __repr__(self):
return "link from %s to %s" % (str(self.prevblock), str(self.target))
+ __getstate__ = getstate_with_slots
+ __setstate__ = setstate_with_slots
+
class Block(object):
__slots__ = """isstartblock inputargs operations exitswitch
@@ -222,6 +226,9 @@
exit.prevblock = self
self.exits = exits
+ __getstate__ = getstate_with_slots
+ __setstate__ = setstate_with_slots
+
class Variable(object):
__slots__ = ["_name", "_nr", "concretetype"]
Added: pypy/dist/pypy/objspace/flow/test/test_picklegraph.py
==============================================================================
--- (empty file)
+++ pypy/dist/pypy/objspace/flow/test/test_picklegraph.py Tue Jan 31 15:36:29 2006
@@ -0,0 +1,18 @@
+from pypy.objspace.flow.test import test_model
+from pypy.objspace.flow.model import checkgraph
+
+import pickle
+
+
+def test_pickle_block():
+ # does not raise
+ s = pickle.dumps(test_model.graph.startblock)
+ # does not raise
+ block = pickle.loads(s)
+
+def test_pickle_graph():
+ # does not raise
+ s = pickle.dumps(test_model.graph)
+ # does not raise
+ newgraph = pickle.loads(s)
+ checkgraph(newgraph)
Added: pypy/dist/pypy/tool/picklesupport.py
==============================================================================
--- (empty file)
+++ pypy/dist/pypy/tool/picklesupport.py Tue Jan 31 15:36:29 2006
@@ -0,0 +1,50 @@
+import weakref
+
+def getstate_with_slots(self):
+ result = []
+ for cls in self.__class__.__mro__:
+ if not hasattr(cls, '__slots__'):
+ continue
+ for attr in cls.__slots__:
+ if attr in ("__weakref__", "__dict__"):
+ continue
+ if hasattr(self, attr):
+ result.append((True, attr, getattr(self, attr)))
+ else:
+ result.append((False, attr, None))
+ if hasattr(self, "__dict__"):
+ return result, self.__dict__
+ else:
+ return result, None
+
+def setstate_with_slots(self, (state, __dict__)):
+ for i, (is_set, attr, value) in enumerate(state):
+ if is_set:
+ # circumvent eventual __setattr__
+ desc = getattr(self.__class__, attr, None)
+ if desc is None:
+ setattr(self, attr, value)
+ else:
+ desc.__set__(self, value)
+ if __dict__ is not None:
+ self.__dict__ = __dict__
+
+
+class pickleable_weakref(object):
+ __slots__ = "ref"
+
+ def __init__(self, obj):
+ self.ref = weakref.ref(obj)
+
+ def __call__(self):
+ return self.ref()
+
+ def __getstate__(self):
+ return self.ref()
+
+ def __setstate__(self, obj):
+ self.ref = weakref.ref(obj)
+
+ def __repr__(self):
+ return repr(self.ref)
+
Added: pypy/dist/pypy/tool/test/test_picklesupport.py
==============================================================================
--- (empty file)
+++ pypy/dist/pypy/tool/test/test_picklesupport.py Tue Jan 31 15:36:29 2006
@@ -0,0 +1,104 @@
+from pypy.tool.picklesupport import *
+
+import pickle
+import py
+
+class A(object):
+ __slots__ = ("a", "b")
+ __getstate__ = getstate_with_slots
+ __setstate__ = setstate_with_slots
+
+class B(A):
+ __slots__ = ("c", "d")
+
+class C(B):
+ pass
+
+def test_slot_getstate_setstate():
+ b = B()
+ b.a, b.c = range(2)
+ s = pickle.dumps(b)
+ new_b = pickle.loads(s)
+ assert new_b.a == b.a
+ py.test.raises(AttributeError, "new_b.b")
+ assert new_b.c == b.c
+ py.test.raises(AttributeError, "new_b.d")
+
+def test_slot_getstate_setstate_with_dict():
+ c = C()
+ assert '__dict__' in dir(c)
+ c.a, c.b, c.c, c.d, c.e = range(5)
+ s = pickle.dumps(c)
+ new_c = pickle.loads(s)
+ assert new_c.a == c.a
+ assert new_c.b == c.b
+ assert new_c.c == c.c
+ assert new_c.d == c.d
+ assert new_c.e == c.e
+
+class D(B):
+ __slots__ = '__weakref__'
+
+def test_slot_getstate_setstate_with_weakref():
+ d = D()
+ s = pickle.dumps(d)
+ new_d = pickle.loads(s)
+ assert new_d.__weakref__ is None
+
+def test_pickleable_weakref():
+ d = D()
+ ref = pickleable_weakref(d)
+ s = pickle.dumps((d, ref))
+ new_d, new_ref = pickle.loads(s)
+ assert new_ref() is new_d
+ del new_d
+ assert new_ref() is None
+
+def test_pickleable_weakref_dieing():
+ d = D()
+ ref = pickleable_weakref(d)
+ s = pickle.dumps(ref)
+ new_ref = pickle.loads(s)
+ assert new_ref() is None
+
+class E(B):
+ __slots__ = ()
+ def __init__(self, a, b, c, d):
+ self.__class__.a.__set__(self, a)
+ self.__class__.b.__set__(self, b)
+ self.__class__.c.__set__(self, c)
+ self.__class__.d.__set__(self, d)
+ def __getattr__(self, attr):
+ raise AttributeError("not found")
+
+def test_getsetstate_getattr():
+ e = E(1, 2, 3, 4)
+ s = pickle.dumps(e)
+ new_e = pickle.loads(s)
+ assert new_e.a == 1
+ assert new_e.b == 2
+ assert new_e.c == 3
+ assert new_e.d == 4
+
+class F(B):
+ __slots__ = "__dict__"
+ def __init__(self, a, b, c, d, e):
+ self.__class__.a.__set__(self, a)
+ self.__class__.b.__set__(self, b)
+ self.__class__.c.__set__(self, c)
+ self.__class__.d.__set__(self, d)
+ self.__dict__['e'] = e
+ def __getattr__(self, attr):
+ raise AttributeError("not found")
+
+def test_getsetstate_getattr_withdict():
+ f = F(1, 2, 3, 4, 5)
+ assert '__dict__' in dir(f)
+ s = pickle.dumps(f)
+ new_f = pickle.loads(s)
+ assert new_f.a == 1
+ assert new_f.b == 2
+ assert new_f.c == 3
+ assert new_f.d == 4
+ assert new_f.e == 5
+
More information about the Pypy-commit
mailing list