[Checkins] SVN: Acquisition/trunk/ Give both wrapper classes a ``__getnewargs__`` method, which causes the ZODB optimization to fail and create persistent references using the ``_p_oid`` alone. This happens to be the persistent oid of the wrapped object. This lets these objects to be persisted correctly, even though they are passed to the ZODB in a wrapped state.
Hanno Schlichting
hannosch at hannosch.eu
Sat Apr 3 19:07:40 EDT 2010
Log message for revision 110475:
Give both wrapper classes a ``__getnewargs__`` method, which causes the ZODB optimization to fail and create persistent references using the ``_p_oid`` alone. This happens to be the persistent oid of the wrapped object. This lets these objects to be persisted correctly, even though they are passed to the ZODB in a wrapped state.
Changed:
U Acquisition/trunk/CHANGES.txt
U Acquisition/trunk/src/Acquisition/_Acquisition.c
U Acquisition/trunk/src/Acquisition/tests.py
-=-
Modified: Acquisition/trunk/CHANGES.txt
===================================================================
--- Acquisition/trunk/CHANGES.txt 2010-04-03 23:04:03 UTC (rev 110474)
+++ Acquisition/trunk/CHANGES.txt 2010-04-03 23:07:40 UTC (rev 110475)
@@ -4,6 +4,12 @@
2.13.2 (unreleased)
-------------------
+- Give both wrapper classes a ``__getnewargs__`` method, which causes the ZODB
+ optimization to fail and create persistent references using the ``_p_oid``
+ alone. This happens to be the persistent oid of the wrapped object. This lets
+ these objects to be persisted correctly, even though they are passed to the
+ ZODB in a wrapped state.
+
- Added failing tests for http://dev.plone.org/plone/ticket/10318. This shows
an edge-case where AQ wrappers can be pickled using the specific combination
of cPickle, pickle protocol one and a custom Pickler class with an
Modified: Acquisition/trunk/src/Acquisition/_Acquisition.c
===================================================================
--- Acquisition/trunk/src/Acquisition/_Acquisition.c 2010-04-03 23:04:03 UTC (rev 110474)
+++ Acquisition/trunk/src/Acquisition/_Acquisition.c 2010-04-03 23:07:40 UTC (rev 110475)
@@ -1290,6 +1290,12 @@
return NULL;
}
+static PyObject *
+Wrapper___getnewargs__(PyObject *self)
+{
+ return PyTuple_New(0);
+}
+
static struct PyMethodDef Wrapper_methods[] = {
{"acquire", (PyCFunction)Wrapper_acquire_method,
METH_VARARGS|METH_KEYWORDS,
@@ -1299,6 +1305,8 @@
"Get an attribute, acquiring it if necessary"},
{"aq_inContextOf", (PyCFunction)Wrapper_inContextOf, METH_VARARGS,
"Test whether the object is currently in the context of the argument"},
+ {"__getnewargs__", (PyCFunction)Wrapper___getnewargs__, METH_NOARGS,
+ "Get arguments to be passed to __new__"},
{"__getstate__", (PyCFunction)Wrappers_are_not_picklable, METH_VARARGS,
"Wrappers are not picklable"},
{"__reduce__", (PyCFunction)Wrappers_are_not_picklable, METH_VARARGS,
Modified: Acquisition/trunk/src/Acquisition/tests.py
===================================================================
--- Acquisition/trunk/src/Acquisition/tests.py 2010-04-03 23:04:03 UTC (rev 110474)
+++ Acquisition/trunk/src/Acquisition/tests.py 2010-04-03 23:07:40 UTC (rev 110475)
@@ -1570,6 +1570,7 @@
>>> import cPickle
>>> class X:
+ ... _p_oid = '1234'
... def __getstate__(self):
... return 1
@@ -1608,15 +1609,18 @@
>>> def persistent_id(obj):
... klass = type(obj)
+ ... oid = obj._p_oid
... if hasattr(klass, '__getnewargs__'):
- ... return id(obj)
- ... return id(obj), klass
+ ... return oid
+ ... return 'class_and_oid', klass
>>> pickler.inst_persistent_id = persistent_id
- >>> pickler.dump(w)
- Traceback (most recent call last):
- ...
- TypeError: Can't pickle objects in acquisition wrappers.
+ >>> _ = pickler.dump(w)
+ >>> state = file.getvalue()
+ >>> '1234' in state
+ True
+ >>> 'class_and_oid' in state
+ False
"""
@@ -1625,6 +1629,7 @@
>>> import cPickle
>>> class X(object):
+ ... _p_oid = '1234'
... def __getstate__(self):
... return 1
@@ -1663,15 +1668,18 @@
>>> def persistent_id(obj):
... klass = type(obj)
+ ... oid = obj._p_oid
... if hasattr(klass, '__getnewargs__'):
- ... return id(obj)
- ... return id(obj), klass
+ ... return oid
+ ... return 'class_and_oid', klass
>>> pickler.inst_persistent_id = persistent_id
- >>> pickler.dump(w)
- Traceback (most recent call last):
- ...
- TypeError: Can't pickle objects in acquisition wrappers.
+ >>> _ = pickler.dump(w)
+ >>> state = file.getvalue()
+ >>> '1234' in state
+ True
+ >>> 'class_and_oid' in state
+ False
"""
More information about the checkins
mailing list