[Zope3-checkins] CVS: Zope3/lib/python/Persistence - Class.py:1.5 Module.py:1.29 __init__.py:1.9 cPersistence.c:1.21 cPersistence.h:1.6 cPersistenceAPI.h:1.6

Jim Fulton jim@zope.com
Thu, 10 Oct 2002 04:20:10 -0400


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

Modified Files:
	Class.py Module.py __init__.py cPersistence.c cPersistence.h 
	cPersistenceAPI.h 
Log Message:
Backed out a bunch of persistence changes checkin in last night that
broke things badly. Unit tests failed and zope wouldn't start under
either Python 2.2.1 or the Python CVS head. Aaaargh.


=== Zope3/lib/python/Persistence/Class.py 1.4 => 1.5 ===
--- Zope3/lib/python/Persistence/Class.py:1.4	Wed Oct  9 18:41:32 2002
+++ Zope3/lib/python/Persistence/Class.py	Thu Oct 10 04:20:06 2002
@@ -13,7 +13,7 @@
 ##############################################################################
 """Persistent Classes."""
 
-from Persistence import Persistent, PersistentMetaClass
+from Persistence import Persistent
 from Persistence.cPersistence import UPTODATE, CHANGED, STICKY, GHOST
 from Persistence.IPersistent import IPersistent
 from Persistence.Function import PersistentFunction
@@ -22,10 +22,6 @@
 from types import FunctionType as function
 import time
 
