[Checkins] SVN: persistent/trunk/ Work toward tests passing under Python3 with C modules importable.
Tres Seaver
cvs-admin at zope.org
Fri Dec 14 00:21:16 UTC 2012
Log message for revision 128632:
Work toward tests passing under Python3 with C modules importable.
Changed:
_U persistent/trunk/
A persistent/trunk/persistent/_compat.h
U persistent/trunk/persistent/_timestamp.c
U persistent/trunk/persistent/cPersistence.c
U persistent/trunk/persistent/cPersistence.h
U persistent/trunk/persistent/cPickleCache.c
U persistent/trunk/persistent/tests/test_persistence.py
U persistent/trunk/persistent/tests/test_timestamp.py
-=-
Added: persistent/trunk/persistent/_compat.h
===================================================================
--- persistent/trunk/persistent/_compat.h (rev 0)
+++ persistent/trunk/persistent/_compat.h 2012-12-14 00:21:15 UTC (rev 128632)
@@ -0,0 +1,48 @@
+/*****************************************************************************
+
+ Copyright (c) 2012 Zope Foundation and Contributors.
+ All Rights Reserved.
+
+ This software is subject to the provisions of the Zope Public License,
+ Version 2.1 (ZPL). A copy of the ZPL should accompany this distribution.
+ THIS SOFTWARE IS PROVIDED "AS IS" AND ANY AND ALL EXPRESS OR IMPLIED
+ WARRANTIES ARE DISCLAIMED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ WARRANTIES OF TITLE, MERCHANTABILITY, AGAINST INFRINGEMENT, AND FITNESS
+ FOR A PARTICULAR PURPOSE
+
+ ****************************************************************************/
+
+#ifndef PERSISTENT__COMPAT_H
+#define PERSISTENT__COMPAT_H
+
+#include "Python.h"
+
+#if PY_MAJOR_VERSION >= 3
+#define PY3K
+#endif
+
+#ifdef PY3K
+#define INTERN PyUnicode_InternFromString
+#define NATIVE_AS_STRING(x) PyBytes_AS_STRING(PyUnicode_AsUTF16String((x)))
+#define NATIVE_FROM_STRING PyUnicode_FromString
+#define NATIVE_FROM_STRING_AND_SIZE PyUnicode_FromStringAndSize
+
+#define Py_TPFLAGS_HAVE_RICHCOMPARE 0
+
+#define INT_FROM_LONG(x) PyLong_FromLong(x)
+#define INT_CHECK(x) PyLong_Check(x)
+#define INT_AS_LONG(x) PyLong_AS_LONG(x)
+#define CAPI_CAPSULE_NAME "persistent.cPersistence.CAPI"
+
+#else
+#define INTERN PyString_InternFromString
+#define NATIVE_AS_STRING PyString_AsString
+#define NATIVE_FROM_STRING PyString_FromString
+#define NATIVE_FROM_STRING_AND_SIZE PyString_FromStringAndSize
+
+#define INT_FROM_LONG(x) PyInt_FromLong(x)
+#define INT_CHECK(x) PyInt_Check(x)
+#define INT_AS_LONG(x) PyInt_AS_LONG(x)
+#endif
+
+#endif
Modified: persistent/trunk/persistent/_timestamp.c
===================================================================
--- persistent/trunk/persistent/_timestamp.c 2012-12-14 00:21:12 UTC (rev 128631)
+++ persistent/trunk/persistent/_timestamp.c 2012-12-14 00:21:15 UTC (rev 128632)
@@ -15,18 +15,9 @@
#include "Python.h"
#include "bytesobject.h"
#include <time.h>
+#include "_compat.h"
-#if PY_MAJOR_VERSION >= 3
-#define PY3K
-#define Py_TPFLAGS_HAVE_RICHCOMPARE 0
-#endif
-#ifdef PY3K
-#define INT_FROM_LONG(x) PyLong_FromLong(x)
-#else
-#define INT_FROM_LONG(x) PyInt_FromLong(x)
-#endif
-
PyObject *TimeStamp_FromDate(int, int, int, int, int, double);
PyObject *TimeStamp_FromString(const char *);
@@ -36,21 +27,24 @@
"$Id$\n";
-typedef struct {
+typedef struct
+{
PyObject_HEAD
unsigned char data[8];
} TimeStamp;
/* The first dimension of the arrays below is non-leapyear / leapyear */
-static char month_len[2][12]={
- {31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31},
- {31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31}
+static char month_len[2][12] =
+{
+ {31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31},
+ {31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31}
};
-static short joff[2][12] = {
- {0, 31, 59, 90, 120, 151, 181, 212, 243, 273, 304, 334},
- {0, 31, 60, 91, 121, 152, 182, 213, 244, 274, 305, 335}
+static short joff[2][12] =
+{
+ {0, 31, 59, 90, 120, 151, 181, 212, 243, 273, 304, 334},
+ {0, 31, 60, 91, 121, 152, 182, 213, 244, 274, 305, 335}
};
static double gmoff=0;
@@ -80,10 +74,10 @@
d = (y - 1) * 365;
if (y > 0) {
s = 1.0;
- y -= 1;
+ y -= 1;
} else {
- s = -1.0;
- y = -y;
+ s = -1.0;
+ y = -y;
}
return d + s * (y / 4 - y / 100 + (y + 300) / 400);
}
@@ -101,13 +95,14 @@
time_t z=0;
t = gmtime(&z);
- if (t == NULL) {
- PyErr_SetString(PyExc_SystemError, "gmtime failed");
- return -1;
+ if (t == NULL)
+ {
+ PyErr_SetString(PyExc_SystemError, "gmtime failed");
+ return -1;
}
gmoff = TimeStamp_abst(t->tm_year+1900, t->tm_mon, t->tm_mday - 1,
- t->tm_hour * 60 + t->tm_min, t->tm_sec);
+ t->tm_hour * 60 + t->tm_min, t->tm_sec);
return 0;
}
@@ -124,10 +119,12 @@
PyObject *result = NULL;
int cmp;
- if (Py_TYPE(other) != Py_TYPE(self)) {
+ if (Py_TYPE(other) != Py_TYPE(self))
+ {
result = Py_NotImplemented;
}
- else {
+ else
+ {
cmp = memcmp(self->data, other->data, 8);
switch (op) {
case Py_LT:
@@ -162,14 +159,15 @@
register int len = 8;
register long x = *p << 7;
while (--len >= 0)
- x = (1000003*x) ^ *p++;
+ x = (1000003*x) ^ *p++;
x ^= 8;
if (x == -1)
- x = -2;
+ x = -2;
return x;
}
-typedef struct {
+typedef struct
+{
/* TODO: reverse-engineer what's in these things and comment them */
int y;
int m;
@@ -183,7 +181,7 @@
unsigned long v;
v = (self->data[0] * 16777216 + self->data[1] * 65536
- + self->data[2] * 256 + self->data[3]);
+ + self->data[2] * 256 + self->data[3]);
p->y = v / 535680 + 1900;
p->m = (v % 535680) / 44640 + 1;
p->d = (v % 44640) / 1440 + 1;
@@ -196,7 +194,7 @@
unsigned int v;
v = (self->data[4] * 16777216 + self->data[5] * 65536
- + self->data[6] * 256 + self->data[7]);
+ + self->data[6] * 256 + self->data[7]);
return SCONV * v;
}
@@ -252,7 +250,7 @@
TimeStampParts p;
TimeStamp_unpack(self, &p);
return PyFloat_FromDouble(TimeStamp_abst(p.y, p.m - 1, p.d - 1, p.mi, 0)
- + TimeStamp_sec(self) - gmoff);
+ + TimeStamp_sec(self) - gmoff);
}
static PyObject *
@@ -262,6 +260,12 @@
}
static PyObject *
+TimeStamp_repr(TimeStamp *self)
+{
+ return NATIVE_FROM_STRING_AND_SIZE((const char*)self->data, 8);
+}
+
+static PyObject *
TimeStamp_str(TimeStamp *self)
{
char buf[128];
@@ -270,8 +274,8 @@
TimeStamp_unpack(self, &p);
len =sprintf(buf, "%4.4d-%2.2d-%2.2d %2.2d:%2.2d:%09.6f",
- p.y, p.m, p.d, p.mi / 60, p.mi % 60,
- TimeStamp_sec(self));
+ p.y, p.m, p.d, p.mi / 60, p.mi % 60,
+ TimeStamp_sec(self));
return PyBytes_FromStringAndSize(buf, len);
}
@@ -285,98 +289,110 @@
unsigned char new[8];
int i;
- if (Py_TYPE(obj) != Py_TYPE(self)) {
- PyErr_SetString(PyExc_TypeError, "expected TimeStamp object");
- return NULL;
+ if (Py_TYPE(obj) != Py_TYPE(self))
+ {
+ PyErr_SetString(PyExc_TypeError, "expected TimeStamp object");
+ return NULL;
}
o = (TimeStamp *)obj;
- if (memcmp(self->data, o->data, 8) > 0) {
- Py_INCREF(self);
- return (PyObject *)self;
+ if (memcmp(self->data, o->data, 8) > 0)
+ {
+ Py_INCREF(self);
+ return (PyObject *)self;
}
memcpy(new, o->data, 8);
- for (i = 7; i > 3; i--) {
- if (new[i] == 255)
- new[i] = 0;
- else {
- new[i]++;
- return TimeStamp_FromString((const char*)new);
- }
+ for (i = 7; i > 3; i--)
+ {
+ if (new[i] == 255)
+ new[i] = 0;
+ else
+ {
+ new[i]++;
+ return TimeStamp_FromString((const char*)new);
+ }
}
/* All but the first two bytes are the same. Need to increment
the year, month, and day explicitly. */
TimeStamp_unpack(o, &p);
- if (p.mi >= 1439) {
- p.mi = 0;
- if (p.d == month_len[leap(p.y)][p.m - 1]) {
- p.d = 1;
- if (p.m == 12) {
- p.m = 1;
- p.y++;
- } else
- p.m++;
- } else
- p.d++;
- } else
- p.mi++;
+ if (p.mi >= 1439)
+ {
+ p.mi = 0;
+ if (p.d == month_len[leap(p.y)][p.m - 1])
+ {
+ p.d = 1;
+ if (p.m == 12)
+ {
+ p.m = 1;
+ p.y++;
+ }
+ else
+ p.m++;
+ }
+ else
+ p.d++;
+ }
+ else
+ p.mi++;
return TimeStamp_FromDate(p.y, p.m, p.d, p.mi / 60, p.mi % 60, 0);
}
-static struct PyMethodDef TimeStamp_methods[] = {
- {"year", (PyCFunction)TimeStamp_year, METH_NOARGS},
- {"minute", (PyCFunction)TimeStamp_minute, METH_NOARGS},
- {"month", (PyCFunction)TimeStamp_month, METH_NOARGS},
- {"day", (PyCFunction)TimeStamp_day, METH_NOARGS},
- {"hour", (PyCFunction)TimeStamp_hour, METH_NOARGS},
- {"second", (PyCFunction)TimeStamp_second, METH_NOARGS},
- {"timeTime",(PyCFunction)TimeStamp_timeTime, METH_NOARGS},
- {"laterThan", (PyCFunction)TimeStamp_laterThan, METH_O},
- {"raw", (PyCFunction)TimeStamp_raw, METH_NOARGS},
- {NULL, NULL},
+static struct PyMethodDef TimeStamp_methods[] =
+{
+ {"year", (PyCFunction)TimeStamp_year, METH_NOARGS},
+ {"minute", (PyCFunction)TimeStamp_minute, METH_NOARGS},
+ {"month", (PyCFunction)TimeStamp_month, METH_NOARGS},
+ {"day", (PyCFunction)TimeStamp_day, METH_NOARGS},
+ {"hour", (PyCFunction)TimeStamp_hour, METH_NOARGS},
+ {"second", (PyCFunction)TimeStamp_second, METH_NOARGS},
+ {"timeTime", (PyCFunction)TimeStamp_timeTime, METH_NOARGS},
+ {"laterThan", (PyCFunction)TimeStamp_laterThan, METH_O},
+ {"raw", (PyCFunction)TimeStamp_raw, METH_NOARGS},
+ {NULL, NULL},
};
#define DEFERRED_ADDRESS(ADDR) 0
-static PyTypeObject TimeStamp_type = {
+static PyTypeObject TimeStamp_type =
+{
PyVarObject_HEAD_INIT(DEFERRED_ADDRESS(NULL), 0)
"persistent.TimeStamp",
sizeof(TimeStamp), /* tp_basicsize */
0, /* tp_itemsize */
- (destructor)TimeStamp_dealloc, /* tp_dealloc */
- 0, /* tp_print */
- 0, /* tp_getattr */
- 0, /* tp_setattr */
- 0, /* tp_compare */
- (reprfunc)TimeStamp_raw, /* tp_repr */
- 0, /* tp_as_number */
- 0, /* tp_as_sequence */
- 0, /* tp_as_mapping */
- (hashfunc)TimeStamp_hash, /* tp_hash */
- 0, /* tp_call */
- (reprfunc)TimeStamp_str, /* tp_str */
- 0, /* tp_getattro */
- 0, /* tp_setattro */
- 0, /* tp_as_buffer */
+ (destructor)TimeStamp_dealloc, /* tp_dealloc */
+ 0, /* tp_print */
+ 0, /* tp_getattr */
+ 0, /* tp_setattr */
+ 0, /* tp_compare */
+ (reprfunc)TimeStamp_repr, /* tp_repr */
+ 0, /* tp_as_number */
+ 0, /* tp_as_sequence */
+ 0, /* tp_as_mapping */
+ (hashfunc)TimeStamp_hash, /* tp_hash */
+ 0, /* tp_call */
+ (reprfunc)TimeStamp_str, /* tp_str */
+ 0, /* tp_getattro */
+ 0, /* tp_setattro */
+ 0, /* tp_as_buffer */
Py_TPFLAGS_DEFAULT |
Py_TPFLAGS_BASETYPE |
Py_TPFLAGS_HAVE_RICHCOMPARE, /* tp_flags */
- 0, /* tp_doc */
- 0, /* tp_traverse */
- 0, /* tp_clear */
+ 0, /* tp_doc */
+ 0, /* tp_traverse */
+ 0, /* tp_clear */
(richcmpfunc)&TimeStamp_richcompare, /* tp_richcompare */
- 0, /* tp_weaklistoffset */
- 0, /* tp_iter */
- 0, /* tp_iternext */
- TimeStamp_methods, /* tp_methods */
- 0, /* tp_members */
- 0, /* tp_getset */
- 0, /* tp_base */
- 0, /* tp_dict */
- 0, /* tp_descr_get */
- 0, /* tp_descr_set */
+ 0, /* tp_weaklistoffset */
+ 0, /* tp_iter */
+ 0, /* tp_iternext */
+ TimeStamp_methods, /* tp_methods */
+ 0, /* tp_members */
+ 0, /* tp_getset */
+ 0, /* tp_base */
+ 0, /* tp_dict */
+ 0, /* tp_descr_get */
+ 0, /* tp_descr_set */
};
PyObject *
@@ -390,33 +406,33 @@
#define CHECK_RANGE(VAR, LO, HI) if ((VAR) < (LO) || (VAR) > (HI)) { \
return PyErr_Format(PyExc_ValueError, \
- # VAR " must be between %d and %d: %d", \
- (LO), (HI), (VAR)); \
+ # VAR " must be between %d and %d: %d", \
+ (LO), (HI), (VAR)); \
}
PyObject *
TimeStamp_FromDate(int year, int month, int day, int hour, int min,
- double sec)
+ double sec)
{
TimeStamp *ts = NULL;
int d;
unsigned int v;
if (year < 1900)
- return PyErr_Format(PyExc_ValueError,
- "year must be greater than 1900: %d", year);
+ return PyErr_Format(PyExc_ValueError,
+ "year must be greater than 1900: %d", year);
CHECK_RANGE(month, 1, 12);
d = days_in_month(year, month - 1);
if (day < 1 || day > d)
- return PyErr_Format(PyExc_ValueError,
- "day must be between 1 and %d: %d", d, day);
+ return PyErr_Format(PyExc_ValueError,
+ "day must be between 1 and %d: %d", d, day);
CHECK_RANGE(hour, 0, 23);
CHECK_RANGE(min, 0, 59);
/* Seconds are allowed to be anything, so chill
If we did want to be pickly, 60 would be a better choice.
if (sec < 0 || sec > 59)
- return PyErr_Format(PyExc_ValueError,
- "second must be between 0 and 59: %f", sec);
+ return PyErr_Format(PyExc_ValueError,
+ "second must be between 0 and 59: %f", sec);
*/
ts = (TimeStamp *)PyObject_New(TimeStamp, &TimeStamp_type);
v = (((year - 1900) * 12 + month - 1) * 31 + day - 1);
@@ -442,61 +458,79 @@
int len = 0, y, mo, d, h = 0, m = 0;
double sec = 0;
- if (PyArg_ParseTuple(args, "s#:TimeStamp", &buf, &len)) {
- if (len != 8) {
- PyErr_SetString(PyExc_ValueError, "8-character string expected");
- return NULL;
- }
- return TimeStamp_FromString(buf);
+ if (PyArg_ParseTuple(args, "s#:TimeStamp", &buf, &len))
+ {
+ if (len != 8)
+ {
+ PyErr_SetString(PyExc_ValueError, "8-character string expected");
+ return NULL;
+ }
+ return TimeStamp_FromString(buf);
}
PyErr_Clear();
if (!PyArg_ParseTuple(args, "iii|iid", &y, &mo, &d, &h, &m, &sec))
- return NULL;
+ return NULL;
return TimeStamp_FromDate(y, mo, d, h, m, sec);
}
-static PyMethodDef TimeStampModule_functions[] = {
- {"TimeStamp", TimeStamp_TimeStamp, METH_VARARGS},
- {NULL, NULL},
+static PyMethodDef TimeStampModule_functions[] =
+{
+ {"TimeStamp", TimeStamp_TimeStamp, METH_VARARGS},
+ {NULL, NULL},
};
#ifdef PY3K
-static struct PyModuleDef moduledef = {
- PyModuleDef_HEAD_INIT,
- "_timestamp", /* m_name */
- TimeStampModule_doc, /* m_doc */
- -1, /* m_size */
- TimeStampModule_functions, /* m_methods */
- NULL, /* m_reload */
- NULL, /* m_traverse */
- NULL, /* m_clear */
- NULL, /* m_free */
- };
+static struct PyModuleDef moduledef =
+{
+ PyModuleDef_HEAD_INIT,
+ "_timestamp", /* m_name */
+ TimeStampModule_doc, /* m_doc */
+ -1, /* m_size */
+ TimeStampModule_functions, /* m_methods */
+ NULL, /* m_reload */
+ NULL, /* m_traverse */
+ NULL, /* m_clear */
+ NULL, /* m_free */
+};
#endif
-void
-init_timestamp(void)
+static PyObject*
+module_init(void)
{
- PyObject *m;
+ PyObject *module;
if (TimeStamp_init_gmoff() < 0)
- return;
+ return;
#ifdef PY3K
- m = PyModule_Create(&moduledef);
+ module = PyModule_Create(&moduledef);
#else
- m = Py_InitModule4("_timestamp", TimeStampModule_functions,
- TimeStampModule_doc, NULL, PYTHON_API_VERSION);
+ module = Py_InitModule4("_timestamp", TimeStampModule_functions,
+ TimeStampModule_doc, NULL, PYTHON_API_VERSION);
#endif
- if (m == NULL)
- return;
+ if (module == NULL)
+ return NULL;
#ifdef PY3K
- ((PyObject*)&TimeStamp_type)->ob_type = &PyType_Type;
+ ((PyObject*)&TimeStamp_type)->ob_type = &PyType_Type;
#else
TimeStamp_type.ob_type = &PyType_Type;
#endif
TimeStamp_type.tp_getattro = PyObject_GenericGetAttr;
+
+ return module;
}
+
+#ifdef PY3K
+PyMODINIT_FUNC PyInit__timestamp(void)
+{
+ return module_init();
+}
+#else
+PyMODINIT_FUNC init_timestamp(void)
+{
+ module_init();
+}
+#endif
Modified: persistent/trunk/persistent/cPersistence.c
===================================================================
--- persistent/trunk/persistent/cPersistence.c 2012-12-14 00:21:12 UTC (rev 128631)
+++ persistent/trunk/persistent/cPersistence.c 2012-12-14 00:21:15 UTC (rev 128632)
@@ -19,8 +19,9 @@
#include "cPersistence.h"
#include "structmember.h"
-struct ccobject_head_struct {
- CACHE_HEAD
+struct ccobject_head_struct
+{
+ CACHE_HEAD
};
/* These two objects are initialized when the module is loaded */
@@ -66,9 +67,9 @@
static void
fatal_1350(cPersistentObject *self, const char *caller, const char *detail)
{
- char buf[1000];
+ char buf[1000];
- PyOS_snprintf(buf, sizeof(buf),
+ PyOS_snprintf(buf, sizeof(buf),
"cPersistence.c %s(): object at %p with type %.200s\n"
"%s.\n"
"The only known cause is multiple threads trying to ghost and\n"
@@ -76,7 +77,7 @@
"That's not legal, but ZODB can't stop it.\n"
"See Collector #1350.\n",
caller, self, Py_TYPE(self)->tp_name, detail);
- Py_FatalError(buf);
+ Py_FatalError(buf);
}
#endif
@@ -88,48 +89,48 @@
static int
unghostify(cPersistentObject *self)
{
- if (self->state < 0 && self->jar)
+ if (self->state < 0 && self->jar)
{
- PyObject *r;
+ PyObject *r;
- /* Is it ever possible to not have a cache? */
- if (self->cache)
+ /* Is it ever possible to not have a cache? */
+ if (self->cache)
{
- /* Create a node in the ring for this unghostified object. */
- self->cache->non_ghost_count++;
- self->cache->total_estimated_size +=
- _estimated_size_in_bytes(self->estimated_size);
- ring_add(&self->cache->ring_home, &self->ring);
- Py_INCREF(self);
+ /* Create a node in the ring for this unghostified object. */
+ self->cache->non_ghost_count++;
+ self->cache->total_estimated_size +=
+ _estimated_size_in_bytes(self->estimated_size);
+ ring_add(&self->cache->ring_home, &self->ring);
+ Py_INCREF(self);
}
- /* set state to CHANGED while setstate() call is in progress
- to prevent a recursive call to _PyPersist_Load().
- */
- self->state = cPersistent_CHANGED_STATE;
- /* Call the object's __setstate__() */
- r = PyObject_CallMethod(self->jar, "setstate", "O", (PyObject *)self);
- if (r == NULL)
+ /* set state to CHANGED while setstate() call is in progress
+ to prevent a recursive call to _PyPersist_Load().
+ */
+ self->state = cPersistent_CHANGED_STATE;
+ /* Call the object's __setstate__() */
+ r = PyObject_CallMethod(self->jar, "setstate", "O", (PyObject *)self);
+ if (r == NULL)
{
- ghostify(self);
- return -1;
+ ghostify(self);
+ return -1;
}
- self->state = cPersistent_UPTODATE_STATE;
- Py_DECREF(r);
- if (self->cache && self->ring.r_next == NULL)
+ self->state = cPersistent_UPTODATE_STATE;
+ Py_DECREF(r);
+ if (self->cache && self->ring.r_next == NULL)
{
#ifdef Py_DEBUG
- fatal_1350(self, "unghostify",
+ fatal_1350(self, "unghostify",
"is not in the cache despite that we just "
"unghostified it");
#else
- PyErr_Format(PyExc_SystemError, "object at %p with type "
+ PyErr_Format(PyExc_SystemError, "object at %p with type "
"%.200s not in the cache despite that we just "
"unghostified it", self, Py_TYPE(self)->tp_name);
- return -1;
+ return -1;
#endif
}
}
- return 1;
+ return 1;
}
/****************************************************************************/
@@ -139,148 +140,148 @@
static void
accessed(cPersistentObject *self)
{
- /* Do nothing unless the object is in a cache and not a ghost. */
- if (self->cache && self->state >= 0 && self->ring.r_next)
- ring_move_to_head(&self->cache->ring_home, &self->ring);
+ /* Do nothing unless the object is in a cache and not a ghost. */
+ if (self->cache && self->state >= 0 && self->ring.r_next)
+ ring_move_to_head(&self->cache->ring_home, &self->ring);
}
static void
ghostify(cPersistentObject *self)
{
- PyObject **dictptr;
+ PyObject **dictptr;
- /* are we already a ghost? */
- if (self->state == cPersistent_GHOST_STATE)
- return;
+ /* are we already a ghost? */
+ if (self->state == cPersistent_GHOST_STATE)
+ return;
- /* Is it ever possible to not have a cache? */
- if (self->cache == NULL)
+ /* Is it ever possible to not have a cache? */
+ if (self->cache == NULL)
{
- self->state = cPersistent_GHOST_STATE;
- return;
+ self->state = cPersistent_GHOST_STATE;
+ return;
}
- if (self->ring.r_next == NULL)
+ if (self->ring.r_next == NULL)
{
- /* There's no way to raise an error in this routine. */
+ /* There's no way to raise an error in this routine. */
#ifdef Py_DEBUG
- fatal_1350(self, "ghostify", "claims to be in a cache but isn't");
+ fatal_1350(self, "ghostify", "claims to be in a cache but isn't");
#else
- return;
+ return;
#endif
}
- /* If we're ghostifying an object, we better have some non-ghosts. */
- assert(self->cache->non_ghost_count > 0);
- self->cache->non_ghost_count--;
- self->cache->total_estimated_size -=
- _estimated_size_in_bytes(self->estimated_size);
- ring_del(&self->ring);
- self->state = cPersistent_GHOST_STATE;
- dictptr = _PyObject_GetDictPtr((PyObject *)self);
- if (dictptr && *dictptr)
+ /* If we're ghostifying an object, we better have some non-ghosts. */
+ assert(self->cache->non_ghost_count > 0);
+ self->cache->non_ghost_count--;
+ self->cache->total_estimated_size -=
+ _estimated_size_in_bytes(self->estimated_size);
+ ring_del(&self->ring);
+ self->state = cPersistent_GHOST_STATE;
+ dictptr = _PyObject_GetDictPtr((PyObject *)self);
+ if (dictptr && *dictptr)
{
- Py_DECREF(*dictptr);
- *dictptr = NULL;
+ Py_DECREF(*dictptr);
+ *dictptr = NULL;
}
- /* We remove the reference to the just ghosted object that the ring
- * holds. Note that the dictionary of oids->objects has an uncounted
- * reference, so if the ring's reference was the only one, this frees
- * the ghost object. Note further that the object's dealloc knows to
- * inform the dictionary that it is going away.
- */
- Py_DECREF(self);
+ /* We remove the reference to the just ghosted object that the ring
+ * holds. Note that the dictionary of oids->objects has an uncounted
+ * reference, so if the ring's reference was the only one, this frees
+ * the ghost object. Note further that the object's dealloc knows to
+ * inform the dictionary that it is going away.
+ */
+ Py_DECREF(self);
}
static int
changed(cPersistentObject *self)
{
- if ((self->state == cPersistent_UPTODATE_STATE ||
- self->state == cPersistent_STICKY_STATE)
- && self->jar)
+ if ((self->state == cPersistent_UPTODATE_STATE ||
+ self->state == cPersistent_STICKY_STATE)
+ && self->jar)
{
- PyObject *meth, *arg, *result;
- static PyObject *s_register;
+ PyObject *meth, *arg, *result;
+ static PyObject *s_register;
- if (s_register == NULL)
- s_register = INTERN("register");
- meth = PyObject_GetAttr((PyObject *)self->jar, s_register);
- if (meth == NULL)
- return -1;
- arg = PyTuple_New(1);
- if (arg == NULL)
+ if (s_register == NULL)
+ s_register = INTERN("register");
+ meth = PyObject_GetAttr((PyObject *)self->jar, s_register);
+ if (meth == NULL)
+ return -1;
+ arg = PyTuple_New(1);
+ if (arg == NULL)
{
- Py_DECREF(meth);
- return -1;
+ Py_DECREF(meth);
+ return -1;
}
- Py_INCREF(self);
- PyTuple_SET_ITEM(arg, 0, (PyObject *)self);
- result = PyEval_CallObject(meth, arg);
- Py_DECREF(arg);
- Py_DECREF(meth);
- if (result == NULL)
- return -1;
- Py_DECREF(result);
+ Py_INCREF(self);
+ PyTuple_SET_ITEM(arg, 0, (PyObject *)self);
+ result = PyEval_CallObject(meth, arg);
+ Py_DECREF(arg);
+ Py_DECREF(meth);
+ if (result == NULL)
+ return -1;
+ Py_DECREF(result);
- self->state = cPersistent_CHANGED_STATE;
+ self->state = cPersistent_CHANGED_STATE;
}
- return 0;
+ return 0;
}
static int
readCurrent(cPersistentObject *self)
{
- if ((self->state == cPersistent_UPTODATE_STATE ||
- self->state == cPersistent_STICKY_STATE)
- && self->jar && self->oid)
+ if ((self->state == cPersistent_UPTODATE_STATE ||
+ self->state == cPersistent_STICKY_STATE)
+ && self->jar && self->oid)
{
- static PyObject *s_readCurrent=NULL;
- PyObject *r;
+ static PyObject *s_readCurrent=NULL;
+ PyObject *r;
- if (s_readCurrent == NULL)
- s_readCurrent = INTERN("readCurrent");
+ if (s_readCurrent == NULL)
+ s_readCurrent = INTERN("readCurrent");
- r = PyObject_CallMethodObjArgs(self->jar, s_readCurrent, self, NULL);
- if (r == NULL)
- return -1;
+ r = PyObject_CallMethodObjArgs(self->jar, s_readCurrent, self, NULL);
+ if (r == NULL)
+ return -1;
- Py_DECREF(r);
+ Py_DECREF(r);
}
- return 0;
+ return 0;
}
static PyObject *
Per__p_deactivate(cPersistentObject *self)
{
- if (self->state == cPersistent_UPTODATE_STATE && self->jar)
+ if (self->state == cPersistent_UPTODATE_STATE && self->jar)
{
- PyObject **dictptr = _PyObject_GetDictPtr((PyObject *)self);
- if (dictptr && *dictptr)
+ PyObject **dictptr = _PyObject_GetDictPtr((PyObject *)self);
+ if (dictptr && *dictptr)
{
- Py_DECREF(*dictptr);
- *dictptr = NULL;
+ Py_DECREF(*dictptr);
+ *dictptr = NULL;
}
- /* Note that we need to set to ghost state unless we are
- called directly. Methods that override this need to
- do the same! */
- ghostify(self);
+ /* Note that we need to set to ghost state unless we are
+ called directly. Methods that override this need to
+ do the same! */
+ ghostify(self);
}
- Py_INCREF(Py_None);
- return Py_None;
+ Py_INCREF(Py_None);
+ return Py_None;
}
static PyObject *
Per__p_activate(cPersistentObject *self)
{
- if (unghostify(self) < 0)
- return NULL;
+ if (unghostify(self) < 0)
+ return NULL;
- Py_INCREF(Py_None);
- return Py_None;
+ Py_INCREF(Py_None);
+ return Py_None;
}
static int Per_set_changed(cPersistentObject *self, PyObject *v);
@@ -288,84 +289,84 @@
static PyObject *
Per__p_invalidate(cPersistentObject *self)
{
- signed char old_state = self->state;
+ signed char old_state = self->state;
- if (old_state != cPersistent_GHOST_STATE)
+ if (old_state != cPersistent_GHOST_STATE)
{
- if (Per_set_changed(self, NULL) < 0)
- return NULL;
- ghostify(self);
+ if (Per_set_changed(self, NULL) < 0)
+ return NULL;
+ ghostify(self);
}
- Py_INCREF(Py_None);
- return Py_None;
+ Py_INCREF(Py_None);
+ return Py_None;
}
static PyObject *
pickle_slotnames(PyTypeObject *cls)
{
- PyObject *slotnames;
+ PyObject *slotnames;
- slotnames = PyDict_GetItem(cls->tp_dict, py___slotnames__);
- if (slotnames)
+ slotnames = PyDict_GetItem(cls->tp_dict, py___slotnames__);
+ if (slotnames)
{
- int n = PyObject_Not(slotnames);
- if (n < 0)
- return NULL;
- if (n)
- slotnames = Py_None;
-
- Py_INCREF(slotnames);
- return slotnames;
+ int n = PyObject_Not(slotnames);
+ if (n < 0)
+ return NULL;
+ if (n)
+ slotnames = Py_None;
+
+ Py_INCREF(slotnames);
+ return slotnames;
}
- slotnames = PyObject_CallFunctionObjArgs(copy_reg_slotnames,
- (PyObject*)cls, NULL);
- if (slotnames && !(slotnames == Py_None || PyList_Check(slotnames)))
+ slotnames = PyObject_CallFunctionObjArgs(copy_reg_slotnames,
+ (PyObject*)cls, NULL);
+ if (slotnames && !(slotnames == Py_None || PyList_Check(slotnames)))
{
- PyErr_SetString(PyExc_TypeError,
- "copy_reg._slotnames didn't return a list or None");
- Py_DECREF(slotnames);
- return NULL;
+ PyErr_SetString(PyExc_TypeError,
+ "copy_reg._slotnames didn't return a list or None");
+ Py_DECREF(slotnames);
+ return NULL;
}
- return slotnames;
+ return slotnames;
}
static PyObject *
pickle_copy_dict(PyObject *state)
{
- PyObject *copy, *key, *value;
- char *ckey;
- Py_ssize_t pos = 0;
+ PyObject *copy, *key, *value;
+ char *ckey;
+ Py_ssize_t pos = 0;
- copy = PyDict_New();
- if (!copy)
- return NULL;
+ copy = PyDict_New();
+ if (!copy)
+ return NULL;
- if (!state)
- return copy;
+ if (!state)
+ return copy;
- while (PyDict_Next(state, &pos, &key, &value))
+ while (PyDict_Next(state, &pos, &key, &value))
{
- if (key && PyBytes_Check(key))
+ if (key && PyBytes_Check(key))
{
- ckey = PyBytes_AS_STRING(key);
- if (*ckey == '_' &&
- (ckey[1] == 'v' || ckey[1] == 'p') &&
- ckey[2] == '_')
- /* skip volatile and persistent */
- continue;
+ ckey = PyBytes_AS_STRING(key);
+ if (*ckey == '_' &&
+ (ckey[1] == 'v' || ckey[1] == 'p') &&
+ ckey[2] == '_')
+ /* skip volatile and persistent */
+ continue;
}
- if (PyObject_SetItem(copy, key, value) < 0)
- goto err;
+ if (PyObject_SetItem(copy, key, value) < 0)
+ goto err;
}
- return copy;
- err:
- Py_DECREF(copy);
- return NULL;
+ return copy;
+err:
+ Py_DECREF(copy);
+ return NULL;
}
@@ -388,90 +389,90 @@
static PyObject *
pickle___getstate__(PyObject *self)
{
- PyObject *slotnames=NULL, *slots=NULL, *state=NULL;
- PyObject **dictp;
- int n=0;
+ PyObject *slotnames=NULL, *slots=NULL, *state=NULL;
+ PyObject **dictp;
+ int n=0;
- slotnames = pickle_slotnames(Py_TYPE(self));
- if (!slotnames)
- return NULL;
+ slotnames = pickle_slotnames(Py_TYPE(self));
+ if (!slotnames)
+ return NULL;
- dictp = _PyObject_GetDictPtr(self);
- if (dictp)
- state = pickle_copy_dict(*dictp);
- else
+ dictp = _PyObject_GetDictPtr(self);
+ if (dictp)
+ state = pickle_copy_dict(*dictp);
+ else
{
- state = Py_None;
- Py_INCREF(state);
+ state = Py_None;
+ Py_INCREF(state);
}
- if (slotnames != Py_None)
+ if (slotnames != Py_None)
{
- int i;
+ int i;
- slots = PyDict_New();
- if (!slots)
- goto end;
+ slots = PyDict_New();
+ if (!slots)
+ goto end;
- for (i = 0; i < PyList_GET_SIZE(slotnames); i++)
+ for (i = 0; i < PyList_GET_SIZE(slotnames); i++)
{
- PyObject *name, *value;
- char *cname;
+ PyObject *name, *value;
+ char *cname;
- name = PyList_GET_ITEM(slotnames, i);
- if (PyBytes_Check(name))
+ name = PyList_GET_ITEM(slotnames, i);
+ if (PyBytes_Check(name))
{
- cname = PyBytes_AS_STRING(name);
- if (*cname == '_' &&
- (cname[1] == 'v' || cname[1] == 'p') &&
- cname[2] == '_')
- /* skip volatile and persistent */
- continue;
+ cname = PyBytes_AS_STRING(name);
+ if (*cname == '_' &&
+ (cname[1] == 'v' || cname[1] == 'p') &&
+ cname[2] == '_')
+ /* skip volatile and persistent */
+ continue;
}
- /* Unclear: Will this go through our getattr hook? */
- value = PyObject_GetAttr(self, name);
- if (value == NULL)
- PyErr_Clear();
- else
+ /* Unclear: Will this go through our getattr hook? */
+ value = PyObject_GetAttr(self, name);
+ if (value == NULL)
+ PyErr_Clear();
+ else
{
- int err = PyDict_SetItem(slots, name, value);
- Py_DECREF(value);
- if (err < 0)
- goto end;
- n++;
+ int err = PyDict_SetItem(slots, name, value);
+ Py_DECREF(value);
+ if (err < 0)
+ goto end;
+ n++;
}
}
}
- if (n)
- state = Py_BuildValue("(NO)", state, slots);
+ if (n)
+ state = Py_BuildValue("(NO)", state, slots);
- end:
- Py_XDECREF(slotnames);
- Py_XDECREF(slots);
+end:
+ Py_XDECREF(slotnames);
+ Py_XDECREF(slots);
- return state;
+ return state;
}
static int
pickle_setattrs_from_dict(PyObject *self, PyObject *dict)
{
- PyObject *key, *value;
- Py_ssize_t pos = 0;
+ PyObject *key, *value;
+ Py_ssize_t pos = 0;
- if (!PyDict_Check(dict))
+ if (!PyDict_Check(dict))
{
- PyErr_SetString(PyExc_TypeError, "Expected dictionary");
- return -1;
+ PyErr_SetString(PyExc_TypeError, "Expected dictionary");
+ return -1;
}
- while (PyDict_Next(dict, &pos, &key, &value))
+ while (PyDict_Next(dict, &pos, &key, &value))
{
- if (PyObject_SetAttr(self, key, value) < 0)
- return -1;
+ if (PyObject_SetAttr(self, key, value) < 0)
+ return -1;
}
- return 0;
+ return 0;
}
static char pickle___setstate__doc[] =
@@ -496,44 +497,44 @@
static PyObject *
pickle___setstate__(PyObject *self, PyObject *state)
{
- PyObject *slots=NULL;
+ PyObject *slots=NULL;
- if (PyTuple_Check(state))
+ if (PyTuple_Check(state))
{
- if (!PyArg_ParseTuple(state, "OO:__setstate__", &state, &slots))
- return NULL;
+ if (!PyArg_ParseTuple(state, "OO:__setstate__", &state, &slots))
+ return NULL;
}
- if (state != Py_None)
+ if (state != Py_None)
{
- PyObject **dict;
+ PyObject **dict;
- dict = _PyObject_GetDictPtr(self);
-
- if (!dict)
+ dict = _PyObject_GetDictPtr(self);
+
+ if (!dict)
{
- PyErr_SetString(PyExc_TypeError,
- "this object has no instance dictionary");
- return NULL;
+ PyErr_SetString(PyExc_TypeError,
+ "this object has no instance dictionary");
+ return NULL;
}
- if (!*dict)
+ if (!*dict)
{
- *dict = PyDict_New();
- if (!*dict)
- return NULL;
+ *dict = PyDict_New();
+ if (!*dict)
+ return NULL;
}
- PyDict_Clear(*dict);
- if (PyDict_Update(*dict, state) < 0)
- return NULL;
+ PyDict_Clear(*dict);
+ if (PyDict_Update(*dict, state) < 0)
+ return NULL;
}
- if (slots && pickle_setattrs_from_dict(self, slots) < 0)
- return NULL;
+ if (slots && pickle_setattrs_from_dict(self, slots) < 0)
+ return NULL;
- Py_INCREF(Py_None);
- return Py_None;
+ Py_INCREF(Py_None);
+ return Py_None;
}
static char pickle___reduce__doc[] =
@@ -543,49 +544,49 @@
static PyObject *
pickle___reduce__(PyObject *self)
{
- PyObject *args=NULL, *bargs=NULL, *state=NULL, *getnewargs=NULL;
- int l, i;
+ PyObject *args=NULL, *bargs=NULL, *state=NULL, *getnewargs=NULL;
+ int l, i;
- getnewargs = PyObject_GetAttr(self, py___getnewargs__);
- if (getnewargs)
+ getnewargs = PyObject_GetAttr(self, py___getnewargs__);
+ if (getnewargs)
{
- bargs = PyObject_CallFunctionObjArgs(getnewargs, NULL);
- Py_DECREF(getnewargs);
- if (!bargs)
- return NULL;
- l = PyTuple_Size(bargs);
- if (l < 0)
- goto end;
+ bargs = PyObject_CallFunctionObjArgs(getnewargs, NULL);
+ Py_DECREF(getnewargs);
+ if (!bargs)
+ return NULL;
+ l = PyTuple_Size(bargs);
+ if (l < 0)
+ goto end;
}
- else
+ else
{
- PyErr_Clear();
- l = 0;
+ PyErr_Clear();
+ l = 0;
}
- args = PyTuple_New(l+1);
- if (args == NULL)
- goto end;
+ args = PyTuple_New(l+1);
+ if (args == NULL)
+ goto end;
- Py_INCREF(Py_TYPE(self));
- PyTuple_SET_ITEM(args, 0, (PyObject*)(Py_TYPE(self)));
- for (i = 0; i < l; i++)
+ Py_INCREF(Py_TYPE(self));
+ PyTuple_SET_ITEM(args, 0, (PyObject*)(Py_TYPE(self)));
+ for (i = 0; i < l; i++)
{
- Py_INCREF(PyTuple_GET_ITEM(bargs, i));
- PyTuple_SET_ITEM(args, i+1, PyTuple_GET_ITEM(bargs, i));
+ Py_INCREF(PyTuple_GET_ITEM(bargs, i));
+ PyTuple_SET_ITEM(args, i+1, PyTuple_GET_ITEM(bargs, i));
}
- state = PyObject_CallMethodObjArgs(self, py___getstate__, NULL);
- if (!state)
- goto end;
+ state = PyObject_CallMethodObjArgs(self, py___getstate__, NULL);
+ if (!state)
+ goto end;
- state = Py_BuildValue("(OON)", __newobj__, args, state);
+ state = Py_BuildValue("(OON)", __newobj__, args, state);
- end:
- Py_XDECREF(bargs);
- Py_XDECREF(args);
+end:
+ Py_XDECREF(bargs);
+ Py_XDECREF(args);
- return state;
+ return state;
}
@@ -602,13 +603,13 @@
static PyObject *
Per__getstate__(cPersistentObject *self)
{
- /* TODO: Should it be an error to call __getstate__() on a ghost? */
- if (unghostify(self) < 0)
- return NULL;
+ /* TODO: Should it be an error to call __getstate__() on a ghost? */
+ if (unghostify(self) < 0)
+ return NULL;
- /* TODO: should we increment stickyness? Tim doesn't understand that
- question. S*/
- return pickle___getstate__((PyObject*)self);
+ /* TODO: should we increment stickyness? Tim doesn't understand that
+ question. S*/
+ return pickle___getstate__((PyObject*)self);
}
/* The Persistent base type provides a traverse function, but not a
@@ -626,48 +627,48 @@
static void
Per_dealloc(cPersistentObject *self)
{
- if (self->state >= 0)
+ if (self->state >= 0)
{
- /* If the cache has been cleared, then a non-ghost object
- isn't in the ring any longer.
- */
- if (self->ring.r_next != NULL)
+ /* If the cache has been cleared, then a non-ghost object
+ isn't in the ring any longer.
+ */
+ if (self->ring.r_next != NULL)
{
- /* if we're ghostifying an object, we better have some non-ghosts */
- assert(self->cache->non_ghost_count > 0);
- self->cache->non_ghost_count--;
- self->cache->total_estimated_size -=
- _estimated_size_in_bytes(self->estimated_size);
- ring_del(&self->ring);
+ /* if we're ghostifying an object, we better have some non-ghosts */
+ assert(self->cache->non_ghost_count > 0);
+ self->cache->non_ghost_count--;
+ self->cache->total_estimated_size -=
+ _estimated_size_in_bytes(self->estimated_size);
+ ring_del(&self->ring);
}
}
- if (self->cache)
- cPersistenceCAPI->percachedel(self->cache, self->oid);
- Py_XDECREF(self->cache);
- Py_XDECREF(self->jar);
- Py_XDECREF(self->oid);
- Py_TYPE(self)->tp_free(self);
+ if (self->cache)
+ cPersistenceCAPI->percachedel(self->cache, self->oid);
+ Py_XDECREF(self->cache);
+ Py_XDECREF(self->jar);
+ Py_XDECREF(self->oid);
+ Py_TYPE(self)->tp_free(self);
}
static int
Per_traverse(cPersistentObject *self, visitproc visit, void *arg)
{
- int err;
+ int err;
#define VISIT(SLOT) \
- if (SLOT) { \
- err = visit((PyObject *)(SLOT), arg); \
- if (err) \
- return err; \
- }
+ if (SLOT) { \
+ err = visit((PyObject *)(SLOT), arg); \
+ if (err) \
+ return err; \
+ }
- VISIT(self->jar);
- VISIT(self->oid);
- VISIT(self->cache);
+ VISIT(self->jar);
+ VISIT(self->oid);
+ VISIT(self->cache);
#undef VISIT
- return 0;
+ return 0;
}
/* convert_name() returns a new reference to a string name
@@ -681,20 +682,20 @@
/* The Unicode to string conversion is done here because the
existing tp_setattro slots expect a string object as name
and we wouldn't want to break those. */
- if (PyUnicode_Check(name))
+ if (PyUnicode_Check(name))
{
- name = PyUnicode_AsEncodedString(name, NULL, NULL);
+ name = PyUnicode_AsEncodedString(name, NULL, NULL);
}
- else
+ else
#endif
- if (!PyBytes_Check(name))
- {
- PyErr_SetString(PyExc_TypeError, "attribute name must be a string");
- return NULL;
- }
- else
- Py_INCREF(name);
- return name;
+ if (!PyBytes_Check(name))
+ {
+ PyErr_SetString(PyExc_TypeError, "attribute name must be a string");
+ return NULL;
+ }
+ else
+ Py_INCREF(name);
+ return name;
}
/* Returns true if the object requires unghostification.
@@ -711,92 +712,94 @@
static int
unghost_getattr(const char *s)
{
- if (*s++ != '_')
- return 1;
- if (*s == 'p')
+ if (*s++ != '_')
+ return 1;
+ if (*s == 'p')
{
- s++;
- if (*s == '_')
- return 0; /* _p_ */
- else
- return 1;
+ s++;
+ if (*s == '_')
+ return 0; /* _p_ */
+ else
+ return 1;
}
- else if (*s == '_')
+ else if (*s == '_')
{
- s++;
- switch (*s)
+ s++;
+ switch (*s)
{
- case 'c':
- return strcmp(s, "class__");
- case 'd':
- s++;
- if (!strcmp(s, "el__"))
- return 0; /* __del__ */
- if (!strcmp(s, "ict__"))
- return 0; /* __dict__ */
- return 1;
- case 'o':
- return strcmp(s, "of__");
- case 's':
- return strcmp(s, "setstate__");
- default:
- return 1;
+ case 'c':
+ return strcmp(s, "class__");
+ case 'd':
+ s++;
+ if (!strcmp(s, "el__"))
+ return 0; /* __del__ */
+ if (!strcmp(s, "ict__"))
+ return 0; /* __dict__ */
+ return 1;
+ case 'o':
+ return strcmp(s, "of__");
+ case 's':
+ return strcmp(s, "setstate__");
+ default:
+ return 1;
}
}
- return 1;
+ return 1;
}
static PyObject*
Per_getattro(cPersistentObject *self, PyObject *name)
{
- PyObject *result = NULL; /* guilty until proved innocent */
- char *s;
+ PyObject *result = NULL; /* guilty until proved innocent */
+ PyObject *converted;
+ char *s;
- name = convert_name(name);
- if (!name)
- goto Done;
- s = PyBytes_AS_STRING(name);
+ converted = convert_name(name);
+ if (!converted)
+ goto Done;
+ s = PyBytes_AS_STRING(converted);
- if (unghost_getattr(s))
+ if (unghost_getattr(s))
{
- if (unghostify(self) < 0)
- goto Done;
- accessed(self);
+ if (unghostify(self) < 0)
+ goto Done;
+ accessed(self);
}
- result = PyObject_GenericGetAttr((PyObject *)self, name);
+ result = PyObject_GenericGetAttr((PyObject *)self, name);
- Done:
- Py_XDECREF(name);
- return result;
+Done:
+ Py_XDECREF(name);
+ return result;
}
/* Exposed as _p_getattr method. Test whether base getattr should be used */
static PyObject *
Per__p_getattr(cPersistentObject *self, PyObject *name)
{
- PyObject *result = NULL; /* guilty until proved innocent */
- char *s;
+ PyObject *result = NULL; /* guilty until proved innocent */
+ PyObject *converted;
+ char *s;
- name = convert_name(name);
- if (!name)
- goto Done;
- s = PyBytes_AS_STRING(name);
+ converted = convert_name(name);
+ if (!converted)
+ goto Done;
+ s = PyBytes_AS_STRING(converted);
- if (*s != '_' || unghost_getattr(s))
+ if (*s != '_' || unghost_getattr(s))
{
- if (unghostify(self) < 0)
- goto Done;
- accessed(self);
- result = Py_False;
+ if (unghostify(self) < 0)
+ goto Done;
+ accessed(self);
+ result = Py_False;
}
- else
- result = Py_True;
+ else
+ result = Py_True;
- Py_INCREF(result);
+ Py_INCREF(result);
- Done:
- Py_XDECREF(name);
- return result;
+Done:
+ Py_XDECREF(name);
+ return result;
}
/*
@@ -806,61 +809,63 @@
static int
Per_setattro(cPersistentObject *self, PyObject *name, PyObject *v)
{
- int result = -1; /* guilty until proved innocent */
- char *s;
+ int result = -1; /* guilty until proved innocent */
+ PyObject *converted;
+ char *s;
- name = convert_name(name);
- if (!name)
- goto Done;
- s = PyBytes_AS_STRING(name);
+ converted = convert_name(name);
+ if (!converted)
+ goto Done;
+ s = PyBytes_AS_STRING(converted);
- if (strncmp(s, "_p_", 3) != 0)
+ if (strncmp(s, "_p_", 3) != 0)
{
- if (unghostify(self) < 0)
- goto Done;
- accessed(self);
- if (strncmp(s, "_v_", 3) != 0
- && self->state != cPersistent_CHANGED_STATE)
- {
- if (changed(self) < 0)
+ if (unghostify(self) < 0)
goto Done;
- }
+ accessed(self);
+ if (strncmp(s, "_v_", 3) != 0
+ && self->state != cPersistent_CHANGED_STATE)
+ {
+ if (changed(self) < 0)
+ goto Done;
+ }
}
- result = PyObject_GenericSetAttr((PyObject *)self, name, v);
+ result = PyObject_GenericSetAttr((PyObject *)self, name, v);
- Done:
- Py_XDECREF(name);
- return result;
+Done:
+ Py_XDECREF(name);
+ return result;
}
static int
Per_p_set_or_delattro(cPersistentObject *self, PyObject *name, PyObject *v)
{
- int result = -1; /* guilty until proved innocent */
- char *s;
+ int result = -1; /* guilty until proved innocent */
+ PyObject *converted;
+ char *s;
- name = convert_name(name);
- if (!name)
- goto Done;
- s = PyBytes_AS_STRING(name);
+ converted = convert_name(name);
+ if (!converted)
+ goto Done;
+ s = PyBytes_AS_STRING(converted);
- if (strncmp(s, "_p_", 3))
+ if (strncmp(s, "_p_", 3))
{
- if (unghostify(self) < 0)
- goto Done;
- accessed(self);
+ if (unghostify(self) < 0)
+ goto Done;
+ accessed(self);
- result = 0;
+ result = 0;
}
- else
+ else
{
- if (PyObject_GenericSetAttr((PyObject *)self, name, v) < 0)
- goto Done;
- result = 1;
+ if (PyObject_GenericSetAttr((PyObject *)self, name, v) < 0)
+ goto Done;
+ result = 1;
}
- Done:
+Done:
Py_XDECREF(name);
return result;
}
@@ -868,335 +873,340 @@
static PyObject *
Per__p_setattr(cPersistentObject *self, PyObject *args)
{
- PyObject *name, *v, *result;
- int r;
+ PyObject *name, *v, *result;
+ int r;
- if (!PyArg_ParseTuple(args, "OO:_p_setattr", &name, &v))
- return NULL;
+ if (!PyArg_ParseTuple(args, "OO:_p_setattr", &name, &v))
+ return NULL;
- r = Per_p_set_or_delattro(self, name, v);
- if (r < 0)
- return NULL;
+ r = Per_p_set_or_delattro(self, name, v);
+ if (r < 0)
+ return NULL;
- result = r ? Py_True : Py_False;
- Py_INCREF(result);
- return result;
+ result = r ? Py_True : Py_False;
+ Py_INCREF(result);
+ return result;
}
static PyObject *
Per__p_delattr(cPersistentObject *self, PyObject *name)
{
- int r;
- PyObject *result;
+ int r;
+ PyObject *result;
- r = Per_p_set_or_delattro(self, name, NULL);
- if (r < 0)
- return NULL;
+ r = Per_p_set_or_delattro(self, name, NULL);
+ if (r < 0)
+ return NULL;
- result = r ? Py_True : Py_False;
- Py_INCREF(result);
- return result;
+ result = r ? Py_True : Py_False;
+ Py_INCREF(result);
+ return result;
}
static PyObject *
Per_get_changed(cPersistentObject *self)
{
- if (self->state < 0)
+ if (self->state < 0)
{
- Py_INCREF(Py_None);
- return Py_None;
+ Py_INCREF(Py_None);
+ return Py_None;
}
- return PyBool_FromLong(self->state == cPersistent_CHANGED_STATE);
+ return PyBool_FromLong(self->state == cPersistent_CHANGED_STATE);
}
static int
Per_set_changed(cPersistentObject *self, PyObject *v)
{
- int deactivate = 0;
- int true;
+ int deactivate = 0;
+ int true;
- if (!v)
+ if (!v)
{
- /* delattr is used to invalidate an object even if it has changed. */
- if (self->state != cPersistent_GHOST_STATE)
- self->state = cPersistent_UPTODATE_STATE;
- deactivate = 1;
+ /* delattr is used to invalidate an object even if it has changed. */
+ if (self->state != cPersistent_GHOST_STATE)
+ self->state = cPersistent_UPTODATE_STATE;
+ deactivate = 1;
}
- else if (v == Py_None)
- deactivate = 1;
+ else if (v == Py_None)
+ deactivate = 1;
- if (deactivate)
+ if (deactivate)
{
- PyObject *res, *meth;
- meth = PyObject_GetAttr((PyObject *)self, py__p_deactivate);
- if (meth == NULL)
- return -1;
- res = PyObject_CallObject(meth, NULL);
- if (res)
- Py_DECREF(res);
- else
+ PyObject *res, *meth;
+ meth = PyObject_GetAttr((PyObject *)self, py__p_deactivate);
+ if (meth == NULL)
+ return -1;
+ res = PyObject_CallObject(meth, NULL);
+ if (res)
+ Py_DECREF(res);
+ else
{
- /* an error occured in _p_deactivate().
+ /* an error occured in _p_deactivate().
- It's not clear what we should do here. The code is
- obviously ignoring the exception, but it shouldn't return
- 0 for a getattr and set an exception. The simplest change
- is to clear the exception, but that simply masks the
- error.
+ It's not clear what we should do here. The code is
+ obviously ignoring the exception, but it shouldn't return
+ 0 for a getattr and set an exception. The simplest change
+ is to clear the exception, but that simply masks the
+ error.
- This prints an error to stderr just like exceptions in
- __del__(). It would probably be better to log it but that
- would be painful from C.
- */
- PyErr_WriteUnraisable(meth);
+ This prints an error to stderr just like exceptions in
+ __del__(). It would probably be better to log it but that
+ would be painful from C.
+ */
+ PyErr_WriteUnraisable(meth);
}
- Py_DECREF(meth);
- return 0;
+ Py_DECREF(meth);
+ return 0;
}
- /* !deactivate. If passed a true argument, mark self as changed (starting
- * with ZODB 3.6, that includes activating the object if it's a ghost).
- * If passed a false argument, and the object isn't a ghost, set the
- * state as up-to-date.
- */
- true = PyObject_IsTrue(v);
- if (true == -1)
- return -1;
- if (true)
+ /* !deactivate. If passed a true argument, mark self as changed (starting
+ * with ZODB 3.6, that includes activating the object if it's a ghost).
+ * If passed a false argument, and the object isn't a ghost, set the
+ * state as up-to-date.
+ */
+ true = PyObject_IsTrue(v);
+ if (true == -1)
+ return -1;
+ if (true)
{
- if (self->state < 0)
+ if (self->state < 0)
{
- if (unghostify(self) < 0)
- return -1;
+ if (unghostify(self) < 0)
+ return -1;
}
- return changed(self);
+ return changed(self);
}
- /* We were passed a false, non-None argument. If we're not a ghost,
- * mark self as up-to-date.
- */
- if (self->state >= 0)
- self->state = cPersistent_UPTODATE_STATE;
- return 0;
+ /* We were passed a false, non-None argument. If we're not a ghost,
+ * mark self as up-to-date.
+ */
+ if (self->state >= 0)
+ self->state = cPersistent_UPTODATE_STATE;
+ return 0;
}
static PyObject *
Per_get_oid(cPersistentObject *self)
{
- PyObject *oid = self->oid ? self->oid : Py_None;
- Py_INCREF(oid);
- return oid;
+ PyObject *oid = self->oid ? self->oid : Py_None;
+ Py_INCREF(oid);
+ return oid;
}
static int
Per_set_oid(cPersistentObject *self, PyObject *v)
{
- if (self->cache)
+ if (self->cache)
{
- int result;
+ int result;
- if (v == NULL)
+ if (v == NULL)
{
- PyErr_SetString(PyExc_ValueError,
- "can't delete _p_oid of cached object");
- return -1;
+ PyErr_SetString(PyExc_ValueError,
+ "can't delete _p_oid of cached object");
+ return -1;
}
- result = PyObject_RichCompareBool(self->oid, v, Py_NE);
- if (result < 0)
- return -1;
- if (result)
+ result = PyObject_RichCompareBool(self->oid, v, Py_NE);
+ if (result < 0)
+ return -1;
+ if (result)
{
- PyErr_SetString(PyExc_ValueError,
- "can not change _p_oid of cached object");
- return -1;
+ PyErr_SetString(PyExc_ValueError,
+ "can not change _p_oid of cached object");
+ return -1;
}
}
- Py_XDECREF(self->oid);
- Py_XINCREF(v);
- self->oid = v;
- return 0;
+ Py_XDECREF(self->oid);
+ Py_XINCREF(v);
+ self->oid = v;
+ return 0;
}
static PyObject *
Per_get_jar(cPersistentObject *self)
{
- PyObject *jar = self->jar ? self->jar : Py_None;
- Py_INCREF(jar);
- return jar;
+ PyObject *jar = self->jar ? self->jar : Py_None;
+ Py_INCREF(jar);
+ return jar;
}
static int
Per_set_jar(cPersistentObject *self, PyObject *v)
{
- if (self->cache)
+ if (self->cache)
{
- int result;
+ int result;
- if (v == NULL)
+ if (v == NULL)
{
- PyErr_SetString(PyExc_ValueError,
- "can't delete _p_jar of cached object");
- return -1;
+ PyErr_SetString(PyExc_ValueError,
+ "can't delete _p_jar of cached object");
+ return -1;
}
- result = PyObject_RichCompareBool(self->jar, v, Py_NE);
- if (result < 0)
- return -1;
- if (result)
+ result = PyObject_RichCompareBool(self->jar, v, Py_NE);
+ if (result < 0)
+ return -1;
+ if (result)
{
- PyErr_SetString(PyExc_ValueError,
- "can not change _p_jar of cached object");
- return -1;
+ PyErr_SetString(PyExc_ValueError,
+ "can not change _p_jar of cached object");
+ return -1;
}
}
- Py_XDECREF(self->jar);
- Py_XINCREF(v);
- self->jar = v;
- return 0;
+ Py_XDECREF(self->jar);
+ Py_XINCREF(v);
+ self->jar = v;
+ return 0;
}
static PyObject *
Per_get_serial(cPersistentObject *self)
{
- return PyBytes_FromStringAndSize(self->serial, 8);
+ return PyBytes_FromStringAndSize(self->serial, 8);
}
static int
Per_set_serial(cPersistentObject *self, PyObject *v)
{
- if (v)
+ if (v)
{
- if (PyBytes_Check(v) && PyBytes_GET_SIZE(v) == 8)
- memcpy(self->serial, PyBytes_AS_STRING(v), 8);
- else
+ if (PyBytes_Check(v) && PyBytes_GET_SIZE(v) == 8)
+ memcpy(self->serial, PyBytes_AS_STRING(v), 8);
+ else
{
- PyErr_SetString(PyExc_ValueError,
- "_p_serial must be an 8-character string");
- return -1;
+ PyErr_SetString(PyExc_ValueError,
+ "_p_serial must be an 8-character string");
+ return -1;
}
}
- else
- memset(self->serial, 0, 8);
- return 0;
+ else
+ memset(self->serial, 0, 8);
+ return 0;
}
static PyObject *
Per_get_mtime(cPersistentObject *self)
{
- PyObject *t, *v;
+ PyObject *t, *v;
- if (unghostify(self) < 0)
- return NULL;
+ if (unghostify(self) < 0)
+ return NULL;
- accessed(self);
+ accessed(self);
- if (memcmp(self->serial, "\0\0\0\0\0\0\0\0", 8) == 0)
+ if (memcmp(self->serial, "\0\0\0\0\0\0\0\0", 8) == 0)
{
- Py_INCREF(Py_None);
- return Py_None;
+ Py_INCREF(Py_None);
+ return Py_None;
}
- t = PyObject_CallFunction(TimeStamp, "s#", self->serial, 8);
- if (!t)
- return NULL;
- v = PyObject_CallMethod(t, "timeTime", "");
- Py_DECREF(t);
- return v;
+ t = PyObject_CallFunction(TimeStamp, "s#", self->serial, 8);
+ if (!t)
+ return NULL;
+ v = PyObject_CallMethod(t, "timeTime", "");
+ Py_DECREF(t);
+ return v;
}
static PyObject *
Per_get_state(cPersistentObject *self)
{
- return INT_FROM_LONG(self->state);
+ return INT_FROM_LONG(self->state);
}
static PyObject *
Per_get_estimated_size(cPersistentObject *self)
{
- return INT_FROM_LONG(_estimated_size_in_bytes(self->estimated_size));
+ return INT_FROM_LONG(_estimated_size_in_bytes(self->estimated_size));
}
static int
Per_set_estimated_size(cPersistentObject *self, PyObject *v)
{
- if (v)
+ if (v)
{
- if (INT_CHECK(v))
+ if (INT_CHECK(v))
{
- long lv = INT_AS_LONG(v);
- if (lv < 0)
+ long lv = INT_AS_LONG(v);
+ if (lv < 0)
{
- PyErr_SetString(PyExc_ValueError,
- "_p_estimated_size must not be negative");
- return -1;
+ PyErr_SetString(PyExc_ValueError,
+ "_p_estimated_size must not be negative");
+ return -1;
}
- self->estimated_size = _estimated_size_in_24_bits(lv);
+ self->estimated_size = _estimated_size_in_24_bits(lv);
}
- else
+ else
{
- PyErr_SetString(PyExc_TypeError,
- "_p_estimated_size must be an integer");
- return -1;
+ PyErr_SetString(PyExc_TypeError,
+ "_p_estimated_size must be an integer");
+ return -1;
}
}
- else
- self->estimated_size = 0;
- return 0;
+ else
+ self->estimated_size = 0;
+ return 0;
}
static PyObject *
Per_get_status(cPersistentObject *self)
{
- PyObject *result = NULL;
+ PyObject *result = NULL;
- if (!self->jar) {
- result = py_unsaved;
- } else {
- switch (self->state) {
- case cPersistent_GHOST_STATE:
- result = py_ghost;
- break;
- case cPersistent_STICKY_STATE:
- result = py_sticky;
- break;
- case cPersistent_UPTODATE_STATE:
- result = py_saved;
- break;
- case cPersistent_CHANGED_STATE:
- result = py_changed;
- break;
+ if (!self->jar)
+ {
+ result = py_unsaved;
+ } else
+ {
+ switch (self->state)
+ {
+ case cPersistent_GHOST_STATE:
+ result = py_ghost;
+ break;
+ case cPersistent_STICKY_STATE:
+ result = py_sticky;
+ break;
+ case cPersistent_UPTODATE_STATE:
+ result = py_saved;
+ break;
+ case cPersistent_CHANGED_STATE:
+ result = py_changed;
+ break;
+ }
}
- }
- if (result) {
- Py_INCREF(result);
- }
- return result;
+ if (result)
+ {
+ Py_INCREF(result);
+ }
+ return result;
}
static PyObject*
Per_get_sticky(cPersistentObject *self)
{
- return PyBool_FromLong(self->state == cPersistent_STICKY_STATE);
+ return PyBool_FromLong(self->state == cPersistent_STICKY_STATE);
}
static int
Per_set_sticky(cPersistentObject *self, PyObject* value)
{
- if (self->state < 0) {
- PyErr_SetString(PyExc_ValueError,
- "can't set sticky flag on a ghost");
- return -1;
- }
- if (self->jar)
- {
- if (PyObject_IsTrue(value))
+ if (self->state < 0)
{
- self->state = cPersistent_STICKY_STATE;
- } else {
- self->state = cPersistent_UPTODATE_STATE;
+ PyErr_SetString(PyExc_ValueError,
+ "can't set sticky flag on a ghost");
+ return -1;
}
- }
- return 0;
+ if (self->jar)
+ {
+ if (PyObject_IsTrue(value))
+ {
+ self->state = cPersistent_STICKY_STATE;
+ } else {
+ self->state = cPersistent_UPTODATE_STATE;
+ }
+ }
+ return 0;
}
static PyGetSetDef Per_getsets[] = {
@@ -1259,7 +1269,7 @@
{"__reduce__", (PyCFunction)pickle___reduce__, METH_NOARGS,
pickle___reduce__doc},
- {NULL, NULL} /* sentinel */
+ {NULL, NULL} /* sentinel */
};
/* This module is compiled as a shared library. Some compilers don't
@@ -1273,37 +1283,37 @@
static PyTypeObject Pertype = {
PyVarObject_HEAD_INIT(DEFERRED_ADDRESS(&PyType_Type), 0)
- "persistent.Persistent", /* tp_name */
- sizeof(cPersistentObject), /* tp_basicsize */
- 0, /* tp_itemsize */
- (destructor)Per_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)Per_getattro, /* tp_getattro */
- (setattrofunc)Per_setattro, /* tp_setattro */
- 0, /* tp_as_buffer */
+ "persistent.Persistent", /* tp_name */
+ sizeof(cPersistentObject), /* tp_basicsize */
+ 0, /* tp_itemsize */
+ (destructor)Per_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)Per_getattro, /* tp_getattro */
+ (setattrofunc)Per_setattro, /* tp_setattro */
+ 0, /* tp_as_buffer */
Py_TPFLAGS_DEFAULT |
Py_TPFLAGS_BASETYPE |
Py_TPFLAGS_HAVE_GC, /* tp_flags */
- 0, /* tp_doc */
- (traverseproc)Per_traverse, /* tp_traverse */
- 0, /* tp_clear */
- 0, /* tp_richcompare */
- 0, /* tp_weaklistoffset */
- 0, /* tp_iter */
- 0, /* tp_iternext */
- Per_methods, /* tp_methods */
- 0, /* tp_members */
- Per_getsets, /* tp_getset */
+ 0, /* tp_doc */
+ (traverseproc)Per_traverse, /* tp_traverse */
+ 0, /* tp_clear */
+ 0, /* tp_richcompare */
+ 0, /* tp_weaklistoffset */
+ 0, /* tp_iter */
+ 0, /* tp_iternext */
+ Per_methods, /* tp_methods */
+ 0, /* tp_members */
+ Per_getsets, /* tp_getset */
};
/* End of code for Persistent objects */
@@ -1315,142 +1325,163 @@
static int
Per_setstate(cPersistentObject *self)
{
- if (unghostify(self) < 0)
- return -1;
- self->state = cPersistent_STICKY_STATE;
- return 0;
+ if (unghostify(self) < 0)
+ return -1;
+ self->state = cPersistent_STICKY_STATE;
+ return 0;
}
static PyObject *
simple_new(PyObject *self, PyObject *type_object)
{
- if (!PyType_Check(type_object))
+ if (!PyType_Check(type_object))
{
- PyErr_SetString(PyExc_TypeError,
- "simple_new argument must be a type object.");
- return NULL;
+ PyErr_SetString(PyExc_TypeError,
+ "simple_new argument must be a type object.");
+ return NULL;
}
- return PyType_GenericNew((PyTypeObject *)type_object, NULL, NULL);
+ return PyType_GenericNew((PyTypeObject *)type_object, NULL, NULL);
}
static PyMethodDef cPersistence_methods[] =
- {
+{
{"simple_new", simple_new, METH_O,
"Create an object by simply calling a class's __new__ method without "
"arguments."},
{NULL, NULL}
- };
+};
static cPersistenceCAPIstruct
truecPersistenceCAPI = {
- &Pertype,
- (getattrofunc)Per_getattro, /*tp_getattr with object key*/
- (setattrofunc)Per_setattro, /*tp_setattr with object key*/
- changed,
- accessed,
- ghostify,
- (intfunctionwithpythonarg)Per_setstate,
- NULL, /* The percachedel slot is initialized in cPickleCache.c when
- the module is loaded. It uses a function in a different
- shared library. */
- readCurrent
+ &Pertype,
+ (getattrofunc)Per_getattro, /*tp_getattr with object key*/
+ (setattrofunc)Per_setattro, /*tp_setattr with object key*/
+ changed,
+ accessed,
+ ghostify,
+ (intfunctionwithpythonarg)Per_setstate,
+ NULL, /* The percachedel slot is initialized in cPickleCache.c when
+ the module is loaded. It uses a function in a different
+ shared library. */
+ readCurrent
};
#ifdef PY3K
-static struct PyModuleDef moduledef = {
- PyModuleDef_HEAD_INIT,
- "cPersistence", /* m_name */
- cPersistence_doc_string, /* m_doc */
- -1, /* m_size */
- cPersistence_methods, /* m_methods */
- NULL, /* m_reload */
- NULL, /* m_traverse */
- NULL, /* m_clear */
- NULL, /* m_free */
- };
+static struct PyModuleDef moduledef =
+{
+ PyModuleDef_HEAD_INIT,
+ "cPersistence", /* m_name */
+ cPersistence_doc_string, /* m_doc */
+ -1, /* m_size */
+ cPersistence_methods, /* m_methods */
+ NULL, /* m_reload */
+ NULL, /* m_traverse */
+ NULL, /* m_clear */
+ NULL, /* m_free */
+};
#endif
-void
-initcPersistence(void)
+static PyObject*
+module_init(void)
{
- PyObject *m, *s;
- PyObject *copy_reg;
+ PyObject *module, *ts_module, *capi;
+ PyObject *copy_reg;
- if (init_strings() < 0)
- return;
+ if (init_strings() < 0)
+ return NULL;
#ifdef PY3K
- m = PyModule_Create(&moduledef);
+ module = PyModule_Create(&moduledef);
#else
- m = Py_InitModule3("cPersistence", cPersistence_methods,
- cPersistence_doc_string);
+ module = Py_InitModule3("cPersistence", cPersistence_methods,
+ cPersistence_doc_string);
#endif
#ifdef PY3K
- ((PyObject*)&Pertype)->ob_type = &PyType_Type;
+ ((PyObject*)&Pertype)->ob_type = &PyType_Type;
#else
- Pertype.ob_type = &PyType_Type;
+ Pertype.ob_type = &PyType_Type;
#endif
- Pertype.tp_new = PyType_GenericNew;
- if (PyType_Ready(&Pertype) < 0)
- return;
- if (PyModule_AddObject(m, "Persistent", (PyObject *)&Pertype) < 0)
- return;
+ Pertype.tp_new = PyType_GenericNew;
+ if (PyType_Ready(&Pertype) < 0)
+ return NULL;
+ if (PyModule_AddObject(module, "Persistent", (PyObject *)&Pertype) < 0)
+ return NULL;
- cPersistenceCAPI = &truecPersistenceCAPI;
+ cPersistenceCAPI = &truecPersistenceCAPI;
#ifdef PY3K
- s = PyCapsule_New(cPersistenceCAPI, "CAPI", NULL);
+ capi = PyCapsule_New(cPersistenceCAPI, CAPI_CAPSULE_NAME, NULL);
#else
- s = PyCObject_FromVoidPtr(cPersistenceCAPI, NULL);
+ capi = PyCObject_FromVoidPtr(cPersistenceCAPI, NULL);
#endif
- if (!s)
- return;
- if (PyModule_AddObject(m, "CAPI", s) < 0)
- return;
+ if (!capi)
+ return NULL;
+ if (PyModule_AddObject(module, "CAPI", capi) < 0)
+ return NULL;
- if (PyModule_AddIntConstant(m, "GHOST", cPersistent_GHOST_STATE) < 0)
- return;
+ if (PyModule_AddIntConstant(module, "GHOST", cPersistent_GHOST_STATE) < 0)
+ return NULL;
- if (PyModule_AddIntConstant(m, "UPTODATE", cPersistent_UPTODATE_STATE) < 0)
- return;
+ if (PyModule_AddIntConstant(module, "UPTODATE",
+ cPersistent_UPTODATE_STATE) < 0)
+ return NULL;
- if (PyModule_AddIntConstant(m, "CHANGED", cPersistent_CHANGED_STATE) < 0)
- return;
+ if (PyModule_AddIntConstant(module, "CHANGED",
+ cPersistent_CHANGED_STATE) < 0)
+ return NULL;
- if (PyModule_AddIntConstant(m, "STICKY", cPersistent_STICKY_STATE) < 0)
- return;
+ if (PyModule_AddIntConstant(module, "STICKY",
+ cPersistent_STICKY_STATE) < 0)
+ return NULL;
- py_simple_new = PyObject_GetAttrString(m, "simple_new");
- if (!py_simple_new)
- return;
+ py_simple_new = PyObject_GetAttrString(module, "simple_new");
+ if (!py_simple_new)
+ return NULL;
- copy_reg = PyImport_ImportModule("copy_reg");
- if (!copy_reg)
- return;
+#ifdef PY3K
+ copy_reg = PyImport_ImportModule("copyreg");
+#else
+ copy_reg = PyImport_ImportModule("copy_reg");
+#endif
+ if (!copy_reg)
+ return NULL;
- copy_reg_slotnames = PyObject_GetAttrString(copy_reg, "_slotnames");
- if (!copy_reg_slotnames)
+ copy_reg_slotnames = PyObject_GetAttrString(copy_reg, "_slotnames");
+ if (!copy_reg_slotnames)
{
Py_DECREF(copy_reg);
- return;
+ return NULL;
}
- __newobj__ = PyObject_GetAttrString(copy_reg, "__newobj__");
- if (!__newobj__)
+ __newobj__ = PyObject_GetAttrString(copy_reg, "__newobj__");
+ if (!__newobj__)
{
Py_DECREF(copy_reg);
- return;
+ return NULL;
}
- if (!TimeStamp)
+ if (!TimeStamp)
{
- m = PyImport_ImportModule("persistent.timestamp");
- if (!m)
- return;
- TimeStamp = PyObject_GetAttrString(m, "TimeStamp");
- Py_DECREF(m);
+ ts_module = PyImport_ImportModule("persistent.timestamp");
+ if (!ts_module)
+ return NULL;
+ TimeStamp = PyObject_GetAttrString(ts_module, "TimeStamp");
+ Py_DECREF(ts_module);
/* fall through to immediate return on error */
}
+ return module;
}
+
+#ifdef PY3K
+PyMODINIT_FUNC PyInit_cPersistence(void)
+{
+ return module_init();
+}
+#else
+PyMODINIT_FUNC initcPersistence(void)
+{
+ module_init();
+}
+#endif
Modified: persistent/trunk/persistent/cPersistence.h
===================================================================
--- persistent/trunk/persistent/cPersistence.h 2012-12-14 00:21:12 UTC (rev 128631)
+++ persistent/trunk/persistent/cPersistence.h 2012-12-14 00:21:15 UTC (rev 128632)
@@ -15,28 +15,7 @@
#ifndef CPERSISTENCE_H
#define CPERSISTENCE_H
-#include "Python.h"
-
-#if PY_MAJOR_VERSION >= 3
-#define PY3K
-#endif
-
-#ifdef PY3K
-#define INTERN PyUnicode_InternFromString
-#else
-#define INTERN PyString_InternFromString
-#endif
-
-#ifdef PY3K
-#define INT_FROM_LONG(x) PyLong_FromLong(x)
-#define INT_CHECK(x) PyLong_Check(x)
-#define INT_AS_LONG(x) PyLong_AS_LONG(x)
-#else
-#define INT_FROM_LONG(x) PyInt_FromLong(x)
-#define INT_CHECK(x) PyInt_Check(x)
-#define INT_AS_LONG(x) PyInt_AS_LONG(x)
-#endif
-
+#include "_compat.h"
#include "bytesobject.h"
#include "ring.h"
Modified: persistent/trunk/persistent/cPickleCache.c
===================================================================
--- persistent/trunk/persistent/cPickleCache.c 2012-12-14 00:21:12 UTC (rev 128631)
+++ persistent/trunk/persistent/cPickleCache.c 2012-12-14 00:21:15 UTC (rev 128632)
@@ -116,33 +116,34 @@
/* This object is the pickle cache. The CACHE_HEAD macro guarantees
that layout of this struct is the same as the start of
ccobject_head in cPersistence.c */
-typedef struct {
- CACHE_HEAD
- int klass_count; /* count of persistent classes */
- PyObject *data; /* oid -> object dict */
- PyObject *jar; /* Connection object */
- int cache_size; /* target number of items in cache */
- PY_LONG_LONG cache_size_bytes; /* target total estimated size of
- items in cache */
+typedef struct
+{
+ CACHE_HEAD
+ int klass_count; /* count of persistent classes */
+ PyObject *data; /* oid -> object dict */
+ PyObject *jar; /* Connection object */
+ int cache_size; /* target number of items in cache */
+ PY_LONG_LONG cache_size_bytes; /* target total estimated size of
+ items in cache */
- /* Most of the time the ring contains only:
- * many nodes corresponding to persistent objects
- * one 'home' node from the cache.
- In some cases it is handy to temporarily add other types
- of node into the ring as placeholders. 'ring_lock' is a boolean
- indicating that someone has already done this. Currently this
- is only used by the garbage collection code. */
+ /* Most of the time the ring contains only:
+ * many nodes corresponding to persistent objects
+ * one 'home' node from the cache.
+ In some cases it is handy to temporarily add other types
+ of node into the ring as placeholders. 'ring_lock' is a boolean
+ indicating that someone has already done this. Currently this
+ is only used by the garbage collection code. */
- int ring_lock;
+ int ring_lock;
- /* 'cache_drain_resistance' controls how quickly the cache size will drop
- when it is smaller than the configured size. A value of zero means it will
- not drop below the configured size (suitable for most caches). Otherwise,
- it will remove cache_non_ghost_count/cache_drain_resistance items from
- the cache every time (suitable for rarely used caches, such as those
- associated with Zope versions. */
+ /* 'cache_drain_resistance' controls how quickly the cache size will drop
+ when it is smaller than the configured size. A value of zero means it
+ will not drop below the configured size (suitable for most caches).
+ Otherwise, it will remove cache_non_ghost_count/cache_drain_resistance
+ items from the cache every time (suitable for rarely used caches, such
+ as those associated with Zope versions. */
- int cache_drain_resistance;
+ int cache_drain_resistance;
} ccobject;
@@ -157,1090 +158,1102 @@
static void
insert_after(CPersistentRing *self, CPersistentRing *after)
{
- assert(self != NULL);
- assert(after != NULL);
- self->r_prev = after;
- self->r_next = after->r_next;
- after->r_next->r_prev = self;
- after->r_next = self;
+ assert(self != NULL);
+ assert(after != NULL);
+ self->r_prev = after;
+ self->r_next = after->r_next;
+ after->r_next->r_prev = self;
+ after->r_next = self;
}
/* Remove self from the ring. */
static void
unlink_from_ring(CPersistentRing *self)
{
- assert(self != NULL);
- self->r_prev->r_next = self->r_next;
- self->r_next->r_prev = self->r_prev;
+ assert(self != NULL);
+ self->r_prev->r_next = self->r_next;
+ self->r_next->r_prev = self->r_prev;
}
static int
scan_gc_items(ccobject *self, int target, PY_LONG_LONG target_bytes)
{
- /* This function must only be called with the ring lock held,
- because it places non-object placeholders in the ring.
- */
- cPersistentObject *object;
- CPersistentRing *here;
- CPersistentRing before_original_home;
- int result = -1; /* guilty until proved innocent */
+ /* This function must only be called with the ring lock held,
+ because it places non-object placeholders in the ring.
+ */
+ cPersistentObject *object;
+ CPersistentRing *here;
+ CPersistentRing before_original_home;
+ int result = -1; /* guilty until proved innocent */
- /* Scan the ring, from least to most recently used, deactivating
- * up-to-date objects, until we either find the ring_home again or
- * or we've ghosted enough objects to reach the target size.
- * Tricky: __getattr__ and __del__ methods can do anything, and in
- * particular if we ghostify an object with a __del__ method, that method
- * can load the object again, putting it back into the MRU part of the
- * ring. Waiting to find ring_home again can thus cause an infinite
- * loop (Collector #1208). So before_original_home records the MRU
- * position we start with, and we stop the scan when we reach that.
- */
- insert_after(&before_original_home, self->ring_home.r_prev);
- here = self->ring_home.r_next; /* least recently used object */
- while (here != &before_original_home &&
- (self->non_ghost_count > target
- || (target_bytes && self->total_estimated_size > target_bytes)
+ /* Scan the ring, from least to most recently used, deactivating
+ * up-to-date objects, until we either find the ring_home again or
+ * or we've ghosted enough objects to reach the target size.
+ * Tricky: __getattr__ and __del__ methods can do anything, and in
+ * particular if we ghostify an object with a __del__ method, that method
+ * can load the object again, putting it back into the MRU part of the
+ * ring. Waiting to find ring_home again can thus cause an infinite
+ * loop (Collector #1208). So before_original_home records the MRU
+ * position we start with, and we stop the scan when we reach that.
+ */
+ insert_after(&before_original_home, self->ring_home.r_prev);
+ here = self->ring_home.r_next; /* least recently used object */
+ while (here != &before_original_home &&
+ (self->non_ghost_count > target
+ || (target_bytes && self->total_estimated_size > target_bytes)
+ )
)
- )
{
- assert(self->ring_lock);
- assert(here != &self->ring_home);
-
- /* At this point we know that the ring only contains nodes
- from persistent objects, plus our own home node. We know
- this because the ring lock is held. We can safely assume
- the current ring node is a persistent object now we know it
- is not the home */
- object = OBJECT_FROM_RING(self, here);
+ assert(self->ring_lock);
+ assert(here != &self->ring_home);
+
+ /* At this point we know that the ring only contains nodes
+ from persistent objects, plus our own home node. We know
+ this because the ring lock is held. We can safely assume
+ the current ring node is a persistent object now we know it
+ is not the home */
+ object = OBJECT_FROM_RING(self, here);
- if (object->state == cPersistent_UPTODATE_STATE)
+ if (object->state == cPersistent_UPTODATE_STATE)
{
- CPersistentRing placeholder;
- PyObject *method;
- PyObject *temp;
- int error_occurred = 0;
- /* deactivate it. This is the main memory saver. */
-
- /* Add a placeholder, a dummy node in the ring. We need
- to do this to mark our position in the ring. It is
- possible that the PyObject_GetAttr() call below will
- invoke a __getattr__() hook in Python. Also possible
- that deactivation will lead to a __del__ method call.
- So another thread might run, and mutate the ring as a side
- effect of object accesses. There's no predicting then where
- in the ring here->next will point after that. The
- placeholder won't move as a side effect of calling Python
- code.
- */
- insert_after(&placeholder, here);
- method = PyObject_GetAttr((PyObject *)object, py__p_deactivate);
- if (method == NULL)
- error_occurred = 1;
- else
+ CPersistentRing placeholder;
+ PyObject *method;
+ PyObject *temp;
+ int error_occurred = 0;
+ /* deactivate it. This is the main memory saver. */
+
+ /* Add a placeholder, a dummy node in the ring. We need
+ to do this to mark our position in the ring. It is
+ possible that the PyObject_GetAttr() call below will
+ invoke a __getattr__() hook in Python. Also possible
+ that deactivation will lead to a __del__ method call.
+ So another thread might run, and mutate the ring as a side
+ effect of object accesses. There's no predicting then where
+ in the ring here->next will point after that. The
+ placeholder won't move as a side effect of calling Python
+ code.
+ */
+ insert_after(&placeholder, here);
+ method = PyObject_GetAttr((PyObject *)object, py__p_deactivate);
+ if (method == NULL)
+ error_occurred = 1;
+ else
{
- temp = PyObject_CallObject(method, NULL);
- Py_DECREF(method);
- if (temp == NULL)
- error_occurred = 1;
- else
- Py_DECREF(temp);
+ temp = PyObject_CallObject(method, NULL);
+ Py_DECREF(method);
+ if (temp == NULL)
+ error_occurred = 1;
+ else
+ Py_DECREF(temp);
}
- here = placeholder.r_next;
- unlink_from_ring(&placeholder);
- if (error_occurred)
- goto Done;
+ here = placeholder.r_next;
+ unlink_from_ring(&placeholder);
+ if (error_occurred)
+ goto Done;
}
- else
- here = here->r_next;
+ else
+ here = here->r_next;
}
- result = 0;
- Done:
- unlink_from_ring(&before_original_home);
- return result;
+ result = 0;
+Done:
+ unlink_from_ring(&before_original_home);
+ return result;
}
static PyObject *
lockgc(ccobject *self, int target_size, PY_LONG_LONG target_size_bytes)
{
- /* This is thread-safe because of the GIL, and there's nothing
- * in between checking the ring_lock and acquiring it that calls back
- * into Python.
- */
- if (self->ring_lock)
+ /* This is thread-safe because of the GIL, and there's nothing
+ * in between checking the ring_lock and acquiring it that calls back
+ * into Python.
+ */
+ if (self->ring_lock)
{
- Py_INCREF(Py_None);
- return Py_None;
+ Py_INCREF(Py_None);
+ return Py_None;
}
- self->ring_lock = 1;
- if (scan_gc_items(self, target_size, target_size_bytes) < 0)
+ self->ring_lock = 1;
+ if (scan_gc_items(self, target_size, target_size_bytes) < 0)
{
- self->ring_lock = 0;
- return NULL;
+ self->ring_lock = 0;
+ return NULL;
}
- self->ring_lock = 0;
+ self->ring_lock = 0;
- Py_INCREF(Py_None);
- return Py_None;
+ Py_INCREF(Py_None);
+ return Py_None;
}
static PyObject *
cc_incrgc(ccobject *self, PyObject *args)
{
- int obsolete_arg = -999;
- int starting_size = self->non_ghost_count;
- int target_size = self->cache_size;
- PY_LONG_LONG target_size_bytes = self->cache_size_bytes;
+ int obsolete_arg = -999;
+ int starting_size = self->non_ghost_count;
+ int target_size = self->cache_size;
+ PY_LONG_LONG target_size_bytes = self->cache_size_bytes;
- if (self->cache_drain_resistance >= 1)
+ if (self->cache_drain_resistance >= 1)
{
- /* This cache will gradually drain down to a small size. Check
- a (small) number of objects proportional to the current size */
+ /* This cache will gradually drain down to a small size. Check
+ a (small) number of objects proportional to the current size */
- int target_size_2 = (starting_size - 1
- - starting_size / self->cache_drain_resistance);
- if (target_size_2 < target_size)
- target_size = target_size_2;
+ int target_size_2 = (starting_size - 1
+ - starting_size / self->cache_drain_resistance);
+ if (target_size_2 < target_size)
+ target_size = target_size_2;
}
- if (!PyArg_ParseTuple(args, "|i:incrgc", &obsolete_arg))
- return NULL;
+ if (!PyArg_ParseTuple(args, "|i:incrgc", &obsolete_arg))
+ return NULL;
- if (obsolete_arg != -999
- &&
- (PyErr_Warn(PyExc_DeprecationWarning,
- "No argument expected")
- < 0))
- return NULL;
+ if (obsolete_arg != -999
+ &&
+ (PyErr_Warn(PyExc_DeprecationWarning,
+ "No argument expected")
+ < 0))
+ return NULL;
- return lockgc(self, target_size, target_size_bytes);
+ return lockgc(self, target_size, target_size_bytes);
}
static PyObject *
cc_full_sweep(ccobject *self, PyObject *args)
{
- int dt = -999;
+ int dt = -999;
- /* TODO: This should be deprecated; */
+ /* TODO: This should be deprecated; */
- if (!PyArg_ParseTuple(args, "|i:full_sweep", &dt))
- return NULL;
- if (dt == -999)
- return lockgc(self, 0, 0);
- else
- return cc_incrgc(self, args);
+ if (!PyArg_ParseTuple(args, "|i:full_sweep", &dt))
+ return NULL;
+ if (dt == -999)
+ return lockgc(self, 0, 0);
+ else
+ return cc_incrgc(self, args);
}
static PyObject *
cc_minimize(ccobject *self, PyObject *args)
{
- int ignored = -999;
+ int ignored = -999;
- if (!PyArg_ParseTuple(args, "|i:minimize", &ignored))
- return NULL;
+ if (!PyArg_ParseTuple(args, "|i:minimize", &ignored))
+ return NULL;
- if (ignored != -999
- &&
- (PyErr_Warn(PyExc_DeprecationWarning,
- "No argument expected")
- < 0))
- return NULL;
+ if (ignored != -999
+ &&
+ (PyErr_Warn(PyExc_DeprecationWarning,
+ "No argument expected")
+ < 0))
+ return NULL;
- return lockgc(self, 0, 0);
+ return lockgc(self, 0, 0);
}
static int
_invalidate(ccobject *self, PyObject *key)
{
- static PyObject *_p_invalidate = NULL;
- PyObject *meth, *v;
+ static PyObject *_p_invalidate = NULL;
+ PyObject *meth, *v;
- v = PyDict_GetItem(self->data, key);
- if (v == NULL)
- return 0;
+ v = PyDict_GetItem(self->data, key);
+ if (v == NULL)
+ return 0;
- if (_p_invalidate == NULL)
+ if (_p_invalidate == NULL)
{
- _p_invalidate = INTERN("_p_invalidate");
- if (_p_invalidate == NULL)
+ _p_invalidate = INTERN("_p_invalidate");
+ if (_p_invalidate == NULL)
{
- /* It doesn't make any sense to ignore this error, but
- the caller ignores all errors.
+ /* It doesn't make any sense to ignore this error, but
+ the caller ignores all errors.
- TODO: and why does it do that? This should be fixed
- */
- return -1;
+ TODO: and why does it do that? This should be fixed
+ */
+ return -1;
}
}
- if (v->ob_refcnt <= 1 && PyType_Check(v))
+ if (v->ob_refcnt <= 1 && PyType_Check(v))
{
- /* This looks wrong, but it isn't. We use strong references to types
- because they don't have the ring members.
+ /* This looks wrong, but it isn't. We use strong references to types
+ because they don't have the ring members.
- The result is that we *never* remove classes unless
- they are modified. We can fix this by using wekrefs uniformly.
- */
- self->klass_count--;
- return PyDict_DelItem(self->data, key);
+ The result is that we *never* remove classes unless
+ they are modified. We can fix this by using wekrefs uniformly.
+ */
+ self->klass_count--;
+ return PyDict_DelItem(self->data, key);
}
- meth = PyObject_GetAttr(v, _p_invalidate);
- if (meth == NULL)
- return -1;
+ meth = PyObject_GetAttr(v, _p_invalidate);
+ if (meth == NULL)
+ return -1;
- v = PyObject_CallObject(meth, NULL);
- Py_DECREF(meth);
- if (v == NULL)
- return -1;
- Py_DECREF(v);
- return 0;
+ v = PyObject_CallObject(meth, NULL);
+ Py_DECREF(meth);
+ if (v == NULL)
+ return -1;
+ Py_DECREF(v);
+ return 0;
}
static PyObject *
cc_invalidate(ccobject *self, PyObject *inv)
{
- PyObject *key, *v;
- Py_ssize_t i = 0;
+ PyObject *key, *v;
+ Py_ssize_t i = 0;
- if (PyDict_Check(inv))
+ if (PyDict_Check(inv))
{
- while (PyDict_Next(inv, &i, &key, &v))
+ while (PyDict_Next(inv, &i, &key, &v))
{
- if (_invalidate(self, key) < 0)
- return NULL;
+ if (_invalidate(self, key) < 0)
+ return NULL;
}
- PyDict_Clear(inv);
+ PyDict_Clear(inv);
}
- else
+ else
{
- if (PyBytes_Check(inv))
+ if (PyBytes_Check(inv))
{
- if (_invalidate(self, inv) < 0)
- return NULL;
+ if (_invalidate(self, inv) < 0)
+ return NULL;
}
- else
+ else
{
- int l, r;
+ int l, r;
- l = PyObject_Length(inv);
- if (l < 0)
- return NULL;
- for (i=l; --i >= 0; )
+ l = PyObject_Length(inv);
+ if (l < 0)
+ return NULL;
+ for (i=l; --i >= 0; )
{
- key = PySequence_GetItem(inv, i);
- if (!key)
- return NULL;
- r = _invalidate(self, key);
- Py_DECREF(key);
- if (r < 0)
- return NULL;
+ key = PySequence_GetItem(inv, i);
+ if (!key)
+ return NULL;
+ r = _invalidate(self, key);
+ Py_DECREF(key);
+ if (r < 0)
+ return NULL;
}
- /* Dubious: modifying the input may be an unexpected side effect. */
- PySequence_DelSlice(inv, 0, l);
+ /* Dubious: modifying the input may be an unexpected side effect. */
+ PySequence_DelSlice(inv, 0, l);
}
}
- Py_INCREF(Py_None);
- return Py_None;
+ Py_INCREF(Py_None);
+ return Py_None;
}
static PyObject *
cc_get(ccobject *self, PyObject *args)
{
- PyObject *r, *key, *d = NULL;
+ PyObject *r, *key, *d = NULL;
- if (!PyArg_ParseTuple(args, "O|O:get", &key, &d))
- return NULL;
+ if (!PyArg_ParseTuple(args, "O|O:get", &key, &d))
+ return NULL;
- r = PyDict_GetItem(self->data, key);
- if (!r)
+ r = PyDict_GetItem(self->data, key);
+ if (!r)
{
- if (d)
- r = d;
- else
- r = Py_None;
+ if (d)
+ r = d;
+ else
+ r = Py_None;
}
- Py_INCREF(r);
- return r;
+ Py_INCREF(r);
+ return r;
}
static PyObject *
cc_items(ccobject *self)
{
- return PyObject_CallMethod(self->data, "items", "");
+ return PyObject_CallMethod(self->data, "items", "");
}
static PyObject *
cc_klass_items(ccobject *self)
{
- PyObject *l,*k,*v;
- Py_ssize_t p = 0;
+ PyObject *l,*k,*v;
+ Py_ssize_t p = 0;
- l = PyList_New(0);
- if (l == NULL)
- return NULL;
+ l = PyList_New(0);
+ if (l == NULL)
+ return NULL;
- while (PyDict_Next(self->data, &p, &k, &v))
+ while (PyDict_Next(self->data, &p, &k, &v))
{
- if(PyType_Check(v))
+ if(PyType_Check(v))
{
- v = Py_BuildValue("OO", k, v);
- if (v == NULL)
+ v = Py_BuildValue("OO", k, v);
+ if (v == NULL)
{
- Py_DECREF(l);
- return NULL;
+ Py_DECREF(l);
+ return NULL;
}
- if (PyList_Append(l, v) < 0)
+ if (PyList_Append(l, v) < 0)
{
- Py_DECREF(v);
- Py_DECREF(l);
- return NULL;
+ Py_DECREF(v);
+ Py_DECREF(l);
+ return NULL;
}
- Py_DECREF(v);
+ Py_DECREF(v);
}
}
- return l;
+ return l;
}
static PyObject *
cc_debug_info(ccobject *self)
{
- PyObject *l,*k,*v;
- Py_ssize_t p = 0;
+ PyObject *l,*k,*v;
+ Py_ssize_t p = 0;
- l = PyList_New(0);
- if (l == NULL)
- return NULL;
+ l = PyList_New(0);
+ if (l == NULL)
+ return NULL;
- while (PyDict_Next(self->data, &p, &k, &v))
+ while (PyDict_Next(self->data, &p, &k, &v))
{
- if (v->ob_refcnt <= 0)
- v = Py_BuildValue("Oi", k, v->ob_refcnt);
+ if (v->ob_refcnt <= 0)
+ v = Py_BuildValue("Oi", k, v->ob_refcnt);
- else if (! PyType_Check(v) &&
- (v->ob_type->tp_basicsize >= sizeof(cPersistentObject))
- )
- v = Py_BuildValue("Oisi",
- k, v->ob_refcnt, v->ob_type->tp_name,
- ((cPersistentObject*)v)->state);
- else
- v = Py_BuildValue("Ois", k, v->ob_refcnt, v->ob_type->tp_name);
+ else if (! PyType_Check(v) &&
+ (v->ob_type->tp_basicsize >= sizeof(cPersistentObject))
+ )
+ v = Py_BuildValue("Oisi",
+ k, v->ob_refcnt, v->ob_type->tp_name,
+ ((cPersistentObject*)v)->state);
+ else
+ v = Py_BuildValue("Ois", k, v->ob_refcnt, v->ob_type->tp_name);
- if (v == NULL)
- goto err;
+ if (v == NULL)
+ goto err;
- if (PyList_Append(l, v) < 0)
- goto err;
+ if (PyList_Append(l, v) < 0)
+ goto err;
}
- return l;
+ return l;
- err:
- Py_DECREF(l);
- return NULL;
-
+err:
+ Py_DECREF(l);
+ return NULL;
}
static PyObject *
cc_lru_items(ccobject *self)
{
- PyObject *l;
- CPersistentRing *here;
+ PyObject *l;
+ CPersistentRing *here;
- if (self->ring_lock)
+ if (self->ring_lock)
{
- /* When the ring lock is held, we have no way of know which
- ring nodes belong to persistent objects, and which a
- placeholders. */
- PyErr_SetString(PyExc_ValueError,
- ".lru_items() is unavailable during garbage collection");
- return NULL;
+ /* When the ring lock is held, we have no way of know which
+ ring nodes belong to persistent objects, and which a
+ placeholders. */
+ PyErr_SetString(PyExc_ValueError,
+ ".lru_items() is unavailable during garbage collection");
+ return NULL;
}
- l = PyList_New(0);
- if (l == NULL)
- return NULL;
+ l = PyList_New(0);
+ if (l == NULL)
+ return NULL;
- here = self->ring_home.r_next;
- while (here != &self->ring_home)
+ here = self->ring_home.r_next;
+ while (here != &self->ring_home)
{
- PyObject *v;
- cPersistentObject *object = OBJECT_FROM_RING(self, here);
+ PyObject *v;
+ cPersistentObject *object = OBJECT_FROM_RING(self, here);
- if (object == NULL)
+ if (object == NULL)
{
- Py_DECREF(l);
- return NULL;
+ Py_DECREF(l);
+ return NULL;
}
- v = Py_BuildValue("OO", object->oid, object);
- if (v == NULL)
+ v = Py_BuildValue("OO", object->oid, object);
+ if (v == NULL)
{
- Py_DECREF(l);
- return NULL;
+ Py_DECREF(l);
+ return NULL;
}
- if (PyList_Append(l, v) < 0)
+ if (PyList_Append(l, v) < 0)
{
- Py_DECREF(v);
- Py_DECREF(l);
- return NULL;
+ Py_DECREF(v);
+ Py_DECREF(l);
+ return NULL;
}
- Py_DECREF(v);
- here = here->r_next;
+ Py_DECREF(v);
+ here = here->r_next;
}
- return l;
+ return l;
}
static void
cc_oid_unreferenced(ccobject *self, PyObject *oid)
{
- /* This is called by the persistent object deallocation function
- when the reference count on a persistent object reaches
- zero. We need to fix up our dictionary; its reference is now
- dangling because we stole its reference count. Be careful to
- not release the global interpreter lock until this is
- complete. */
+ /* This is called by the persistent object deallocation function
+ when the reference count on a persistent object reaches
+ zero. We need to fix up our dictionary; its reference is now
+ dangling because we stole its reference count. Be careful to
+ not release the global interpreter lock until this is
+ complete. */
- PyObject *v;
+ PyObject *v;
- /* If the cache has been cleared by GC, data will be NULL. */
- if (!self->data)
- return;
+ /* If the cache has been cleared by GC, data will be NULL. */
+ if (!self->data)
+ return;
- v = PyDict_GetItem(self->data, oid);
- assert(v);
- assert(v->ob_refcnt == 0);
- /* Need to be very hairy here because a dictionary is about
- to decref an already deleted object.
- */
+ v = PyDict_GetItem(self->data, oid);
+ assert(v);
+ assert(v->ob_refcnt == 0);
+ /* Need to be very hairy here because a dictionary is about
+ to decref an already deleted object.
+ */
#ifdef Py_TRACE_REFS
- /* This is called from the deallocation function after the
- interpreter has untracked the reference. Track it again.
- */
- _Py_NewReference(v);
- /* Don't increment total refcount as a result of the
- shenanigans played in this function. The _Py_NewReference()
- call above creates artificial references to v.
- */
- _Py_RefTotal--;
- assert(v->ob_type);
+ /* This is called from the deallocation function after the
+ interpreter has untracked the reference. Track it again.
+ */
+ _Py_NewReference(v);
+ /* Don't increment total refcount as a result of the
+ shenanigans played in this function. The _Py_NewReference()
+ call above creates artificial references to v.
+ */
+ _Py_RefTotal--;
+ assert(v->ob_type);
#else
- Py_INCREF(v);
+ Py_INCREF(v);
#endif
- assert(v->ob_refcnt == 1);
- /* Incremement the refcount again, because delitem is going to
- DECREF it. If it's refcount reached zero again, we'd call back to
- the dealloc function that called us.
- */
- Py_INCREF(v);
+ assert(v->ob_refcnt == 1);
+ /* Incremement the refcount again, because delitem is going to
+ DECREF it. If it's refcount reached zero again, we'd call back to
+ the dealloc function that called us.
+ */
+ Py_INCREF(v);
- /* TODO: Should we call _Py_ForgetReference() on error exit? */
- if (PyDict_DelItem(self->data, oid) < 0)
- return;
- Py_DECREF((ccobject *)((cPersistentObject *)v)->cache);
- ((cPersistentObject *)v)->cache = NULL;
+ /* TODO: Should we call _Py_ForgetReference() on error exit? */
+ if (PyDict_DelItem(self->data, oid) < 0)
+ return;
+ Py_DECREF((ccobject *)((cPersistentObject *)v)->cache);
+ ((cPersistentObject *)v)->cache = NULL;
- assert(v->ob_refcnt == 1);
+ assert(v->ob_refcnt == 1);
- /* Undo the temporary resurrection.
- Don't DECREF the object, because this function is called from
- the object's dealloc function. If the refcnt reaches zero, it
- will all be invoked recursively.
- */
- _Py_ForgetReference(v);
+ /* Undo the temporary resurrection.
+ Don't DECREF the object, because this function is called from
+ the object's dealloc function. If the refcnt reaches zero, it
+ will all be invoked recursively.
+ */
+ _Py_ForgetReference(v);
}
static PyObject *
cc_ringlen(ccobject *self)
{
- CPersistentRing *here;
- int c = 0;
+ CPersistentRing *here;
+ int c = 0;
- for (here = self->ring_home.r_next; here != &self->ring_home;
- here = here->r_next)
- c++;
- return INT_FROM_LONG(c);
+ for (here = self->ring_home.r_next; here != &self->ring_home;
+ here = here->r_next)
+ c++;
+ return INT_FROM_LONG(c);
}
static PyObject *
cc_update_object_size_estimation(ccobject *self, PyObject *args)
{
- PyObject *oid;
- cPersistentObject *v;
- unsigned int new_size;
- if (!PyArg_ParseTuple(args, "OI:updateObjectSizeEstimation",
- &oid, &new_size))
- return NULL;
- /* Note: reference borrowed */
- v = (cPersistentObject *)PyDict_GetItem(self->data, oid);
- if (v)
+ PyObject *oid;
+ cPersistentObject *v;
+ unsigned int new_size;
+ if (!PyArg_ParseTuple(args, "OI:updateObjectSizeEstimation",
+ &oid, &new_size))
+ return NULL;
+ /* Note: reference borrowed */
+ v = (cPersistentObject *)PyDict_GetItem(self->data, oid);
+ if (v)
{
- /* we know this object -- update our "total_size_estimation"
- we must only update when the object is in the ring
- */
- if (v->ring.r_next)
+ /* we know this object -- update our "total_size_estimation"
+ we must only update when the object is in the ring
+ */
+ if (v->ring.r_next)
{
- self->total_estimated_size += _estimated_size_in_bytes(
- (int)(_estimated_size_in_24_bits(new_size))
- - (int)(v->estimated_size)
- );
- /* we do this in "Connection" as we need it even when the
- object is not in the cache (or not the ring)
- */
- /* v->estimated_size = new_size; */
+ self->total_estimated_size += _estimated_size_in_bytes(
+ (int)(_estimated_size_in_24_bits(new_size))
+ - (int)(v->estimated_size)
+ );
+ /* we do this in "Connection" as we need it even when the
+ object is not in the cache (or not the ring)
+ */
+ /* v->estimated_size = new_size; */
}
}
- Py_RETURN_NONE;
+ Py_RETURN_NONE;
}
static PyObject*
cc_new_ghost(ccobject *self, PyObject *args)
{
- PyObject *tmp, *key, *v;
+ PyObject *tmp, *key, *v;
- if (!PyArg_ParseTuple(args, "OO:new_ghost", &key, &v))
- return NULL;
+ if (!PyArg_ParseTuple(args, "OO:new_ghost", &key, &v))
+ return NULL;
- /* Sanity check the value given to make sure it is allowed in the cache */
- if (PyType_Check(v))
+ /* Sanity check the value given to make sure it is allowed in the cache */
+ if (PyType_Check(v))
{
- /* Its a persistent class, such as a ZClass. Thats ok. */
+ /* Its a persistent class, such as a ZClass. Thats ok. */
}
- else if (v->ob_type->tp_basicsize < sizeof(cPersistentObject))
+ else if (v->ob_type->tp_basicsize < sizeof(cPersistentObject))
{
- /* If it's not an instance of a persistent class, (ie Python
- classes that derive from persistent.Persistent, BTrees,
- etc), report an error.
+ /* If it's not an instance of a persistent class, (ie Python
+ classes that derive from persistent.Persistent, BTrees,
+ etc), report an error.
- TODO: checking sizeof() seems a poor test.
- */
- PyErr_SetString(PyExc_TypeError,
- "Cache values must be persistent objects.");
- return NULL;
+ TODO: checking sizeof() seems a poor test.
+ */
+ PyErr_SetString(PyExc_TypeError,
+ "Cache values must be persistent objects.");
+ return NULL;
}
- /* Can't access v->oid directly because the object might be a
- * persistent class.
- */
- tmp = PyObject_GetAttr(v, py__p_oid);
- if (tmp == NULL)
- return NULL;
- Py_DECREF(tmp);
- if (tmp != Py_None)
+ /* Can't access v->oid directly because the object might be a
+ * persistent class.
+ */
+ tmp = PyObject_GetAttr(v, py__p_oid);
+ if (tmp == NULL)
+ return NULL;
+ Py_DECREF(tmp);
+ if (tmp != Py_None)
{
- PyErr_SetString(PyExc_AssertionError,
- "New ghost object must not have an oid");
- return NULL;
+ PyErr_SetString(PyExc_AssertionError,
+ "New ghost object must not have an oid");
+ return NULL;
}
- /* useful sanity check, but not strictly an invariant of this class */
- tmp = PyObject_GetAttr(v, py__p_jar);
- if (tmp == NULL)
- return NULL;
- Py_DECREF(tmp);
- if (tmp != Py_None)
+ /* useful sanity check, but not strictly an invariant of this class */
+ tmp = PyObject_GetAttr(v, py__p_jar);
+ if (tmp == NULL)
+ return NULL;
+ Py_DECREF(tmp);
+ if (tmp != Py_None)
{
- PyErr_SetString(PyExc_AssertionError,
- "New ghost object must not have a jar");
- return NULL;
+ PyErr_SetString(PyExc_AssertionError,
+ "New ghost object must not have a jar");
+ return NULL;
}
- tmp = PyDict_GetItem(self->data, key);
- if (tmp)
+ tmp = PyDict_GetItem(self->data, key);
+ if (tmp)
{
- Py_DECREF(tmp);
- PyErr_SetString(PyExc_AssertionError,
- "The given oid is already in the cache");
- return NULL;
+ Py_DECREF(tmp);
+ PyErr_SetString(PyExc_AssertionError,
+ "The given oid is already in the cache");
+ return NULL;
}
- if (PyType_Check(v))
+ if (PyType_Check(v))
{
- if (PyObject_SetAttr(v, py__p_jar, self->jar) < 0)
- return NULL;
- if (PyObject_SetAttr(v, py__p_oid, key) < 0)
- return NULL;
- if (PyDict_SetItem(self->data, key, v) < 0)
- return NULL;
- PyObject_GC_UnTrack((void *)self->data);
- self->klass_count++;
+ if (PyObject_SetAttr(v, py__p_jar, self->jar) < 0)
+ return NULL;
+ if (PyObject_SetAttr(v, py__p_oid, key) < 0)
+ return NULL;
+ if (PyDict_SetItem(self->data, key, v) < 0)
+ return NULL;
+ PyObject_GC_UnTrack((void *)self->data);
+ self->klass_count++;
}
- else
+ else
{
- cPersistentObject *p = (cPersistentObject *)v;
+ cPersistentObject *p = (cPersistentObject *)v;
- if(p->cache != NULL)
+ if(p->cache != NULL)
{
- PyErr_SetString(PyExc_AssertionError, "Already in a cache");
- return NULL;
+ PyErr_SetString(PyExc_AssertionError, "Already in a cache");
+ return NULL;
}
- if (PyDict_SetItem(self->data, key, v) < 0)
- return NULL;
- /* the dict should have a borrowed reference */
- PyObject_GC_UnTrack((void *)self->data);
- Py_DECREF(v);
+ if (PyDict_SetItem(self->data, key, v) < 0)
+ return NULL;
+ /* the dict should have a borrowed reference */
+ PyObject_GC_UnTrack((void *)self->data);
+ Py_DECREF(v);
- Py_INCREF(self);
- p->cache = (PerCache *)self;
- Py_INCREF(self->jar);
- p->jar = self->jar;
- Py_INCREF(key);
- p->oid = key;
- p->state = cPersistent_GHOST_STATE;
+ Py_INCREF(self);
+ p->cache = (PerCache *)self;
+ Py_INCREF(self->jar);
+ p->jar = self->jar;
+ Py_INCREF(key);
+ p->oid = key;
+ p->state = cPersistent_GHOST_STATE;
}
- Py_RETURN_NONE;
+ Py_RETURN_NONE;
}
static struct PyMethodDef cc_methods[] = {
- {"items", (PyCFunction)cc_items, METH_NOARGS,
- "Return list of oid, object pairs for all items in cache."},
- {"lru_items", (PyCFunction)cc_lru_items, METH_NOARGS,
- "List (oid, object) pairs from the lru list, as 2-tuples."},
- {"klass_items", (PyCFunction)cc_klass_items, METH_NOARGS,
- "List (oid, object) pairs of cached persistent classes."},
- {"full_sweep", (PyCFunction)cc_full_sweep, METH_VARARGS,
- "full_sweep() -- Perform a full sweep of the cache."},
- {"minimize", (PyCFunction)cc_minimize, METH_VARARGS,
- "minimize([ignored]) -- Remove as many objects as possible\n\n"
- "Ghostify all objects that are not modified. Takes an optional\n"
- "argument, but ignores it."},
- {"incrgc", (PyCFunction)cc_incrgc, METH_VARARGS,
- "incrgc() -- Perform incremental garbage collection\n\n"
- "This method had been depricated!"
- "Some other implementations support an optional parameter 'n' which\n"
- "indicates a repetition count; this value is ignored."},
- {"invalidate", (PyCFunction)cc_invalidate, METH_O,
- "invalidate(oids) -- invalidate one, many, or all ids"},
- {"get", (PyCFunction)cc_get, METH_VARARGS,
- "get(key [, default]) -- get an item, or a default"},
- {"ringlen", (PyCFunction)cc_ringlen, METH_NOARGS,
- "ringlen() -- Returns number of non-ghost items in cache."},
- {"debug_info", (PyCFunction)cc_debug_info, METH_NOARGS,
- "debug_info() -- Returns debugging data about objects in the cache."},
- {"update_object_size_estimation",
- (PyCFunction)cc_update_object_size_estimation,
- METH_VARARGS,
- "update_object_size_estimation(oid, new_size) -- "
- "update the caches size estimation for *oid* "
- "(if this is known to the cache)."},
- {"new_ghost", (PyCFunction)cc_new_ghost, METH_VARARGS,
- "new_ghost() -- Initialize a ghost and add it to the cache."},
- {NULL, NULL} /* sentinel */
+ {"items", (PyCFunction)cc_items, METH_NOARGS,
+ "Return list of oid, object pairs for all items in cache."},
+
+ {"lru_items", (PyCFunction)cc_lru_items, METH_NOARGS,
+ "List (oid, object) pairs from the lru list, as 2-tuples."},
+
+ {"klass_items", (PyCFunction)cc_klass_items, METH_NOARGS,
+ "List (oid, object) pairs of cached persistent classes."},
+
+ {"full_sweep", (PyCFunction)cc_full_sweep, METH_VARARGS,
+ "full_sweep() -- Perform a full sweep of the cache."},
+
+ {"minimize", (PyCFunction)cc_minimize, METH_VARARGS,
+ "minimize([ignored]) -- Remove as many objects as possible\n\n"
+ "Ghostify all objects that are not modified. Takes an optional\n"
+ "argument, but ignores it."},
+
+ {"incrgc", (PyCFunction)cc_incrgc, METH_VARARGS,
+ "incrgc() -- Perform incremental garbage collection\n\n"
+ "This method had been depricated!"
+ "Some other implementations support an optional parameter 'n' which\n"
+ "indicates a repetition count; this value is ignored."},
+
+ {"invalidate", (PyCFunction)cc_invalidate, METH_O,
+ "invalidate(oids) -- invalidate one, many, or all ids"},
+
+ {"get", (PyCFunction)cc_get, METH_VARARGS,
+ "get(key [, default]) -- get an item, or a default"},
+
+ {"ringlen", (PyCFunction)cc_ringlen, METH_NOARGS,
+ "ringlen() -- Returns number of non-ghost items in cache."},
+
+ {"debug_info", (PyCFunction)cc_debug_info, METH_NOARGS,
+ "debug_info() -- Returns debugging data about objects in the cache."},
+
+ {"update_object_size_estimation",
+ (PyCFunction)cc_update_object_size_estimation, METH_VARARGS,
+ "update_object_size_estimation(oid, new_size) -- "
+ "update the caches size estimation for *oid* "
+ "(if this is known to the cache)."},
+
+ {"new_ghost", (PyCFunction)cc_new_ghost, METH_VARARGS,
+ "new_ghost() -- Initialize a ghost and add it to the cache."},
+
+ {NULL, NULL} /* sentinel */
};
static int
cc_init(ccobject *self, PyObject *args, PyObject *kwds)
{
- int cache_size = 100;
- PY_LONG_LONG cache_size_bytes = 0;
- PyObject *jar;
+ int cache_size = 100;
+ PY_LONG_LONG cache_size_bytes = 0;
+ PyObject *jar;
- if (!PyArg_ParseTuple(args, "O|iL", &jar, &cache_size, &cache_size_bytes))
- return -1;
+ if (!PyArg_ParseTuple(args, "O|iL", &jar, &cache_size, &cache_size_bytes))
+ return -1;
- self->jar = NULL;
- self->data = PyDict_New();
- if (self->data == NULL)
+ self->jar = NULL;
+ self->data = PyDict_New();
+ if (self->data == NULL)
{
- Py_DECREF(self);
- return -1;
+ Py_DECREF(self);
+ return -1;
}
- /* Untrack the dict mapping oids to objects.
+ /* Untrack the dict mapping oids to objects.
- The dict contains uncounted references to ghost objects, so it
- isn't safe for GC to visit it. If GC finds an object with more
- referents that refcounts, it will die with an assertion failure.
+ The dict contains uncounted references to ghost objects, so it
+ isn't safe for GC to visit it. If GC finds an object with more
+ referents that refcounts, it will die with an assertion failure.
- When the cache participates in GC, it will need to traverse the
- objects in the doubly-linked list, which will account for all the
- non-ghost objects.
- */
- PyObject_GC_UnTrack((void *)self->data);
- self->jar = jar;
- Py_INCREF(jar);
- self->cache_size = cache_size;
- self->cache_size_bytes = cache_size_bytes;
- self->non_ghost_count = 0;
- self->total_estimated_size = 0;
- self->klass_count = 0;
- self->cache_drain_resistance = 0;
- self->ring_lock = 0;
- self->ring_home.r_next = &self->ring_home;
- self->ring_home.r_prev = &self->ring_home;
- return 0;
+ When the cache participates in GC, it will need to traverse the
+ objects in the doubly-linked list, which will account for all the
+ non-ghost objects.
+ */
+ PyObject_GC_UnTrack((void *)self->data);
+ self->jar = jar;
+ Py_INCREF(jar);
+ self->cache_size = cache_size;
+ self->cache_size_bytes = cache_size_bytes;
+ self->non_ghost_count = 0;
+ self->total_estimated_size = 0;
+ self->klass_count = 0;
+ self->cache_drain_resistance = 0;
+ self->ring_lock = 0;
+ self->ring_home.r_next = &self->ring_home;
+ self->ring_home.r_prev = &self->ring_home;
+ return 0;
}
static void
cc_dealloc(ccobject *self)
{
- Py_XDECREF(self->data);
- Py_XDECREF(self->jar);
- PyObject_GC_Del(self);
+ Py_XDECREF(self->data);
+ Py_XDECREF(self->jar);
+ PyObject_GC_Del(self);
}
static int
cc_clear(ccobject *self)
{
- Py_ssize_t pos = 0;
- PyObject *k, *v;
- /* Clearing the cache is delicate.
+ Py_ssize_t pos = 0;
+ PyObject *k, *v;
+ /* Clearing the cache is delicate.
- A non-ghost object will show up in the ring and in the dict. If
- we deallocating the dict before clearing the ring, the GC will
- decref each object in the dict. Since the dict references are
- uncounted, this will lead to objects having negative refcounts.
+ A non-ghost object will show up in the ring and in the dict. If
+ we deallocating the dict before clearing the ring, the GC will
+ decref each object in the dict. Since the dict references are
+ uncounted, this will lead to objects having negative refcounts.
- Freeing the non-ghost objects should eliminate many objects from
- the cache, but there may still be ghost objects left. It's
- not safe to decref the dict until it's empty, so we need to manually
- clear those out of the dict, too. We accomplish that by replacing
- all the ghost objects with None.
- */
+ Freeing the non-ghost objects should eliminate many objects from
+ the cache, but there may still be ghost objects left. It's
+ not safe to decref the dict until it's empty, so we need to manually
+ clear those out of the dict, too. We accomplish that by replacing
+ all the ghost objects with None.
+ */
- /* We don't need to lock the ring, because the cache is unreachable.
- It should be impossible for anyone to be modifying the cache.
- */
- assert(! self->ring_lock);
+ /* We don't need to lock the ring, because the cache is unreachable.
+ It should be impossible for anyone to be modifying the cache.
+ */
+ assert(! self->ring_lock);
- while (self->ring_home.r_next != &self->ring_home)
+ while (self->ring_home.r_next != &self->ring_home)
{
- CPersistentRing *here = self->ring_home.r_next;
- cPersistentObject *o = OBJECT_FROM_RING(self, here);
+ CPersistentRing *here = self->ring_home.r_next;
+ cPersistentObject *o = OBJECT_FROM_RING(self, here);
- if (o->cache)
+ if (o->cache)
{
- Py_INCREF(o); /* account for uncounted reference */
- if (PyDict_DelItem(self->data, o->oid) < 0)
- return -1;
+ Py_INCREF(o); /* account for uncounted reference */
+ if (PyDict_DelItem(self->data, o->oid) < 0)
+ return -1;
}
- o->cache = NULL;
- Py_DECREF(self);
- self->ring_home.r_next = here->r_next;
- o->ring.r_prev = NULL;
- o->ring.r_next = NULL;
- Py_DECREF(o);
- here = here->r_next;
+ o->cache = NULL;
+ Py_DECREF(self);
+ self->ring_home.r_next = here->r_next;
+ o->ring.r_prev = NULL;
+ o->ring.r_next = NULL;
+ Py_DECREF(o);
+ here = here->r_next;
}
- Py_XDECREF(self->jar);
+ Py_XDECREF(self->jar);
- while (PyDict_Next(self->data, &pos, &k, &v))
+ while (PyDict_Next(self->data, &pos, &k, &v))
{
- Py_INCREF(v);
- if (PyDict_SetItem(self->data, k, Py_None) < 0)
- return -1;
+ Py_INCREF(v);
+ if (PyDict_SetItem(self->data, k, Py_None) < 0)
+ return -1;
}
- Py_XDECREF(self->data);
- self->data = NULL;
- self->jar = NULL;
- return 0;
+ Py_XDECREF(self->data);
+ self->data = NULL;
+ self->jar = NULL;
+ return 0;
}
static int
cc_traverse(ccobject *self, visitproc visit, void *arg)
{
- int err;
- CPersistentRing *here;
+ int err;
+ CPersistentRing *here;
- /* If we're in the midst of cleaning up old objects, the ring contains
- * assorted junk we must not pass on to the visit() callback. This
- * should be rare (our cleanup code would need to have called back
- * into Python, which in turn triggered Python's gc). When it happens,
- * simply don't chase any pointers. The cache will appear to be a
- * source of external references then, and at worst we miss cleaning
- * up a dead cycle until the next time Python's gc runs.
- */
- if (self->ring_lock)
- return 0;
+ /* If we're in the midst of cleaning up old objects, the ring contains
+ * assorted junk we must not pass on to the visit() callback. This
+ * should be rare (our cleanup code would need to have called back
+ * into Python, which in turn triggered Python's gc). When it happens,
+ * simply don't chase any pointers. The cache will appear to be a
+ * source of external references then, and at worst we miss cleaning
+ * up a dead cycle until the next time Python's gc runs.
+ */
+ if (self->ring_lock)
+ return 0;
#define VISIT(SLOT) \
- if (SLOT) { \
- err = visit((PyObject *)(SLOT), arg); \
- if (err) \
- return err; \
- }
+ if (SLOT) { \
+ err = visit((PyObject *)(SLOT), arg); \
+ if (err) \
+ return err; \
+ }
- VISIT(self->jar);
+ VISIT(self->jar);
- here = self->ring_home.r_next;
+ here = self->ring_home.r_next;
- /* It is possible that an object is traversed after it is cleared.
- In that case, there is no ring.
- */
- if (!here)
- return 0;
+ /* It is possible that an object is traversed after it is cleared.
+ In that case, there is no ring.
+ */
+ if (!here)
+ return 0;
- while (here != &self->ring_home)
+ while (here != &self->ring_home)
{
- cPersistentObject *o = OBJECT_FROM_RING(self, here);
- VISIT(o);
- here = here->r_next;
+ cPersistentObject *o = OBJECT_FROM_RING(self, here);
+ VISIT(o);
+ here = here->r_next;
}
#undef VISIT
- return 0;
+ return 0;
}
static Py_ssize_t
cc_length(ccobject *self)
{
- return PyObject_Length(self->data);
+ return PyObject_Length(self->data);
}
static PyObject *
cc_subscript(ccobject *self, PyObject *key)
{
- PyObject *r;
+ PyObject *r;
- r = PyDict_GetItem(self->data, key);
- if (r == NULL)
+ r = PyDict_GetItem(self->data, key);
+ if (r == NULL)
{
- PyErr_SetObject(PyExc_KeyError, key);
- return NULL;
+ PyErr_SetObject(PyExc_KeyError, key);
+ return NULL;
}
- Py_INCREF(r);
+ Py_INCREF(r);
- return r;
+ return r;
}
static int
cc_add_item(ccobject *self, PyObject *key, PyObject *v)
{
- int result;
- PyObject *oid, *object_again, *jar;
- cPersistentObject *p;
+ int result;
+ PyObject *oid, *object_again, *jar;
+ cPersistentObject *p;
- /* Sanity check the value given to make sure it is allowed in the cache */
- if (PyType_Check(v))
+ /* Sanity check the value given to make sure it is allowed in the cache */
+ if (PyType_Check(v))
{
- /* Its a persistent class, such as a ZClass. Thats ok. */
+ /* Its a persistent class, such as a ZClass. Thats ok. */
}
- else if (v->ob_type->tp_basicsize < sizeof(cPersistentObject))
+ else if (v->ob_type->tp_basicsize < sizeof(cPersistentObject))
{
- /* If it's not an instance of a persistent class, (ie Python
- classes that derive from persistent.Persistent, BTrees,
- etc), report an error.
+ /* If it's not an instance of a persistent class, (ie Python
+ classes that derive from persistent.Persistent, BTrees,
+ etc), report an error.
- TODO: checking sizeof() seems a poor test.
- */
- PyErr_SetString(PyExc_TypeError,
- "Cache values must be persistent objects.");
- return -1;
+ TODO: checking sizeof() seems a poor test.
+ */
+ PyErr_SetString(PyExc_TypeError,
+ "Cache values must be persistent objects.");
+ return -1;
}
- /* Can't access v->oid directly because the object might be a
- * persistent class.
- */
- oid = PyObject_GetAttr(v, py__p_oid);
- if (oid == NULL)
- return -1;
- if (! PyBytes_Check(oid))
+ /* Can't access v->oid directly because the object might be a
+ * persistent class.
+ */
+ oid = PyObject_GetAttr(v, py__p_oid);
+ if (oid == NULL)
+ return -1;
+ if (! PyBytes_Check(oid))
{
- Py_DECREF(oid);
- PyErr_Format(PyExc_TypeError,
- "Cached object oid must be a string, not a %s",
- oid->ob_type->tp_name);
-
- return -1;
+ Py_DECREF(oid);
+ PyErr_Format(PyExc_TypeError,
+ "Cached object oid must be a string, not a %s",
+ oid->ob_type->tp_name);
+
+ return -1;
}
- /* we know they are both strings.
- * now check if they are the same string.
- */
- result = PyObject_RichCompareBool(key, oid, Py_NE);
- Py_DECREF(oid);
- if (result < 0)
+ /* we know they are both strings.
+ * now check if they are the same string.
+ */
+ result = PyObject_RichCompareBool(key, oid, Py_NE);
+ Py_DECREF(oid);
+ if (result < 0)
{
- return -1;
+ return -1;
}
- if (result)
+ if (result)
{
- PyErr_SetString(PyExc_ValueError, "Cache key does not match oid");
- return -1;
+ PyErr_SetString(PyExc_ValueError, "Cache key does not match oid");
+ return -1;
}
- /* useful sanity check, but not strictly an invariant of this class */
- jar = PyObject_GetAttr(v, py__p_jar);
- if (jar == NULL)
- return -1;
- if (jar==Py_None)
+ /* useful sanity check, but not strictly an invariant of this class */
+ jar = PyObject_GetAttr(v, py__p_jar);
+ if (jar == NULL)
+ return -1;
+ if (jar==Py_None)
{
- Py_DECREF(jar);
- PyErr_SetString(PyExc_ValueError,
- "Cached object jar missing");
- return -1;
+ Py_DECREF(jar);
+ PyErr_SetString(PyExc_ValueError,
+ "Cached object jar missing");
+ return -1;
}
- Py_DECREF(jar);
+ Py_DECREF(jar);
- object_again = PyDict_GetItem(self->data, key);
- if (object_again)
+ object_again = PyDict_GetItem(self->data, key);
+ if (object_again)
{
- if (object_again != v)
+ if (object_again != v)
{
- PyErr_SetString(PyExc_ValueError,
- "A different object already has the same oid");
- return -1;
+ PyErr_SetString(PyExc_ValueError,
+ "A different object already has the same oid");
+ return -1;
}
- else
+ else
{
- /* re-register under the same oid - no work needed */
- return 0;
+ /* re-register under the same oid - no work needed */
+ return 0;
}
}
- if (PyType_Check(v))
+ if (PyType_Check(v))
{
- if (PyDict_SetItem(self->data, key, v) < 0)
- return -1;
- PyObject_GC_UnTrack((void *)self->data);
- self->klass_count++;
- return 0;
+ if (PyDict_SetItem(self->data, key, v) < 0)
+ return -1;
+ PyObject_GC_UnTrack((void *)self->data);
+ self->klass_count++;
+ return 0;
}
- else
+ else
{
- PerCache *cache = ((cPersistentObject *)v)->cache;
- if (cache)
+ PerCache *cache = ((cPersistentObject *)v)->cache;
+ if (cache)
{
- if (cache != (PerCache *)self)
- /* This object is already in a different cache. */
- PyErr_SetString(PyExc_ValueError,
- "Cache values may only be in one cache.");
- return -1;
+ if (cache != (PerCache *)self)
+ /* This object is already in a different cache. */
+ PyErr_SetString(PyExc_ValueError,
+ "Cache values may only be in one cache.");
+ return -1;
}
- /* else:
+ /* else:
- This object is already one of ours, which is ok. It
- would be very strange if someone was trying to register
- the same object under a different key.
- */
+ This object is already one of ours, which is ok. It
+ would be very strange if someone was trying to register
+ the same object under a different key.
+ */
}
- if (PyDict_SetItem(self->data, key, v) < 0)
- return -1;
- /* the dict should have a borrowed reference */
- PyObject_GC_UnTrack((void *)self->data);
- Py_DECREF(v);
+ if (PyDict_SetItem(self->data, key, v) < 0)
+ return -1;
+ /* the dict should have a borrowed reference */
+ PyObject_GC_UnTrack((void *)self->data);
+ Py_DECREF(v);
- p = (cPersistentObject *)v;
- Py_INCREF(self);
- p->cache = (PerCache *)self;
- if (p->state >= 0)
+ p = (cPersistentObject *)v;
+ Py_INCREF(self);
+ p->cache = (PerCache *)self;
+ if (p->state >= 0)
{
- /* insert this non-ghost object into the ring just
- behind the home position. */
- self->non_ghost_count++;
- ring_add(&self->ring_home, &p->ring);
- /* this list should have a new reference to the object */
- Py_INCREF(v);
+ /* insert this non-ghost object into the ring just
+ behind the home position. */
+ self->non_ghost_count++;
+ ring_add(&self->ring_home, &p->ring);
+ /* this list should have a new reference to the object */
+ Py_INCREF(v);
}
- return 0;
+ return 0;
}
static int
cc_del_item(ccobject *self, PyObject *key)
{
- PyObject *v;
- cPersistentObject *p;
+ PyObject *v;
+ cPersistentObject *p;
- /* unlink this item from the ring */
- v = PyDict_GetItem(self->data, key);
- if (v == NULL)
+ /* unlink this item from the ring */
+ v = PyDict_GetItem(self->data, key);
+ if (v == NULL)
{
- PyErr_SetObject(PyExc_KeyError, key);
- return -1;
+ PyErr_SetObject(PyExc_KeyError, key);
+ return -1;
}
- if (PyType_Check(v))
+ if (PyType_Check(v))
{
- self->klass_count--;
+ self->klass_count--;
}
- else
+ else
{
- p = (cPersistentObject *)v;
- if (p->state >= 0)
+ p = (cPersistentObject *)v;
+ if (p->state >= 0)
{
- self->non_ghost_count--;
- ring_del(&p->ring);
- /* The DelItem below will account for the reference
- held by the list. */
+ self->non_ghost_count--;
+ ring_del(&p->ring);
+ /* The DelItem below will account for the reference
+ held by the list. */
}
- else
+ else
{
- /* This is a ghost object, so we haven't kept a reference
- count on it. For it have stayed alive this long
- someone else must be keeping a reference to
- it. Therefore we need to temporarily give it back a
- reference count before calling DelItem below */
- Py_INCREF(v);
+ /* This is a ghost object, so we haven't kept a reference
+ count on it. For it have stayed alive this long
+ someone else must be keeping a reference to
+ it. Therefore we need to temporarily give it back a
+ reference count before calling DelItem below */
+ Py_INCREF(v);
}
- Py_DECREF((PyObject *)p->cache);
- p->cache = NULL;
+ Py_DECREF((PyObject *)p->cache);
+ p->cache = NULL;
}
- if (PyDict_DelItem(self->data, key) < 0)
+ if (PyDict_DelItem(self->data, key) < 0)
{
- PyErr_SetString(PyExc_RuntimeError,
- "unexpectedly couldn't remove key in cc_ass_sub");
- return -1;
+ PyErr_SetString(PyExc_RuntimeError,
+ "unexpectedly couldn't remove key in cc_ass_sub");
+ return -1;
}
- return 0;
+ return 0;
}
static int
cc_ass_sub(ccobject *self, PyObject *key, PyObject *v)
{
- if (!PyBytes_Check(key))
+ if (!PyBytes_Check(key))
{
- PyErr_Format(PyExc_TypeError,
- "cPickleCache key must be a string, not a %s",
- key->ob_type->tp_name);
- return -1;
+ PyErr_Format(PyExc_TypeError,
+ "cPickleCache key must be a string, not a %s",
+ key->ob_type->tp_name);
+ return -1;
}
- if (v)
- return cc_add_item(self, key, v);
- else
- return cc_del_item(self, key);
+ if (v)
+ return cc_add_item(self, key, v);
+ else
+ return cc_del_item(self, key);
}
static PyMappingMethods cc_as_mapping =
- {
- (lenfunc)cc_length, /*mp_length*/
- (binaryfunc)cc_subscript, /*mp_subscript*/
- (objobjargproc)cc_ass_sub, /*mp_ass_subscript*/
- };
+{
+ (lenfunc)cc_length, /* mp_length */
+ (binaryfunc)cc_subscript, /* mp_subscript */
+ (objobjargproc)cc_ass_sub, /* mp_ass_subscript */
+};
static PyObject *
cc_cache_data(ccobject *self, void *context)
{
- return PyDict_Copy(self->data);
+ return PyDict_Copy(self->data);
}
static PyGetSetDef cc_getsets[] =
- {
+{
{"cache_data", (getter)cc_cache_data},
{NULL}
- };
+};
-static PyMemberDef cc_members[] = {
- {"cache_size", T_INT, offsetof(ccobject, cache_size)},
- {"cache_size_bytes", T_LONG, offsetof(ccobject, cache_size_bytes)},
- {"total_estimated_size", T_LONG, offsetof(ccobject, total_estimated_size),
- READONLY},
- {"cache_drain_resistance", T_INT,
- offsetof(ccobject, cache_drain_resistance)},
- {"cache_non_ghost_count", T_INT, offsetof(ccobject, non_ghost_count), READONLY},
- {"cache_klass_count", T_INT, offsetof(ccobject, klass_count), READONLY},
- {NULL}
+static PyMemberDef cc_members[] =
+{
+ {"cache_size", T_INT, offsetof(ccobject, cache_size)},
+ {"cache_size_bytes", T_LONG, offsetof(ccobject, cache_size_bytes)},
+ {"total_estimated_size", T_LONG, offsetof(ccobject, total_estimated_size),
+ READONLY},
+ {"cache_drain_resistance", T_INT,
+ offsetof(ccobject, cache_drain_resistance)},
+ {"cache_non_ghost_count", T_INT, offsetof(ccobject, non_ghost_count),
+ READONLY},
+ {"cache_klass_count", T_INT, offsetof(ccobject, klass_count), READONLY},
+ {NULL}
};
/* This module is compiled as a shared library. Some compilers don't
@@ -1252,114 +1265,127 @@
*/
#define DEFERRED_ADDRESS(ADDR) 0
-static PyTypeObject Cctype = {
- PyVarObject_HEAD_INIT(DEFERRED_ADDRESS(&PyType_Type), 0)
- "persistent.PickleCache", /* tp_name */
- sizeof(ccobject), /* tp_basicsize */
- 0, /* tp_itemsize */
- (destructor)cc_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 */
- &cc_as_mapping, /* tp_as_mapping */
- 0, /* tp_hash */
- 0, /* tp_call */
- 0, /* tp_str */
- 0, /* tp_getattro */
- 0, /* tp_setattro */
- 0, /* tp_as_buffer */
- Py_TPFLAGS_DEFAULT |
- Py_TPFLAGS_BASETYPE |
- Py_TPFLAGS_HAVE_GC, /* tp_flags */
- 0, /* tp_doc */
- (traverseproc)cc_traverse, /* tp_traverse */
- (inquiry)cc_clear, /* tp_clear */
- 0, /* tp_richcompare */
- 0, /* tp_weaklistoffset */
- 0, /* tp_iter */
- 0, /* tp_iternext */
- cc_methods, /* tp_methods */
- cc_members, /* tp_members */
- cc_getsets, /* tp_getset */
- 0, /* tp_base */
- 0, /* tp_dict */
- 0, /* tp_descr_get */
- 0, /* tp_descr_set */
- 0, /* tp_dictoffset */
- (initproc)cc_init, /* tp_init */
+static PyTypeObject Cctype =
+{
+ PyVarObject_HEAD_INIT(DEFERRED_ADDRESS(&PyType_Type), 0)
+ "persistent.PickleCache", /* tp_name */
+ sizeof(ccobject), /* tp_basicsize */
+ 0, /* tp_itemsize */
+ (destructor)cc_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 */
+ &cc_as_mapping, /* tp_as_mapping */
+ 0, /* tp_hash */
+ 0, /* tp_call */
+ 0, /* tp_str */
+ 0, /* tp_getattro */
+ 0, /* tp_setattro */
+ 0, /* tp_as_buffer */
+ Py_TPFLAGS_DEFAULT |
+ Py_TPFLAGS_BASETYPE |
+ Py_TPFLAGS_HAVE_GC, /* tp_flags */
+ 0, /* tp_doc */
+ (traverseproc)cc_traverse, /* tp_traverse */
+ (inquiry)cc_clear, /* tp_clear */
+ 0, /* tp_richcompare */
+ 0, /* tp_weaklistoffset */
+ 0, /* tp_iter */
+ 0, /* tp_iternext */
+ cc_methods, /* tp_methods */
+ cc_members, /* tp_members */
+ cc_getsets, /* tp_getset */
+ 0, /* tp_base */
+ 0, /* tp_dict */
+ 0, /* tp_descr_get */
+ 0, /* tp_descr_set */
+ 0, /* tp_dictoffset */
+ (initproc)cc_init, /* tp_init */
};
#ifdef PY3K
-static struct PyModuleDef moduledef = {
- PyModuleDef_HEAD_INIT,
- "cPickleCache", /* m_name */
- cPickleCache_doc_string, /* m_doc */
- -1, /* m_size */
- NULL, /* m_methods */
- NULL, /* m_reload */
- NULL, /* m_traverse */
- NULL, /* m_clear */
- NULL, /* m_free */
- };
+static struct PyModuleDef moduledef =
+{
+ PyModuleDef_HEAD_INIT,
+ "cPickleCache", /* m_name */
+ cPickleCache_doc_string, /* m_doc */
+ -1, /* m_size */
+ NULL, /* m_methods */
+ NULL, /* m_reload */
+ NULL, /* m_traverse */
+ NULL, /* m_clear */
+ NULL, /* m_free */
+};
#endif
-void
-initcPickleCache(void)
+static PyObject*
+module_init(void)
{
- PyObject *m;
+ PyObject *module;
-
#ifdef PY3K
- ((PyObject*)&Cctype)->ob_type = &PyType_Type;
+ ((PyObject*)&Cctype)->ob_type = &PyType_Type;
#else
- Cctype.ob_type = &PyType_Type;
+ Cctype.ob_type = &PyType_Type;
#endif
- Cctype.tp_new = &PyType_GenericNew;
- if (PyType_Ready(&Cctype) < 0)
+ Cctype.tp_new = &PyType_GenericNew;
+ if (PyType_Ready(&Cctype) < 0)
{
- return;
+ return NULL;
}
-
#ifdef PY3K
- m = PyModule_Create(&moduledef);
+ module = PyModule_Create(&moduledef);
#else
- m = Py_InitModule3("cPickleCache", NULL, cPickleCache_doc_string);
+ module = Py_InitModule3("cPickleCache", NULL, cPickleCache_doc_string);
#endif
#ifdef PY3K
- capi = (cPersistenceCAPIstruct *)PyCapsule_Import(
- "persistent.cPersistence.CAPI", 0);
+ capi = (cPersistenceCAPIstruct *)PyCapsule_Import(CAPI_CAPSULE_NAME, 0);
#else
- capi = (cPersistenceCAPIstruct *)PyCObject_Import(
- "persistent.cPersistence", "CAPI");
+ capi = (cPersistenceCAPIstruct *)PyCObject_Import(
+ "persistent.cPersistence", "CAPI");
#endif
- if (!capi)
- return;
- capi->percachedel = (percachedelfunc)cc_oid_unreferenced;
+ if (!capi)
+ return NULL;
+ capi->percachedel = (percachedelfunc)cc_oid_unreferenced;
- py__p_changed = INTERN("_p_changed");
- if (!py__p_changed)
- return;
- py__p_deactivate = INTERN("_p_deactivate");
- if (!py__p_deactivate)
- return;
- py__p_jar = INTERN("_p_jar");
- if (!py__p_jar)
- return;
- py__p_oid = INTERN("_p_oid");
- if (!py__p_oid)
- return;
+ py__p_changed = INTERN("_p_changed");
+ if (!py__p_changed)
+ return NULL;
+ py__p_deactivate = INTERN("_p_deactivate");
+ if (!py__p_deactivate)
+ return NULL;
+ py__p_jar = INTERN("_p_jar");
+ if (!py__p_jar)
+ return NULL;
+ py__p_oid = INTERN("_p_oid");
+ if (!py__p_oid)
+ return NULL;
- if (PyModule_AddStringConstant(m, "cache_variant", "stiff/c") < 0)
- return;
+ if (PyModule_AddStringConstant(module, "cache_variant", "stiff/c") < 0)
+ return NULL;
- /* This leaks a reference to Cctype, but it doesn't matter. */
- if (PyModule_AddObject(m, "PickleCache", (PyObject *)&Cctype) < 0)
- return;
+ /* This leaks a reference to Cctype, but it doesn't matter. */
+ if (PyModule_AddObject(module, "PickleCache", (PyObject *)&Cctype) < 0)
+ return NULL;
+
+ return module;
}
+
+#ifdef PY3K
+PyMODINIT_FUNC PyInit_cPickleCache(void)
+{
+ return module_init();
+}
+#else
+PyMODINIT_FUNC initcPickleCache(void)
+{
+ module_init();
+}
+#endif
Modified: persistent/trunk/persistent/tests/test_persistence.py
===================================================================
--- persistent/trunk/persistent/tests/test_persistence.py 2012-12-14 00:21:12 UTC (rev 128631)
+++ persistent/trunk/persistent/tests/test_persistence.py 2012-12-14 00:21:15 UTC (rev 128632)
@@ -604,6 +604,7 @@
def test___setattr___v__name(self):
class Derived(self._getTargetClass()):
pass
+ import pdb; pdb.set_trace()
inst, jar, OID = self._makeOneWithJar(Derived)
self._clearMRU(jar)
inst._v_foo = 'bar'
Modified: persistent/trunk/persistent/tests/test_timestamp.py
===================================================================
--- persistent/trunk/persistent/tests/test_timestamp.py 2012-12-14 00:21:12 UTC (rev 128631)
+++ persistent/trunk/persistent/tests/test_timestamp.py 2012-12-14 00:21:15 UTC (rev 128632)
@@ -118,14 +118,15 @@
def test_laterThan_invalid(self):
from persistent.timestamp import _makeOctets
+ ERRORS = (ValueError, TypeError)
SERIAL = _makeOctets('\x01' * 8)
ts = self._makeOne(SERIAL)
- self.assertRaises(ValueError, ts.laterThan, None)
- self.assertRaises(ValueError, ts.laterThan, '')
- self.assertRaises(ValueError, ts.laterThan, ())
- self.assertRaises(ValueError, ts.laterThan, [])
- self.assertRaises(ValueError, ts.laterThan, {})
- self.assertRaises(ValueError, ts.laterThan, object())
+ self.assertRaises(ERRORS, ts.laterThan, None)
+ self.assertRaises(ERRORS, ts.laterThan, '')
+ self.assertRaises(ERRORS, ts.laterThan, ())
+ self.assertRaises(ERRORS, ts.laterThan, [])
+ self.assertRaises(ERRORS, ts.laterThan, {})
+ self.assertRaises(ERRORS, ts.laterThan, object())
def test_laterThan_self_is_earlier(self):
from persistent.timestamp import _makeOctets
@@ -152,7 +153,7 @@
ts = self._makeOne(SERIAL)
self.assertEqual(repr(ts), _native(SERIAL))
-class TimeStampTests(unittest.TestCase):
+class TimeStampTests(pyTimeStampTests):
def _getTargetClass(self):
from persistent.timestamp import TimeStamp
More information about the checkins
mailing list