[Zope-Checkins] CVS: Zope3/lib/python/Persistence - __init__.py:1.1.40.10 cPersistence.c:1.1.2.14 cPersistence.h:1.1.2.6 cPersistenceAPI.h:1.1.2.6
Jeremy Hylton
jeremy@zope.com
Tue, 4 Jun 2002 14:05:52 -0400
Update of /cvs-repository/Zope3/lib/python/Persistence
In directory cvs.zope.org:/tmp/cvs-serv12193
Modified Files:
Tag: Zope-3x-branch
__init__.py cPersistence.c cPersistence.h cPersistenceAPI.h
Log Message:
Split Persistent into two C types, BasePersistent and Persistent.
BasePersistent is used by persistent objects implemented in C that do
not have an __dict__. Persistent is the base class for persistent
objects implemented in Python.
BasePersistent is exposed to Python as an attribute of the Persistence
package. (Just like Persistent.)
Other changes to the C API:
Expose both PyPersist_Type and PyPersistBase_Type.
The register, load, and accessed functions implemented in C now start
with underscores. Extension modules that need to use these functions
should use the macro versions, which pull the functions from the C API
struct.
The PER_ACCESSED() macro can now be replaced with PyPersist_SetATime().
=== Zope3/lib/python/Persistence/__init__.py 1.1.40.9 => 1.1.40.10 ===
"""Provide access to Persistent and PersistentMapping"""
-from cPersistence import Persistent
+from cPersistence import Persistent, BasePersistent
# XXX why do we hide the real organization of the package?
@@ -23,4 +23,4 @@
from PersistentList import PersistentList
PersistentList.__module__ = 'Persistence'
-__all__ = ["Persistent", "PersistentMapping"]
+__all__ = ["BasePersistent", "Persistent", "PersistentMapping"]
=== Zope3/lib/python/Persistence/cPersistence.c 1.1.2.13 => 1.1.2.14 ===
"$Id$\n";
-staticforward PyTypeObject PyPersist_Type;
+/* 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 for setstate that is more efficient than PyMapping_Keys().
*/
@@ -41,7 +69,7 @@
static PyObject *s_register = NULL;
PyObject *
-PyPersist_RegisterDataManager(PyPersistBaseObject *self)
+_PyPersist_RegisterDataManager(PyPersistBaseObject *self)
{
PyObject *meth, *arg, *result;
@@ -71,7 +99,7 @@
*/
PyObject *
-PyPersist_Load(PyPersistBaseObject *self)
+_PyPersist_Load(PyPersistBaseObject *self)
{
static PyObject *s_setstate = NULL;
PyObject *meth, *arg, *result;
@@ -105,7 +133,7 @@
*/
int
-PyPersist_RegisterTransaction(PyPersistBaseObject *self)
+_PyPersist_RegisterTransaction(PyPersistBaseObject *self)
{
static PyObject *get_transaction = NULL;
PyObject *mainmod = NULL, *builtins = NULL;
@@ -182,7 +210,7 @@
*/
void
-PyPersist_SetATime(PyPersistBaseObject *self)
+_PyPersist_SetATime(PyPersistBaseObject *self)
{
time_t t = time(NULL);
self->po_atime = t % 86400;
@@ -238,7 +266,7 @@
Py_INCREF(Py_None);
return Py_None;
}
-
+
pdict = _PyObject_GetDictPtr(self);
if ((*pdict) == NULL) {
*pdict = PyDict_New();
@@ -378,7 +406,7 @@
if (newstate == CHANGED_TRUE || newstate == CHANGED_FALSE) {
/* Turn a ghost into a real object. */
self->po_state = CHANGED;
- if (PyPersist_Load((PyPersistBaseObject *)self) == NULL)
+ if (_PyPersist_Load((PyPersistBaseObject *)self) == NULL)
return -1;
if (newstate == CHANGED_TRUE)
self->po_state = CHANGED;
@@ -389,7 +417,7 @@
/* Mark an up-to-date object as changed. */
if (self->po_state == UPTODATE) {
self->po_state = CHANGED;
- if (!PyPersist_RegisterDataManager((PyPersistBaseObject *)self))
+ if (!_PyPersist_RegisterDataManager((PyPersistBaseObject *)self))
return -1;
}
} else if (newstate == CHANGED_FALSE) {
@@ -427,6 +455,12 @@
return self->po_dict;
}
+
+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},
@@ -491,14 +525,14 @@
&& (strcmp(s_name, "__dict__") != 0))) {
if (self->po_state == GHOST) {
self->po_state = CHANGED;
- if (PyPersist_Load((PyPersistBaseObject *)self) == NULL) {
+ if (_PyPersist_Load((PyPersistBaseObject *)self) == NULL) {
persist_deactivate(self);
self->po_state = GHOST;
return NULL;
} else
self->po_state = UPTODATE;
}
- PyPersist_SetATime((PyPersistBaseObject *)self);
+ _PyPersist_SetATime((PyPersistBaseObject *)self);
}
attr = PyObject_GenericGetAttr((PyObject *)self, name);
@@ -547,15 +581,15 @@
"attempt to modify unrevivable ghost");
return -1;
}
- if (PyPersist_Load((PyPersistBaseObject *)self) == NULL)
+ if (_PyPersist_Load((PyPersistBaseObject *)self) == NULL)
return -1;
} else if (self->po_state == UPTODATE && self->po_dm)
- if (!PyPersist_RegisterDataManager((PyPersistBaseObject *)self))
+ if (!_PyPersist_RegisterDataManager((PyPersistBaseObject *)self))
return -1;
if (self->po_dm && self->po_oid) {
self->po_state = CHANGED;
- PyPersist_SetATime((PyPersistBaseObject *)self);
+ _PyPersist_SetATime((PyPersistBaseObject *)self);
}
}
@@ -574,7 +608,9 @@
Py_XDECREF(self->po_dm);
Py_XDECREF(self->po_oid);
Py_XDECREF(self->po_serial);
- Py_XDECREF(self->po_dict);
+ if (self->ob_type->tp_dictoffset) {
+ Py_XDECREF(self->po_dict);
+ }
PyObject_GC_Del(self);
}
@@ -592,7 +628,9 @@
VISIT(self->po_dm);
VISIT(self->po_oid);
VISIT(self->po_serial);
- VISIT(self->po_dict);
+ if (self->ob_type->tp_dictoffset) {
+ VISIT(self->po_dict);
+ }
#undef VISIT
return 0;
}
@@ -603,11 +641,13 @@
Py_XDECREF(self->po_dm);
Py_XDECREF(self->po_oid);
Py_XDECREF(self->po_serial);
- Py_XDECREF(self->po_dict);
self->po_dm = NULL;
self->po_oid = NULL;
self->po_serial = NULL;
- self->po_dict = NULL;
+ if (self->ob_type->tp_dictoffset) {
+ Py_XDECREF(self->po_dict);
+ self->po_dict = NULL;
+ }
return 0;
}
@@ -620,6 +660,54 @@
*/
#define DEFERRED_ADDRESS(ADDR) 0
+/* 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.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 */
+ 0, /* 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 */
+ PyType_GenericNew, /* tp_new */
+};
+
static PyTypeObject PyPersist_Type = {
PyObject_HEAD_INIT(DEFERRED_ADDRESS(&PyType_Type))
0, /* ob_size */
@@ -668,10 +756,11 @@
};
static PyPersist_C_API_struct c_api = {
+ &PyPersistBase_Type,
&PyPersist_Type,
- PyPersist_Load,
- PyPersist_RegisterTransaction,
- PyPersist_SetATime
+ _PyPersist_Load,
+ _PyPersist_RegisterTransaction,
+ _PyPersist_SetATime
};
static int
@@ -704,9 +793,14 @@
{
PyObject *m, *d, *v;
+ PyPersistBase_Type.ob_type = &PyType_Type;
PyPersist_Type.ob_type = &PyType_Type;
+ 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;
@@ -720,6 +814,11 @@
Py_INCREF(&PyPersist_Type);
if (PyDict_SetItemString(d, "Persistent", (PyObject *)&PyPersist_Type) < 0)
+ return;
+
+ 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.1.2.5 => 1.1.2.6 ===
} PyPersistObject;
-/* XXX need to make these macros in cPersistenceAPI.h */
-extern PyObject *PyPersist_Load(PyPersistBaseObject *);
-extern PyObject *PyPersist_RegisterDataManager(PyPersistBaseObject *);
-extern int PyPersist_RegisterTransaction(PyPersistBaseObject *);
-extern void PyPersist_SetATime(PyPersistBaseObject *);
+extern PyObject *_PyPersist_Load(PyPersistBaseObject *);
+extern PyObject *_PyPersist_RegisterDataManager(PyPersistBaseObject *);
+extern int _PyPersist_RegisterTransaction(PyPersistBaseObject *);
+extern void _PyPersist_SetATime(PyPersistBaseObject *);
/* A struct to encapsulation the PyPersist C API for use by other
dynamically load extensions.
*/
typedef struct {
- PyTypeObject *type;
+ PyTypeObject *base_type;
+ PyTypeObject *instance_type;
PyObject *(*load)(PyPersistBaseObject *);
int (*reg_trans)(PyPersistBaseObject *);
void (*set_atime)(PyPersistBaseObject *);
=== Zope3/lib/python/Persistence/cPersistenceAPI.h 1.1.2.5 => 1.1.2.6 ===
static PyPersist_C_API_struct *PyPersist_C_API;
-#define PyPersist_TYPE PyPersist_C_API->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) \
@@ -29,6 +30,9 @@
#define PyPersist_CHANGED(O) \
PyPersist_C_API->reg_trans((PyPersistBaseObject *)(O))
+
+#define PyPersist_SetATime(O) \
+ PyPersist_C_API->set_atime((PyPersistBaseObject *)(O))
/* Macros for compatibility with ZODB 3 C extensions. */