-# XXX There is a lot of magic here to give classes and instances
-# separate sets of attributes.  This code should be documented, as it
-# it quite delicate, and it should be move to a separate module.
-
 class ExtClassDescr(object):
     """Maintains seperate class and instance descriptors for an attribute.
 
@@ -148,7 +144,7 @@
             return o
     return default
 
-class PersistentClassMetaClass(PersistentMetaClass):
+class PersistentMetaClass(type):
 
     # an attempt to make persistent classes look just like other
     # persistent objects by providing class attributes and methods
@@ -162,7 +158,7 @@
     _pc_init = 0
 
     def __new__(meta, name, bases, dict):
-        cls = super(PersistentClassMetaClass, meta).__new__(meta, name, bases, dict)
+        cls = super(PersistentMetaClass, meta).__new__(meta, name, bases, dict)
         # helper functions
         def extend_attr(attr, v):
             prev = findattr(cls, attr, None)
@@ -195,7 +191,7 @@
             if cls._p_state is None:
                 cls._p_activate()
                 cls._p_atime = int(time.time() % 86400)
-        return super(PersistentClassMetaClass, cls).__getattribute__(name)
+        return super(PersistentMetaClass, cls).__getattribute__(name)
 
     def __setattr__(cls, attr, val):
         if not attr.startswith("_pc_") and cls._pc_init:
@@ -205,7 +201,7 @@
                 if set is not None:
                     set(None, val)
                     return
-        super(PersistentClassMetaClass, cls).__setattr__(attr, val)
+        super(PersistentMetaClass, cls).__setattr__(attr, val)
 
     def __delattr__(cls, attr):
         if attr.startswith('_p_'):
@@ -214,7 +210,7 @@
                 pass
             else:
                 return
-        super(PersistentClassMetaClass, cls).__delattr__(attr)
+        super(PersistentMetaClass, cls).__delattr__(attr)
     
     def __getstate__(cls):
         dict = {}
@@ -246,14 +242,14 @@
 
 class PersistentBaseClass(Persistent):
 
-    __metaclass__ = PersistentClassMetaClass
+    __metaclass__ = PersistentMetaClass
 
 def _test():
     global PC, P
 
     class PC(Persistent):
 
-        __metaclass__ = PersistentClassMetaClass
+        __metaclass__ = PersistentMetaClass
 
         def __init__(self):
             self.x = 1


=== Zope3/lib/python/Persistence/Module.py 1.28 => 1.29 ===
--- Zope3/lib/python/Persistence/Module.py:1.28	Wed Oct  9 18:41:32 2002
+++ Zope3/lib/python/Persistence/Module.py	Thu Oct 10 04:20:06 2002
@@ -22,7 +22,7 @@
 
 from Persistence import Persistent
 from Persistence.cPersistence import GHOST
-from Persistence.Class import PersistentClassMetaClass
+from Persistence.Class import PersistentMetaClass
 from Persistence.Function import PersistentFunction
 from Persistence.IPersistentModuleManager import IPersistentModuleManager
 from Persistence.IPersistentModuleRegistry \
@@ -135,7 +135,7 @@
         for k, v in new.items():
             if isinstance(v, function):
                 v = new[k] = PersistentFunction(v, module)
-            elif isinstance(v.__class__, PersistentClassMetaClass):
+            elif isinstance(v.__class__, PersistentMetaClass):
                 v.__class__.fixup(module)
             # XXX need to check for classes that are not persistent!
 


=== Zope3/lib/python/Persistence/__init__.py 1.8 => 1.9 ===
--- Zope3/lib/python/Persistence/__init__.py:1.8	Wed Oct  9 18:41:32 2002
+++ Zope3/lib/python/Persistence/__init__.py	Thu Oct 10 04:20:06 2002
@@ -11,15 +11,15 @@
 # FOR A PARTICULAR PURPOSE.
 # 
 ##############################################################################
-"""Provide access to Persistent C extension types."""
+"""Provide access to Persistent and BasePersistent C extension types."""
 
-from cPersistence import Persistent, PersistentMetaClass
+from cPersistence import Persistent, BasePersistent
 
 # Wire up simple constructor
 import cPersistence
-##simple_new = cPersistence.simple_new
-##del cPersistence.simple_new
-##del cPersistence
+simple_new = cPersistence.simple_new
+del cPersistence.simple_new
+del cPersistence
 import copy_reg
-copy_reg.constructor(cPersistence.simple_new)
-##del copy_reg
+copy_reg.constructor(simple_new)
+del copy_reg


=== Zope3/lib/python/Persistence/cPersistence.c 1.20 => 1.21 ===
--- Zope3/lib/python/Persistence/cPersistence.c:1.20	Wed Oct  9 18:41:32 2002
+++ Zope3/lib/python/Persistence/cPersistence.c	Thu Oct 10 04:20:06 2002
@@ -20,8 +20,35 @@
 "\n"
 "$Id$\n";
 
-/* Python version of the simple_new function; */
-static PyObject *py_simple_new = NULL;
+/* cPersistence defines two Python types and a C API for them.
+
+   This table summarizes the stuff connected to each type.
+
+   PyTypeObject	   PyPersistBase_Type    	PyPersist_Type
+   supports        persistent objects in C 	persistent objects in Python
+   PyObject *      PyPersistBaseObject *        PyPersistObject *
+   C struct        PyPersist_HEAD		PyPersist_INSTANCE_HEAD
+   C API macro     PyPersist_BASE_TYPE          PyPersist_INSTANCE_TYPE       
+   Python object   Persistence.BasePersistent   Persistence.Persistent
+
+   The two types share many of the same tp_xxx implementations.  The
+   key difference between the base type and the instance type is that
+   the latter has room for an __dict__.  The Persistence.Persistent
+   object is used as a base class for peristent object classes written
+   in Python.
+
+   The functions that can operate on either type take a
+   PyPersistBaseObject * argument.  If the function needs to access
+   the po_dict slot, it must first check obj->ob_type->tp_dictoffset.
+   For a PyPersistBase_Type object, the dictoffset is 0.
+
+   The getstate and setstate implementations only work with
+   PyPersist_Type objects, because they depend on having an __dict__.
+
+   The base type exists to support C types that are also persistent.
+   The only examples of such types are in Persistence.BTrees.
+
+*/
 
 /* A helper function that registers a persistent object with its data
    manager.
@@ -29,8 +56,14 @@
 
 static PyObject *s_register = NULL;
 
+/* Python version of the simple_new function; */
+static PyObject *py_simple_new = NULL;
+
+
+
+
 PyObject *
-_PyPersist_RegisterDataManager(PyPersistObject *self) 
+_PyPersist_RegisterDataManager(PyPersistBaseObject *self) 
 {
     PyObject *meth, *arg, *result;
 
@@ -62,7 +95,7 @@
 */
 
 PyObject *
-_PyPersist_Load(PyPersistObject *self) 
+_PyPersist_Load(PyPersistBaseObject *self) 
 {
     static PyObject *s_setstate = NULL;
     PyObject *meth, *arg, *result;
@@ -98,7 +131,7 @@
  */
 
 void
-_PyPersist_SetATime(PyPersistObject *self)
+_PyPersist_SetATime(PyPersistBaseObject *self)
 {
     time_t t = time(NULL);
     self->po_atime = t % 86400;
@@ -190,7 +223,7 @@
 persist_activate(PyPersistObject *self)
 {
     if (self->po_state == GHOST && self->po_dm)
-	return _PyPersist_Load((PyPersistObject *)self);
+	return _PyPersist_Load((PyPersistBaseObject *)self);
     Py_INCREF(Py_None);
     return Py_None;
 }
@@ -280,7 +313,7 @@
 	if (newstate == CHANGED_TRUE || newstate == CHANGED_FALSE) {
 	    /* Turn a ghost into a real object. */
 	    self->po_state = CHANGED;
-	    if (_PyPersist_Load((PyPersistObject *)self) == NULL)
+	    if (_PyPersist_Load((PyPersistBaseObject *)self) == NULL)
 		return -1;
 	    if (newstate == CHANGED_TRUE)
 		self->po_state = CHANGED;
@@ -291,7 +324,7 @@
 	/* Mark an up-to-date object as changed. */
 	if (self->po_state == UPTODATE) {
 	    self->po_state = CHANGED;
-	    if (!_PyPersist_RegisterDataManager((PyPersistObject *)self))
+	    if (!_PyPersist_RegisterDataManager((PyPersistBaseObject *)self))
 		return -1;
 	}
     } else if (newstate == CHANGED_FALSE) {
@@ -319,6 +352,19 @@
     return 0;
 }
 
+static PyObject *
+persist_get_dict(PyPersistObject *self)
+{
+    if (self->po_dict == NULL) {
+	self->po_dict = PyDict_New();
+	if (self->po_dict == NULL)
+	    return NULL;
+    }
+    Py_INCREF(self->po_dict);
+    return self->po_dict;
+}
+
+
 /* convert_name() returns a new reference to a string name
    or sets an exception and returns NULL.
 */
@@ -388,14 +434,14 @@
 	       already registered. 
 	    */
 	    self->po_state = CHANGED;
-	    if (_PyPersist_Load((PyPersistObject *)self) == NULL) {
+	    if (_PyPersist_Load((PyPersistBaseObject *)self) == NULL) {
 		call_p_deactivate(self);
 		self->po_state = GHOST;
 		return NULL;
 	    } else
 		self->po_state = UPTODATE;
 	}
-	_PyPersist_SetATime((PyPersistObject *)self);
+	_PyPersist_SetATime((PyPersistBaseObject *)self);
     }
 
     /* will invoke an __getattr__ if it exists. */
@@ -415,7 +461,7 @@
 */
 
 static int
-persist_setattr_prep(PyPersistObject *self, PyObject *name, 
+persist_setattr_prep(PyPersistBaseObject *self, PyObject *name, 
 			PyObject *value)
 {
     char *s_name;
@@ -445,7 +491,7 @@
 				"attempt to modify unrevivable ghost");
 		return -1;
 	    }
-	    if (_PyPersist_Load((PyPersistObject *)self) == NULL)
+	    if (_PyPersist_Load((PyPersistBaseObject *)self) == NULL)
 		return -1;
 	}
 	/* If the object is marked as UPTODATE then it must be
@@ -457,12 +503,12 @@
 	   XXX What if it's in the sticky state?
 	*/
 	if (self->po_state == UPTODATE && self->po_dm &&
-	    !_PyPersist_RegisterDataManager((PyPersistObject *)self))
+	    !_PyPersist_RegisterDataManager((PyPersistBaseObject *)self))
 	    return -1;
 
 	if (self->po_dm && self->po_oid) {
 	    self->po_state = CHANGED;
-	    _PyPersist_SetATime((PyPersistObject *)self);
+	    _PyPersist_SetATime((PyPersistBaseObject *)self);
 	}
 	return 1;
     }
@@ -470,7 +516,7 @@
 }
 
 static int
-persist_setattro(PyPersistObject *self, PyObject *name, PyObject *value)
+persist_setattro(PyPersistBaseObject *self, PyObject *name, PyObject *value)
 {
     int r;
 
@@ -486,7 +532,7 @@
 }
 
 static PyObject *
-persist_p_set_or_delattr(PyPersistObject *self, PyObject *name, 
+persist_p_set_or_delattr(PyPersistBaseObject *self, PyObject *name, 
 			 PyObject *value)
 {
     PyObject *res;
@@ -521,7 +567,7 @@
 */
 
 static PyObject *
-persist_p_setattr(PyPersistObject *self, PyObject *args)
+persist_p_setattr(PyPersistBaseObject *self, PyObject *args)
 {
     PyObject *name, *value;
 
@@ -538,7 +584,7 @@
 */
 
 static PyObject *
-persist_p_delattr(PyPersistObject *self, PyObject *name)
+persist_p_delattr(PyPersistBaseObject *self, PyObject *name)
 {
     return persist_p_set_or_delattr(self, name, NULL);
 }
@@ -549,6 +595,9 @@
     Py_XDECREF(self->po_dm);
     Py_XDECREF(self->po_oid);
     Py_XDECREF(self->po_serial);
+    if (self->ob_type->tp_dictoffset) {
+	Py_XDECREF(self->po_dict);
+    }
     PyObject_GC_Del(self);
 }
 
@@ -566,6 +615,9 @@
     VISIT(self->po_dm);
     VISIT(self->po_oid);
     VISIT(self->po_serial);
+    if (self->ob_type->tp_dictoffset) {
+	VISIT(self->po_dict);
+    }
 #undef VISIT
     return 0;
 }
@@ -579,6 +631,10 @@
     self->po_dm = NULL;
     self->po_oid = NULL;
     self->po_serial = NULL;
+    if (self->ob_type->tp_dictoffset) {
+	Py_XDECREF(self->po_dict);
+	self->po_dict = NULL;
+    }
     return 0;
 }
 
@@ -628,90 +684,14 @@
   return NULL;
 }
 
-/* Make persistent objects work with Python 2.2. 
-
-   The rules for deciding whether to give an object an __dict__ or an
-   __weakref__ are different in 2.2 than in later versions of Python.
-   In particular, an object will not get an __dict__ if it has a
-   custom setattr.
-*/
-
-static PyObject *
-persist_dict(PyObject *obj, void *context)
-{
-    PyObject **dictptr;
-
-    dictptr = _PyObject_GetDictPtr(obj);
-    assert(dictptr);
-    
-    if (!*dictptr) {
-	PyObject *dict = PyDict_New();
-	if (!dict)
-	    return NULL;
-	*dictptr = dict;
-    }
-    Py_INCREF(*dictptr);
-    return *dictptr;
-}
-
-static PyGetSetDef persist_meta_getsets[] = {
-	{"__dict__",  (getter)persist_dict,  NULL, NULL},
-	{NULL}
+static PyMethodDef base_persist_methods[] = {
+    {"_p_activate", (PyCFunction)persist_activate, METH_NOARGS, },
+    {"_p_deactivate", (PyCFunction)persist_deactivate, METH_NOARGS, },
+    {"_p_setattr", (PyCFunction)persist_p_setattr, METH_VARARGS, },
+    {"_p_delattr", (PyCFunction)persist_p_delattr, METH_O, },
+    {NULL}
 };
 
-/* PyPersist_New is the tp_new of PersistentMetaClass, which exists
-   only for compatibility with Python 2.2. 
-
-   This new function must determine whether to create an __dict__.
-   XXX In the future, it might also handle __weakref__.
-
-   Python 2.2 and 2.3 have fairly different rules for whether an
-   instance should get a dict.  The 2.3 rules will often create an
-   __dict__; we don't want to emulate that functionality because it
-   would make persistent classes different from non-persistent
-   new-style classes.
-*/
-
-static PyObject *
-PyPersist_New(PyTypeObject *type, PyObject *args, PyObject *kwds)
-{
-    PyTypeObject *new;
-
-    new = (PyTypeObject *)PyType_Type.tp_new(type, args, kwds);
-    if (!new)
-	return NULL;
-    
-    /* the slots test is not correct, because all base types must
-       define slots to get slots.
-     */
-    if (!(PyObject_HasAttrString((PyObject *)new, "__slots__")
-	  || new->tp_dictoffset)) {
-	PyObject *descr;
-
-	/* Update the type to know about __dict__. */
-	if (type->tp_itemsize)
-	    new->tp_dictoffset = -(long)sizeof(PyObject *);
-	else
-	    new->tp_dictoffset = type->tp_basicsize;
-	/* alignment issues */
-	new->tp_basicsize += sizeof(PyObject *);
-
-	/* Put a descriptor for __dict__ in the type's __dict__.
-	   It's too late to get type to do this for us. */
-	descr = PyDescr_NewGetSet(new, persist_meta_getsets);
-	if (!descr) {
-	    Py_DECREF(new);
-	    return NULL;
-	}
-	if (PyDict_SetItemString(new->tp_dict, "__dict__", descr) < 0) {
-	    Py_DECREF(new);
-	    return NULL;
-	}
-    }
-    
-    return (PyObject *)new;
-}
-
 static PyMethodDef persist_methods[] = {
     {"__reduce__", (PyCFunction)persist_reduce, METH_NOARGS, },
     {"__getstate__", (PyCFunction)persist_getstate, METH_NOARGS, },
@@ -723,8 +703,14 @@
     {NULL}
 };
 
+static PyGetSetDef base_persist_getsets[] = {
+    {"_p_changed", (getter)persist_get_state, (setter)persist_set_state},
+    {NULL}
+};
+
 static PyGetSetDef persist_getsets[] = {
     {"_p_changed", (getter)persist_get_state, (setter)persist_set_state},
+    {"__dict__", (getter)persist_get_dict},
     {NULL}
 };
 
@@ -735,6 +721,7 @@
     {"_p_oid", T_OBJECT, offsetof(PyPersistObject, po_oid)},
     {"_p_serial", T_OBJECT, offsetof(PyPersistObject, po_serial)},
     {"_p_atime", T_INT, offsetof(PyPersistObject, po_atime)},
+    /* XXX should this be exposed? */
     {"_p_state", T_INT, offsetof(PyPersistObject, po_state), RO},
     {NULL}
 };
@@ -748,14 +735,56 @@
 */
 #define DEFERRED_ADDRESS(ADDR) 0
 
-static PyTypeObject PyPersist_MetaType = {
+/* XXX Not sure how much functionality the base persistent type should
+   provide.  It is currently used only by the BTrees.
+*/
+   
+
+static PyTypeObject PyPersistBase_Type = {
     PyObject_HEAD_INIT(DEFERRED_ADDRESS(&PyType_Type))
     0,					/* ob_size */
-    "Persistence.PersistentMetaClass",	/* tp_name */
+    "Persistence.BasePersistent",	/* tp_name */
+    sizeof(PyPersistBaseObject),	/* tp_basicsize */
+    0,					/* tp_itemsize */
+    (destructor)persist_dealloc,	/* tp_dealloc */
+    0,					/* tp_print */
+    0,					/* tp_getattr */
+    0,					/* tp_setattr */
+    0,					/* tp_compare */
+    0,					/* tp_repr */
+    0,					/* tp_as_number */
+    0,					/* tp_as_sequence */
+    0,					/* tp_as_mapping */
+    0,					/* tp_hash */
+    0,					/* tp_call */
+    0,					/* tp_str */
+    (getattrofunc)persist_getattro,	/* tp_getattro */
+    (setattrofunc)persist_setattro,	/* tp_setattro */
+    0,					/* tp_as_buffer */
+    Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC |
+    Py_TPFLAGS_BASETYPE, 		/* tp_flags */
+    0,					/* tp_doc */
+    (traverseproc)persist_traverse,	/* tp_traverse */
+    (inquiry)persist_clear,		/* tp_clear */
+    0,					/* tp_richcompare */
+    0,					/* tp_weaklistoffset */
+    0,					/* tp_iter */
+    0,					/* tp_iternext */
+    base_persist_methods,		/* tp_methods */
+    persist_members,			/* tp_members */
+    base_persist_getsets,		/* tp_getset */
+    0,					/* tp_base */
+    0,					/* tp_dict */
+    0,					/* tp_descr_get */
+    0,					/* tp_descr_set */
+    0,					/* tp_dictoffset */
+    0,					/* tp_init */
+    0,					/* tp_alloc */
+    0, /*PyType_GenericNew,*/		/* tp_new */
 };
 
 static PyTypeObject PyPersist_Type = {
-    PyObject_HEAD_INIT(&PyPersist_MetaType)
+    PyObject_HEAD_INIT(DEFERRED_ADDRESS(&PyType_Type))
     0,					/* ob_size */
     "Persistence.Persistent",		/* tp_name */
     sizeof(PyPersistObject),		/* tp_basicsize */
@@ -791,26 +820,27 @@
     0,					/* tp_dict */
     0,					/* tp_descr_get */
     0,					/* tp_descr_set */
-    0, 					/* tp_dictoffset */
+    offsetof(PyPersistObject, po_dict),	/* tp_dictoffset */
     0,					/* tp_init */
     0,					/* tp_alloc */
-    0,					/* tp_new */
+    0, /*PyType_GenericNew,*/		/* tp_new */
 };
 
 static PyObject *
 simple_new(PyObject *self, PyObject *type_object)
 {
-    return PyType_GenericNew((PyTypeObject*)type_object, NULL, NULL);
+  return PyType_GenericNew((PyTypeObject*)type_object, NULL, NULL);
 }
 
 static PyMethodDef PyPersist_methods[] = {
-    {"simple_new", simple_new, METH_O,
-     "Create an object by simply calling a class' __new__ method without "
-     "arguments."},
-    {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 = {
+    &PyPersistBase_Type,
     &PyPersist_Type,
     _PyPersist_Load,
     _PyPersist_RegisterDataManager,
@@ -861,22 +891,16 @@
 {
     PyObject *m, *d, *v;
 
-    /* It's easier to initialize a few fields by assignment than to
-       fill out the entire type structure in an initializer. 
-    */
-    PyPersist_MetaType.ob_type = &PyType_Type;
-    PyPersist_MetaType.tp_new = PyPersist_New;
-    PyPersist_MetaType.tp_base = &PyType_Type;
-    PyPersist_MetaType.tp_flags = Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC |
-	Py_TPFLAGS_BASETYPE;
-    PyPersist_MetaType.tp_traverse = PyType_Type.tp_traverse;
-    PyPersist_MetaType.tp_clear = PyType_Type.tp_clear;
-    if (PyType_Ready(&PyPersist_MetaType) < 0)
-	return;
-
+    PyPersistBase_Type.ob_type = &PyType_Type;
+    PyPersistBase_Type.tp_new = PyType_GenericNew;
+    PyPersist_Type.ob_type = &PyType_Type;
     PyPersist_Type.tp_new = PyType_GenericNew;
+    if (PyType_Ready(&PyPersistBase_Type) < 0)
+	return;
     if (PyType_Ready(&PyPersist_Type) < 0)
 	return;
+    if (persist_set_interface(&PyPersistBase_Type) < 0)
+	return;
     if (persist_set_interface(&PyPersist_Type) < 0)
 	return;
 
@@ -891,9 +915,10 @@
     Py_INCREF(&PyPersist_Type);
     if (PyDict_SetItemString(d, "Persistent", (PyObject *)&PyPersist_Type) < 0)
 	return;
-    Py_INCREF(&PyPersist_MetaType);
-    if (PyDict_SetItemString(d, "PersistentMetaClass", 
-			     (PyObject *)&PyPersist_MetaType) < 0)
+
+    Py_INCREF(&PyPersistBase_Type);
+    if (PyDict_SetItemString(d, "BasePersistent", 
+			     (PyObject *)&PyPersistBase_Type) < 0)
 	return;
 
     v = PyCObject_FromVoidPtr(&c_api, NULL);


=== Zope3/lib/python/Persistence/cPersistence.h 1.5 => 1.6 ===
--- Zope3/lib/python/Persistence/cPersistence.h:1.5	Wed Oct  9 18:41:32 2002
+++ Zope3/lib/python/Persistence/cPersistence.h	Thu Oct 10 04:20:06 2002
@@ -40,13 +40,21 @@
     int po_atime; \
     enum PyPersist_State po_state;
 
+#define PyPersist_INSTANCE_HEAD \
+    PyPersist_HEAD \
+    PyObject *po_dict; 
+
 typedef struct {
     PyPersist_HEAD
+} PyPersistBaseObject;
+
+typedef struct {
+    PyPersist_INSTANCE_HEAD
 } PyPersistObject;
 
-extern PyObject *_PyPersist_Load(PyPersistObject *);
-extern PyObject *_PyPersist_RegisterDataManager(PyPersistObject *);
-extern void _PyPersist_SetATime(PyPersistObject *);
+extern PyObject *_PyPersist_Load(PyPersistBaseObject *);
+extern PyObject *_PyPersist_RegisterDataManager(PyPersistBaseObject *);
+extern void _PyPersist_SetATime(PyPersistBaseObject *);
 
 /* A struct to encapsulation the PyPersist C API for use by other
    dynamically load extensions.
@@ -54,8 +62,9 @@
 
 typedef struct {
     PyTypeObject *base_type;
-    PyObject *(*load)(PyPersistObject *);
-    PyObject *(*reg_mgr)(PyPersistObject *);
-    void (*set_atime)(PyPersistObject *);
+    PyTypeObject *instance_type;
+    PyObject *(*load)(PyPersistBaseObject *);
+    PyObject *(*reg_mgr)(PyPersistBaseObject *);
+    void (*set_atime)(PyPersistBaseObject *);
 } PyPersist_C_API_struct;
 


=== Zope3/lib/python/Persistence/cPersistenceAPI.h 1.5 => 1.6 ===
--- Zope3/lib/python/Persistence/cPersistenceAPI.h:1.5	Wed Oct  9 18:41:32 2002
+++ Zope3/lib/python/Persistence/cPersistenceAPI.h	Thu Oct 10 04:20:06 2002
@@ -21,12 +21,13 @@
 
 static PyPersist_C_API_struct *PyPersist_C_API;
 
-#define PyPersist_TYPE PyPersist_C_API->base_type
+#define PyPersist_BASE_TYPE PyPersist_C_API->base_type
+#define PyPersist_INSTANCE_TYPE PyPersist_C_API->instance_type
 
 #define PyPersist_INCREF(O) \
     if (((O)->po_state == UPTODATE) \
 	|| ((O)->po_state == GHOST \
-	    && PyPersist_C_API->load((PyPersistObject *)(O)))) \
+	    && PyPersist_C_API->load((PyPersistBaseObject *)(O)))) \
 	(O)->po_state = STICKY;
 
 #define PyPersist_DECREF(O) \
@@ -40,24 +41,24 @@
     ((O)->po_state == STICKY || (O)->po_state == CHANGED)
 
 #define PyPersist_CHANGED(O) \
-    PyPersist_C_API->reg_mgr((PyPersistObject *)(O))
+    PyPersist_C_API->reg_mgr((PyPersistBaseObject *)(O))
 
 #define PyPersist_SetATime(O) \
-    PyPersist_C_API->set_atime((PyPersistObject *)(O))
+    PyPersist_C_API->set_atime((PyPersistBaseObject *)(O))
 
 /* Macros for compatibility with ZODB 3 C extensions. */
 
 #define PER_USE_OR_RETURN(O, R) \
 { \
     if (((O)->po_state == GHOST) \
-	&& (PyPersist_C_API->load((PyPersistObject *)(O)) < 0)) { \
+	&& (PyPersist_C_API->load((PyPersistBaseObject *)(O)) < 0)) { \
         (O)->po_state = STICKY; \
 	return (R); \
     } else if ((O)->po_state == UPTODATE) \
 	(O)->po_state = STICKY; \
 }
 
-#define PER_CHANGED(O) PyPersist_C_API->reg_mgr((PyPersistObject *)(O))
+#define PER_CHANGED(O) PyPersist_C_API->reg_mgr((PyPersistBaseObject *)(O))
 
 #define PER_ALLOW_DEACTIVATION(O) \
 { \
@@ -72,9 +73,9 @@
 }
 
 #define PER_USE(O) \
-    ((((PyPersistObject *)(O))->po_state != GHOST) \
-     || (PyPersist_C_API->load((PyPersistObject *)(O)) >= 0) \
-     ? ((((PyPersistObject *)(O))->po_state == UPTODATE) \
-	? (((PyPersistObject *)(O))->po_state = STICKY) : 1) : 0)
+    ((((PyPersistBaseObject *)(O))->po_state != GHOST) \
+     || (PyPersist_C_API->load((PyPersistBaseObject *)(O)) >= 0) \
+     ? ((((PyPersistBaseObject *)(O))->po_state == UPTODATE) \
+	? (((PyPersistBaseObject *)(O))->po_state = STICKY) : 1) : 0)
 
-#define PER_ACCESSED(O) PyPersist_C_API->set_atime((PyPersistObject *)O)
+#define PER_ACCESSED(O) PyPersist_C_API->set_atime((PyPersistBaseObject *)O)