[Zodb-checkins] CVS: Zope3/lib/python/Persistence - __init__.py:1.7 cPersistence.c:1.18

Jim Fulton jim@zope.com
Mon, 7 Oct 2002 10:46:24 -0400


Update of /cvs-repository/Zope3/lib/python/Persistence
In directory cvs.zope.org:/tmp/cvs-serv15925/lib/python/Persistence

Modified Files:
	__init__.py cPersistence.c 
Log Message:
Fixed bug: Persistent objects were not picklable. 

Even though they could be stored in the ZODB, there could not be
pickled because they didn't implement a working __reduce__ method.

I added a simple function, simple_new, that gets passed a type and
simply returns the result of calling it's __new__ method.  I added a
__reduce__ method that uses this function.  Note that this will not
work for any types with __new__ methods that require any arguments
other than the type itself.



=== Zope3/lib/python/Persistence/__init__.py 1.6 => 1.7 ===
--- Zope3/lib/python/Persistence/__init__.py:1.6	Mon Aug  5 16:08:38 2002
+++ Zope3/lib/python/Persistence/__init__.py	Mon Oct  7 10:46:22 2002
@@ -15,3 +15,11 @@
 
 from cPersistence import Persistent, BasePersistent
 
+# Wire up simple constructor
+import cPersistence
+simple_new = cPersistence.simple_new
+del cPersistence.simple_new
+del cPersistence
+import copy_reg
+copy_reg.constructor(simple_new)
+del copy_reg


=== Zope3/lib/python/Persistence/cPersistence.c 1.17 => 1.18 ===
--- Zope3/lib/python/Persistence/cPersistence.c:1.17	Thu Oct  3 00:16:59 2002
+++ Zope3/lib/python/Persistence/cPersistence.c	Mon Oct  7 10:46:22 2002
@@ -56,6 +56,12 @@
 
 static PyObject *s_register = NULL;
 
+/* Python version of the simple_new function; */
+static PyObject *py_simple_new = NULL;
+
+
+
+
 PyObject *
 _PyPersist_RegisterDataManager(PyPersistBaseObject *self) 
 {
@@ -621,6 +627,52 @@
     return 0;
 }
 
+static PyObject *
+persist_reduce(PyPersistObject *self)
+{
+  PyObject *state, *args=NULL, *result, *__getstate__;
+  PyObject *__getstate__str = NULL;
+  
+  if (! __getstate__str)
+    {
+      __getstate__str = PyString_FromString("__getstate__");
+      if (! __getstate__str)
+        return NULL; 
+    }
+  
+  __getstate__ = PyObject_GetAttr((PyObject*)self, __getstate__str);
+  if (! __getstate__)
+    return NULL;
+
+  state = PyObject_CallObject(__getstate__, NULL);
+  Py_DECREF(__getstate__);
+  if (! state)
+    return NULL;
+  
+  args = PyTuple_New(1);
+  if (! args)
+    goto err;
+  
+  Py_INCREF(self->ob_type);
+  PyTuple_SET_ITEM(args, 0, (PyObject*)(self->ob_type));
+  
+  result = PyTuple_New(3);
+  if (! result)
+    goto err;
+  
+  Py_INCREF(py_simple_new);
+  PyTuple_SET_ITEM(result, 0, py_simple_new);
+  PyTuple_SET_ITEM(result, 1, args);
+  PyTuple_SET_ITEM(result, 2, state);
+  
+  return result;      
+  
+ err:
+  Py_DECREF(state);
+  Py_XDECREF(args);
+  return NULL;
+}
+
 static PyMethodDef base_persist_methods[] = {
     {"_p_activate", (PyCFunction)_PyPersist_Load, METH_NOARGS, },
     {"_p_deactivate", (PyCFunction)persist_deactivate, METH_NOARGS, },
@@ -630,6 +682,7 @@
 };
 
 static PyMethodDef persist_methods[] = {
+    {"__reduce__", (PyCFunction)persist_reduce, METH_NOARGS, },
     {"__getstate__", (PyCFunction)persist_getstate, METH_NOARGS, },
     {"__setstate__", persist_setstate, METH_O, },
     {"_p_activate", (PyCFunction)_PyPersist_Load, METH_NOARGS, },
@@ -762,8 +815,17 @@
     0, /*PyType_GenericNew,*/		/* tp_new */
 };
 
+static PyObject *
+simple_new(PyObject *self, PyObject *type_object)
+{
+  return PyType_GenericNew((PyTypeObject*)type_object, NULL, NULL);
+}
+
 static PyMethodDef PyPersist_methods[] = {
-    {NULL, NULL}
+   {"simple_new", simple_new, METH_O,
+    "Create an object by simply calling a class' __new__ method without "
+    "arguments."},
+   {NULL, NULL}
 };
 
 static PyPersist_C_API_struct c_api = {
@@ -863,4 +925,8 @@
 	return;
     if (!insenum(d, "GHOST", GHOST))
 	return;
+
+    py_simple_new = PyMapping_GetItemString(d, "simple_new");
+    if (! py_simple_new)
+        return;
 }