[Zope-Checkins] CVS: ZODB3/Persistence - cPersistence.c:1.72.8.11 cPersistence.h:1.25.122.2
Jeremy Hylton
jeremy@zope.com
Thu, 3 Jul 2003 17:07:49 -0400
Update of /cvs-repository/ZODB3/Persistence
In directory cvs.zope.org:/tmp/cvs-serv19211
Modified Files:
Tag: zodb33-devel-branch
cPersistence.c cPersistence.h
Log Message:
Simply Per_setattro() for now and add comment about future work.
Remove two slots from the CAPI that don't make much sense any more.
=== ZODB3/Persistence/cPersistence.c 1.72.8.10 => 1.72.8.11 ===
--- ZODB3/Persistence/cPersistence.c:1.72.8.10 Thu Jul 3 15:21:08 2003
+++ ZODB3/Persistence/cPersistence.c Thu Jul 3 17:07:44 2003
@@ -73,27 +73,6 @@
return self;
}
-static PyObject *
-callmethod1(PyObject *self, PyObject *name, PyObject *arg)
-{
- PyObject *args = NULL, *result = NULL, *meth = NULL;
-
- meth = PyObject_GetAttr(self, name);
- if (!meth)
- goto err;
- args = PyTuple_New(1);
- if (!args)
- goto err;
- PyTuple_SET_ITEM(args, 0, arg);
- result = PyObject_CallObject(meth, args);
- PyTuple_SET_ITEM(name, 0, NULL);
- err:
- Py_XDECREF(meth);
- Py_XDECREF(args);
- return result;
-}
-
-
static void ghostify(cPersistentObject*);
/* Load the state of the object, unghostifying it. Upon success, return 1.
@@ -121,7 +100,7 @@
*/
self->state = cPersistent_CHANGED_STATE;
/* Call the object's __setstate__() */
- r = callmethod1(self->jar, py_setstate, (PyObject*)self);
+ r = PyObject_CallMethod(self->jar, "setstate", "O", (PyObject *)self);
if (r == NULL) {
ghostify(self);
return 0;
@@ -502,95 +481,52 @@
return r;
}
-static int
-_setattro(cPersistentObject *self, PyObject *oname, PyObject *v)
-{
- char *name;
-
- if (oname == NULL)
- return -1;
- if (!PyString_Check(oname))
- return -1;
- name = PyString_AS_STRING(oname);
- if (name == NULL)
- return -1;
+/* We need to decide on a reasonable way for a programmer to write
+ an __setattr__() or __delattr__() hook.
- if (*name == '_' && name[1] == 'p' && name[2] == '_') {
- }
- else
- {
- if (!unghostify(self))
- return -1;
-
- accessed(self);
-
- if ((! (*name=='_' && name[1]=='v' && name[2]=='_'))
- && (self->state != cPersistent_CHANGED_STATE && self->jar)
- && self->ob_type->tp_base->tp_setattro
- )
- if (changed(self) < 0) return -1;
- }
-
- return PyObject_GenericSetAttr((PyObject *)self, oname, v);
-}
+ The ZODB3 has been that if you write a hook, it will be called if
+ the attribute is not an _p_ attribute and after doing any necessary
+ unghostifying. AMK's guide says modification will not be tracked
+ automatically, so the hook must explicitly set _p_changed; I'm not
+ sure if I believe that.
+
+ This approach won't work with new-style classes, because type will
+ install a slot wrapper that calls the derived class's __setattr__().
+ That means Persistent's tp_setattro doesn't get a chance to be called.
+ Changing this behavior would require a metaclass.
+
+ One option for ZODB 3.3 is to require setattr hooks to know about
+ _p_ and to call a prep function before modifying the object's state.
+ That's the solution I like best at the moment.
+*/
static int
-Per_setattro(cPersistentObject *self, PyObject *oname, PyObject *v)
+Per_setattro(cPersistentObject *self, PyObject *name, PyObject *v)
{
- int r;
- PyObject *m;
+ int r;
+ char *s;
- if (v)
- {
- r = _setattro(self, oname, v);
- if (r < 1) return r;
+ name = convert_name(name);
+ if (!name)
+ return -1;
+ s = PyString_AS_STRING(name);
- m=PyObject_GetAttr((PyObject *)self, py___setattr__);
- if (m)
- {
- ASSIGN(m, PyObject_CallFunction(m, "OO", oname, v));
+ if (strncmp(s, "_p_", 3) != 0) {
+ if (!unghostify(self))
+ return -1;
+ accessed(self);
+ if (strncmp(s, "_v_", 3) != 0
+ && self->state != cPersistent_CHANGED_STATE) {
+ if (changed(self) < 0)
+ return -1;
}
- else PyErr_SetObject(PyExc_AttributeError, oname);
}
- else if (!v)
- {
- r=_setattro(self,oname, v);
- if (r < 1) return r;
+ r = PyObject_GenericSetAttr((PyObject *)self, name, v);
- m=PyObject_GetAttr((PyObject *)self, py___delattr__);
- if (m)
- {
- ASSIGN(m, PyObject_CallFunction(m, "O", oname));
- }
- else PyErr_SetObject(PyExc_AttributeError, oname);
- }
- else
- return _setattro(self, oname, v);
-
- if (m)
- {
- Py_DECREF(m);
- return 0;
- }
-
- return -1;
+ Py_DECREF(name);
+ return r;
}
-/*
-
-static PyMethodDef Per_methods[] = {
- {"__reduce__", (PyCFunction)persist_reduce, METH_NOARGS, },
- {"__getstate__", (PyCFunction)persist_getstate, METH_NOARGS, },
- {"__setstate__", persist_setstate, METH_O, },
- {"_p_activate", (PyCFunction)persist_activate, METH_NOARGS, },
- {"_p_deactivate", (PyCFunction)persist_deactivate, METH_KEYWORDS, },
- {"_p_setattr", (PyCFunction)persist_p_setattr, METH_VARARGS, },
- {"_p_delattr", (PyCFunction)persist_p_delattr, METH_O, },
- {NULL}
-};
-
-*/
-
static PyObject *
Per_get_changed(cPersistentObject *self)
{
@@ -834,8 +770,6 @@
ghostify,
deallocated,
(intfunctionwithpythonarg)Per_setstate,
- (pergetattr)Per_getattro,
- (persetattr)_setattro,
NULL /* The percachedel slot is initialized in cPickleCache.c when
the module is loaded. It uses a function in a different
shared library. */
=== ZODB3/Persistence/cPersistence.h 1.25.122.1 => 1.25.122.2 ===
--- ZODB3/Persistence/cPersistence.h:1.25.122.1 Tue Jul 1 15:28:11 2003
+++ ZODB3/Persistence/cPersistence.h Thu Jul 3 17:07:44 2003
@@ -65,8 +65,6 @@
void (*ghostify)(cPersistentObject*);
void (*deallocated)(cPersistentObject*);
int (*setstate)(PyObject*);
- pergetattr pergetattro;
- persetattr persetattro;
percachedelfunc percachedel;
} cPersistenceCAPIstruct;