Commit e94f7e66 authored by Jeremy Hylton's avatar Jeremy Hylton

Rewrite new_persistent_id() to make it clear what's going on.

Reformat all the code to use Python style.

We got an undiagnosed bug report for coptimization, which lead to an
attempt at code review.

Break up a the large new_persistent_id() function into several helpers
-- get_class(), get_class_tuple(), and set_oid().  Each function now
does a little less.  Don't reuse variable names for random purposes.
parent 121f2e20
...@@ -13,7 +13,7 @@ ...@@ -13,7 +13,7 @@
############################################################################## ##############################################################################
"""Database connection support """Database connection support
$Id: Connection.py,v 1.75 2002/09/07 17:22:09 jeremy Exp $""" $Id: Connection.py,v 1.76 2002/09/16 23:50:39 jeremy Exp $"""
from cPickleCache import PickleCache, MUCH_RING_CHECKING from cPickleCache import PickleCache, MUCH_RING_CHECKING
from POSException import ConflictError, ReadConflictError from POSException import ConflictError, ReadConflictError
...@@ -350,7 +350,7 @@ class Connection(ExportImport.ExportImport): ...@@ -350,7 +350,7 @@ class Connection(ExportImport.ExportImport):
file=StringIO() file=StringIO()
seek=file.seek seek=file.seek
pickler=Pickler(file,1) pickler=Pickler(file,1)
pickler.persistent_id=new_persistent_id(self, stack.append) pickler.persistent_id=new_persistent_id(self, stack)
dbstore=self._storage.store dbstore=self._storage.store
file=file.getvalue file=file.getvalue
cache=self._cache cache=self._cache
......
...@@ -14,7 +14,7 @@ ...@@ -14,7 +14,7 @@
static char coptimizations_doc_string[] = static char coptimizations_doc_string[] =
"C optimization for new_persistent_id().\n" "C optimization for new_persistent_id().\n"
"\n" "\n"
"$Id: coptimizations.c,v 1.17 2002/03/08 18:36:14 jeremy Exp $\n"; "$Id: coptimizations.c,v 1.18 2002/09/16 23:50:39 jeremy Exp $\n";
#include "Python.h" #include "Python.h"
#define DONT_USE_CPERSISTENCECAPI #define DONT_USE_CPERSISTENCECAPI
...@@ -33,179 +33,204 @@ static PyObject *InvalidObjectReference; ...@@ -33,179 +33,204 @@ static PyObject *InvalidObjectReference;
typedef struct { typedef struct {
PyObject_HEAD PyObject_HEAD
PyObject *jar, *stackup, *new_oid; PyObject *jar, *stack, *new_oid;
} persistent_id; } persistent_id;
staticforward PyTypeObject persistent_idType; static PyTypeObject persistent_idType;
static persistent_id * static persistent_id *
newpersistent_id(PyObject *ignored, PyObject *args) newpersistent_id(PyObject *ignored, PyObject *args)
{ {
persistent_id *self; persistent_id *self;
PyObject *jar, *stackup; PyObject *jar, *stack;
UNLESS (PyArg_ParseTuple(args, "OO", &jar, &stackup)) return NULL; if (!PyArg_ParseTuple(args, "OO!", &jar, &PyList_Type, &stack))
UNLESS(self = PyObject_NEW(persistent_id, &persistent_idType)) return NULL; return NULL;
self = PyObject_NEW(persistent_id, &persistent_idType);
if (!self)
return NULL;
Py_INCREF(jar); Py_INCREF(jar);
self->jar=jar; self->jar = jar;
Py_INCREF(stackup); Py_INCREF(stack);
self->stackup=stackup; self->stack = stack;
self->new_oid=NULL; self->new_oid = NULL;
return self; return self;
} }
static void static void
persistent_id_dealloc(persistent_id *self) persistent_id_dealloc(persistent_id *self)
{ {
Py_DECREF(self->jar); Py_DECREF(self->jar);
Py_DECREF(self->stackup); Py_DECREF(self->stack);
Py_XDECREF(self->new_oid); Py_XDECREF(self->new_oid);
PyObject_DEL(self); PyObject_DEL(self);
} }
/* Returns the klass of a persistent object.
Returns NULL for other objects.
*/
static PyObject * static PyObject *
persistent_id_call(persistent_id *self, PyObject *args, PyObject *kwargs) get_class(PyObject *object)
{ {
PyObject *object, *oid, *jar=NULL, *r=NULL, *klass=NULL; PyObject *class;
/* if (!PyExtensionClass_Check(object)) {
def persistent_id(object, self=self,stackup=stackup): if (PyExtensionInstance_Check(object)) {
*/ class = PyObject_GetAttr(object, py___class__);
UNLESS (PyArg_ParseTuple(args, "O", &object)) return NULL; if (!class) {
PyErr_Clear();
return NULL;
}
if (!PyExtensionClass_Check(class) ||
!(((PyExtensionClass*)class)->class_flags
& PERSISTENT_TYPE_FLAG)) {
Py_DECREF(class);
return NULL;
}
}
else
return NULL;
}
return class;
}
/* /* Return a two-tuple of the class's module and name.
if (not hasattr(object, '_p_oid') or
type(object) is ClassType): return None
*/ */
static PyObject *
get_class_tuple(PyObject *class, PyObject *oid)
{
PyObject *module = NULL, *name = NULL, *tuple;
module = PyObject_GetAttr(class, py___module__);
/* Filter out most objects with low-level test. if (!module)
Yee ha! goto err;
(Also get klass along the way.) if (!PyObject_IsTrue(module)) {
*/ Py_DECREF(module);
if (! PyExtensionClass_Check(object)) { /* XXX Handle degenerate 1.x ZClass case. */
if (PyExtensionInstance_Check(object)) return oid;
{
UNLESS (klass=PyObject_GetAttr(object, py___class__))
{
PyErr_Clear();
goto not_persistent;
} }
UNLESS (
PyExtensionClass_Check(klass) &&
(((PyExtensionClass*)klass)->class_flags
& PERSISTENT_TYPE_FLAG)
)
goto not_persistent;
name = PyObject_GetAttr(class, py___name__);
if (!name)
goto err;
tuple = PyTuple_New(2);
if (!tuple)
goto err;
PyTuple_SET_ITEM(tuple, 0, module);
PyTuple_SET_ITEM(tuple, 1, name);
return tuple;
err:
Py_XDECREF(module);
Py_XDECREF(name);
return NULL;
}
static PyObject *
set_oid(persistent_id *self, PyObject *object)
{
PyObject *oid;
if (!self->new_oid) {
self->new_oid = PyObject_GetAttr(self->jar, py_new_oid);
if (!self->new_oid)
return NULL;
} }
else oid = PyObject_CallObject(self->new_oid, NULL);
goto not_persistent; if (!oid)
} return NULL;
if (PyObject_SetAttr(object, py__p_oid, oid) < 0)
goto err;
if (PyObject_SetAttr(object, py__p_jar, self->jar) < 0)
goto err;
if (PyList_Append(self->stack, object) < 0)
goto err;
return oid;
err:
Py_DECREF(oid);
return NULL;
}
static PyObject *
persistent_id_call(persistent_id *self, PyObject *args, PyObject *kwargs)
{
PyObject *object, *oid, *klass=NULL;
PyObject *t1, *t2;
int setjar = 0;
if (!PyArg_ParseTuple(args, "O", &object))
return NULL;
UNLESS (oid=PyObject_GetAttr(object, py__p_oid)) klass = get_class(object);
{ if (!klass)
goto return_none;
oid = PyObject_GetAttr(object, py__p_oid);
if (!oid) {
PyErr_Clear(); PyErr_Clear();
goto not_persistent; Py_DECREF(klass);
goto return_none;
} }
/* if (oid != Py_None) {
if oid is None or object._p_jar is not self: PyObject *jar = PyObject_GetAttr(object, py__p_jar);
*/ if (!jar)
if (oid != Py_None) PyErr_Clear();
{ else {
UNLESS (jar=PyObject_GetAttr(object, py__p_jar)) PyErr_Clear(); if (jar != Py_None && jar != self->jar) {
if (jar && jar != Py_None && jar != self->jar)
{
PyErr_SetString(InvalidObjectReference, PyErr_SetString(InvalidObjectReference,
"Attempt to store an object from a foreign " "Attempt to store an object from a foreign "
"database connection"); "database connection");
return NULL; goto err;
}
/* Ignore the oid of the unknown jar and assign a new one. */
if (jar == Py_None)
setjar = 1;
Py_DECREF(jar);
} }
} }
if (oid == Py_None || jar != self->jar) if (oid == Py_None || setjar) {
{ Py_DECREF(oid);
/* oid = set_oid(self, object);
oid = self.new_oid() if (!oid)
object._p_jar=self
object._p_oid=oid
stackup(object)
*/
UNLESS (self->new_oid ||
(self->new_oid=PyObject_GetAttr(self->jar, py_new_oid)))
goto err; goto err;
ASSIGN(oid, PyObject_CallObject(self->new_oid, NULL));
UNLESS (oid) goto null_oid;
if (PyObject_SetAttr(object, py__p_jar, self->jar) < 0) goto err;
if (PyObject_SetAttr(object, py__p_oid, oid) < 0) goto err;
UNLESS (r=PyTuple_New(1)) goto err;
PyTuple_SET_ITEM(r, 0, object);
Py_INCREF(object);
ASSIGN(r, PyObject_CallObject(self->stackup, r));
UNLESS (r) goto err;
Py_DECREF(r);
} }
/* if (PyExtensionClass_Check(object)
klass=object.__class__ || PyObject_HasAttr(klass, py___getinitargs__))
goto return_oid;
if klass is ExtensionKlass: return oid
*/
if (PyExtensionClass_Check(object)) goto return_oid;
/*
if hasattr(klass, '__getinitargs__'): return oid
*/
if ((r=PyObject_GetAttr(klass, py___getinitargs__))) t2 = get_class_tuple(klass, oid);
{ if (!t2)
Py_DECREF(r); goto err;
if (t2 == oid) /* pass through ZClass special case */
goto return_oid; goto return_oid;
t1 = PyTuple_New(2);
if (!t1) {
Py_DECREF(t2);
goto err;
} }
PyErr_Clear(); /* use borrowed references to oid and t2 */
PyTuple_SET_ITEM(t1, 0, oid);
/* PyTuple_SET_ITEM(t1, 1, t2);
module=getattr(klass,'__module__','')
if module: klass=module, klass.__name__
else: return oid # degenerate 1.x ZClass case
*/
UNLESS (jar=PyObject_GetAttr(klass, py___module__)) goto err;
UNLESS (PyObject_IsTrue(jar)) goto return_oid; Py_DECREF(klass);
ASSIGN(klass, PyObject_GetAttr(klass, py___name__)); return t1;
UNLESS (klass) goto err;
UNLESS (r=PyTuple_New(2)) goto err; err:
PyTuple_SET_ITEM(r, 0, jar); Py_XDECREF(oid);
PyTuple_SET_ITEM(r, 1, klass); oid = NULL;
klass=r;
jar=NULL;
/* return_oid:
return oid, klass Py_XDECREF(klass);
*/ return oid;
UNLESS (r=PyTuple_New(2)) goto err;
PyTuple_SET_ITEM(r, 0, oid);
PyTuple_SET_ITEM(r, 1, klass);
return r;
not_persistent: return_none:
Py_INCREF(Py_None); Py_INCREF(Py_None);
return Py_None; return Py_None;
err:
Py_DECREF(oid);
oid=NULL;
null_oid:
return_oid:
Py_XDECREF(jar);
Py_XDECREF(klass);
return oid;
} }
...@@ -244,9 +269,8 @@ static PyTypeObject persistent_idType = { ...@@ -244,9 +269,8 @@ static PyTypeObject persistent_idType = {
static struct PyMethodDef Module_Level__methods[] = { static struct PyMethodDef Module_Level__methods[] = {
{"new_persistent_id", (PyCFunction)newpersistent_id, METH_VARARGS, {"new_persistent_id", (PyCFunction)newpersistent_id, METH_VARARGS,
"new_persistent_id(jar, stackup, new_oid)" "new_persistent_id(jar, stack) -- get a new persistent_id function"},
" -- get a new persistent_id function"}, {NULL, NULL} /* sentinel */
{NULL, (PyCFunction)NULL, 0, NULL} /* sentinel */
}; };
void void
...@@ -271,17 +295,13 @@ initcoptimizations(void) ...@@ -271,17 +295,13 @@ initcoptimizations(void)
UNLESS (m) return; UNLESS (m) return;
InvalidObjectReference=m; InvalidObjectReference=m;
UNLESS (ExtensionClassImported) return; if (!ExtensionClassImported)
return;
m = Py_InitModule4("coptimizations", Module_Level__methods, m = Py_InitModule3("coptimizations", Module_Level__methods,
coptimizations_doc_string, coptimizations_doc_string);
(PyObject*)NULL,PYTHON_API_VERSION);
d = PyModule_GetDict(m); d = PyModule_GetDict(m);
persistent_idType.ob_type=&PyType_Type; persistent_idType.ob_type = &PyType_Type;
PyDict_SetItemString(d,"persistent_idType", OBJECT(&persistent_idType)); PyDict_SetItemString(d,"persistent_idType", OBJECT(&persistent_idType));
/* Check for errors */
if (PyErr_Occurred())
Py_FatalError("can't initialize module coptimizations");
} }
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment