summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorFederico Di Gregorio <fog@initd.org>2008-07-26 15:10:02 +0200
committerFederico Di Gregorio <fog@initd.org>2008-07-26 15:10:02 +0200
commitceee4c816fde88fa4ab32074b923bf4d31cd3598 (patch)
tree6aefd58fd5d4e2565eeeb70c27938a8f5dfc3bf6
parente95a4d9d2ee995715f09431039360de6717e4738 (diff)
parenta2f3e4a3acd58afb09438be186e5fb0a98620820 (diff)
downloadpsycopg2-ceee4c816fde88fa4ab32074b923bf4d31cd3598.tar.gz
Merge from jh
-rw-r--r--ChangeLog50
-rw-r--r--psycopg/adapter_asis.c17
-rw-r--r--psycopg/adapter_binary.c25
-rw-r--r--psycopg/adapter_datetime.c19
-rw-r--r--psycopg/adapter_list.c26
-rw-r--r--psycopg/adapter_mxdatetime.c19
-rw-r--r--psycopg/adapter_pboolean.c19
-rw-r--r--psycopg/adapter_qstring.c29
-rw-r--r--psycopg/connection_type.c28
-rw-r--r--psycopg/cursor_int.c8
-rw-r--r--psycopg/cursor_type.c48
-rw-r--r--psycopg/lobject_type.c8
-rw-r--r--psycopg/python.h23
-rw-r--r--psycopg/typecast.c36
14 files changed, 274 insertions, 81 deletions
diff --git a/ChangeLog b/ChangeLog
index 1e2820a..cbeb111 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -3,6 +3,56 @@
* psycopg/connection_type.c: merged get_backend_pid() method
by Casey Duncan.
+2008-07-23 James Henstridge <james@jamesh.id.au>
+
+ * psycopg/lobject_type.c (lobject_setup): use
+ FORMAT_CODE_PY_SSIZE_T in Dprintf() call for 64-bit compatibility
+ when using Python 2.5 or later.
+ (lobject_dealloc): same here.
+
+2008-07-18 James Henstridge <james@jamesh.id.au>
+
+ * psycopg/adapter_qstring.c (qstring_traverse): add cyclic GC
+ traversal for quoted string adapters.
+
+ * psycopg/adapter_pboolean.c (pboolean_traverse): add cyclic GC
+ traversal for boolean adapters.
+
+ * psycopg/adapter_mxdatetime.c (mxdatetime_traverse): add cyclic
+ GC traversal for mxdatetime adapters.
+
+ * psycopg/adapter_datetime.c (pydatetime_traverse): add cyclic GC
+ traversal for datetime adapters.
+
+2008-07-01 James Henstridge <james@jamesh.id.au>
+
+ * psycopg/adapter_binary.c (binary_traverse): add cyclic GC
+ traversal for binary adapters.
+
+ * psycopg/adapter_asis.c (asis_traverse): add cyclic GC traversal
+ for AsIs adapters.
+
+ * psycopg/adapter_list.c (list_traverse): add cyclic GC traversal
+ for list adapters.
+
+2008-05-28 James Henstridge <james@jamesh.id.au>
+
+ * psycopg/cursor_type.c (cursor_setup): incref before setting
+ attributes, to make things GC-safe.
+
+ * psycopg/cursor_int.c (curs_reset): make clearing of description
+ and casts attributes GC-safe.
+
+ * psycopg/typecast.c (typecast_traverse): implement cyclic GC
+ traversal for typecasters.
+
+ * psycopg/connection_type.c:
+ * psycopg/cursor_type.c: add support for cyclic GC traversal (no
+ support for clearing).
+
+ * psycopg/python.h: add definitions for Py_CLEAR() and Py_VISIT()
+ for compatibility with old versions of Python.
+
2008-06-28 Federico Di Gregorio <fog@initd.org>
* setup.py: fixed problem with spaces in pg_config path.
diff --git a/psycopg/adapter_asis.c b/psycopg/adapter_asis.c
index 0e64eb5..2ad6ef5 100644
--- a/psycopg/adapter_asis.c
+++ b/psycopg/adapter_asis.c
@@ -96,8 +96,8 @@ asis_setup(asisObject *self, PyObject *obj)
self, ((PyObject *)self)->ob_refcnt
);
+ Py_INCREF(obj);
self->wrapped = obj;
- Py_INCREF(self->wrapped);
Dprintf("asis_setup: good asis object at %p, refcnt = "
FORMAT_CODE_PY_SSIZE_T,
@@ -106,12 +106,19 @@ asis_setup(asisObject *self, PyObject *obj)
return 0;
}
+static int
+asis_traverse(asisObject *self, visitproc visit, void *arg)
+{
+ Py_VISIT(self->wrapped);
+ return 0;
+}
+
static void
asis_dealloc(PyObject* obj)
{
asisObject *self = (asisObject *)obj;
- Py_XDECREF(self->wrapped);
+ Py_CLEAR(self->wrapped);
Dprintf("asis_dealloc: deleted asis object at %p, refcnt = "
FORMAT_CODE_PY_SSIZE_T,
@@ -141,7 +148,7 @@ asis_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
static void
asis_del(PyObject* self)
{
- PyObject_Del(self);
+ PyObject_GC_Del(self);
}
static PyObject *
@@ -183,10 +190,10 @@ PyTypeObject asisType = {
0, /*tp_setattro*/
0, /*tp_as_buffer*/
- Py_TPFLAGS_DEFAULT|Py_TPFLAGS_BASETYPE, /*tp_flags*/
+ Py_TPFLAGS_DEFAULT|Py_TPFLAGS_BASETYPE|Py_TPFLAGS_HAVE_GC, /*tp_flags*/
asisType_doc, /*tp_doc*/
- 0, /*tp_traverse*/
+ (traverseproc)asis_traverse, /*tp_traverse*/
0, /*tp_clear*/
0, /*tp_richcompare*/
diff --git a/psycopg/adapter_binary.c b/psycopg/adapter_binary.c
index 1fb9d40..306c9e5 100644
--- a/psycopg/adapter_binary.c
+++ b/psycopg/adapter_binary.c
@@ -257,8 +257,8 @@ binary_setup(binaryObject *self, PyObject *str)
self->buffer = NULL;
self->conn = NULL;
+ Py_INCREF(str);
self->wrapped = str;
- Py_INCREF(self->wrapped);
Dprintf("binary_setup: good binary object at %p, refcnt = "
FORMAT_CODE_PY_SSIZE_T,
@@ -266,14 +266,25 @@ binary_setup(binaryObject *self, PyObject *str)
return 0;
}
+static int
+binary_traverse(PyObject *obj, visitproc visit, void *arg)
+{
+ binaryObject *self = (binaryObject *)obj;
+
+ Py_VISIT(self->wrapped);
+ Py_VISIT(self->buffer);
+ Py_VISIT(self->conn);
+ return 0;
+}
+
static void
binary_dealloc(PyObject* obj)
{
binaryObject *self = (binaryObject *)obj;
- Py_XDECREF(self->wrapped);
- Py_XDECREF(self->buffer);
- Py_XDECREF(self->conn);
+ Py_CLEAR(self->wrapped);
+ Py_CLEAR(self->buffer);
+ Py_CLEAR(self->conn);
Dprintf("binary_dealloc: deleted binary object at %p, refcnt = "
FORMAT_CODE_PY_SSIZE_T,
@@ -303,7 +314,7 @@ binary_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
static void
binary_del(PyObject* self)
{
- PyObject_Del(self);
+ PyObject_GC_Del(self);
}
static PyObject *
@@ -341,11 +352,11 @@ PyTypeObject binaryType = {
0, /*tp_setattro*/
0, /*tp_as_buffer*/
- Py_TPFLAGS_DEFAULT|Py_TPFLAGS_BASETYPE, /*tp_flags*/
+ Py_TPFLAGS_DEFAULT|Py_TPFLAGS_BASETYPE|Py_TPFLAGS_HAVE_GC, /*tp_flags*/
binaryType_doc, /*tp_doc*/
- 0, /*tp_traverse*/
+ binary_traverse, /*tp_traverse*/
0, /*tp_clear*/
0, /*tp_richcompare*/
diff --git a/psycopg/adapter_datetime.c b/psycopg/adapter_datetime.c
index e9fcc1e..bf337ee 100644
--- a/psycopg/adapter_datetime.c
+++ b/psycopg/adapter_datetime.c
@@ -131,8 +131,8 @@ pydatetime_setup(pydatetimeObject *self, PyObject *obj, int type)
self, ((PyObject *)self)->ob_refcnt);
self->type = type;
+ Py_INCREF(obj);
self->wrapped = obj;
- Py_INCREF(self->wrapped);
Dprintf("pydatetime_setup: good pydatetime object at %p, refcnt = "
FORMAT_CODE_PY_SSIZE_T,
@@ -140,12 +140,21 @@ pydatetime_setup(pydatetimeObject *self, PyObject *obj, int type)
return 0;
}
+static int
+pydatetime_traverse(PyObject *obj, visitproc visit, void *arg)
+{
+ pydatetimeObject *self = (pydatetimeObject *)obj;
+
+ Py_VISIT(self->wrapped);
+ return 0;
+}
+
static void
pydatetime_dealloc(PyObject* obj)
{
pydatetimeObject *self = (pydatetimeObject *)obj;
- Py_XDECREF(self->wrapped);
+ Py_CLEAR(self->wrapped);
Dprintf("mpydatetime_dealloc: deleted pydatetime object at %p, "
"refcnt = " FORMAT_CODE_PY_SSIZE_T, obj, obj->ob_refcnt);
@@ -174,7 +183,7 @@ pydatetime_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
static void
pydatetime_del(PyObject* self)
{
- PyObject_Del(self);
+ PyObject_GC_Del(self);
}
static PyObject *
@@ -213,11 +222,11 @@ PyTypeObject pydatetimeType = {
0, /*tp_setattro*/
0, /*tp_as_buffer*/
- Py_TPFLAGS_DEFAULT|Py_TPFLAGS_BASETYPE, /*tp_flags*/
+ Py_TPFLAGS_DEFAULT|Py_TPFLAGS_BASETYPE|Py_TPFLAGS_HAVE_GC, /*tp_flags*/
pydatetimeType_doc, /*tp_doc*/
- 0, /*tp_traverse*/
+ pydatetime_traverse, /*tp_traverse*/
0, /*tp_clear*/
0, /*tp_richcompare*/
diff --git a/psycopg/adapter_list.c b/psycopg/adapter_list.c
index b6022bd..2d26c39 100644
--- a/psycopg/adapter_list.c
+++ b/psycopg/adapter_list.c
@@ -108,9 +108,9 @@ list_prepare(listObject *self, PyObject *args)
reference to it; we'll need it during the recursive adapt() call (the
encoding is here for a future expansion that will make .getquoted()
work even without a connection to the backend. */
- Py_XDECREF(self->connection);
+ Py_CLEAR(self->connection);
+ Py_INCREF(conn);
self->connection = (PyObject*)conn;
- Py_INCREF(self->connection);
Py_INCREF(Py_None);
return Py_None;
@@ -169,8 +169,8 @@ list_setup(listObject *self, PyObject *obj, const char *enc)
if (enc) self->encoding = strdup(enc);
self->connection = NULL;
+ Py_INCREF(obj);
self->wrapped = obj;
- Py_INCREF(self->wrapped);
Dprintf("list_setup: good list object at %p, refcnt = "
FORMAT_CODE_PY_SSIZE_T,
@@ -179,13 +179,23 @@ list_setup(listObject *self, PyObject *obj, const char *enc)
return 0;
}
+static int
+list_traverse(PyObject *obj, visitproc visit, void *arg)
+{
+ listObject *self = (listObject *)obj;
+
+ Py_VISIT(self->wrapped);
+ Py_VISIT(self->connection);
+ return 0;
+}
+
static void
list_dealloc(PyObject* obj)
{
listObject *self = (listObject *)obj;
- Py_XDECREF(self->wrapped);
- Py_XDECREF(self->connection);
+ Py_CLEAR(self->wrapped);
+ Py_CLEAR(self->connection);
if (self->encoding) free(self->encoding);
Dprintf("list_dealloc: deleted list object at %p, "
@@ -215,7 +225,7 @@ list_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
static void
list_del(PyObject* self)
{
- PyObject_Del(self);
+ PyObject_GC_Del(self);
}
static PyObject *
@@ -253,11 +263,11 @@ PyTypeObject listType = {
0, /*tp_setattro*/
0, /*tp_as_buffer*/
- Py_TPFLAGS_DEFAULT|Py_TPFLAGS_BASETYPE, /*tp_flags*/
+ Py_TPFLAGS_DEFAULT|Py_TPFLAGS_BASETYPE|Py_TPFLAGS_HAVE_GC, /*tp_flags*/
listType_doc, /*tp_doc*/
- 0, /*tp_traverse*/
+ list_traverse, /*tp_traverse*/
0, /*tp_clear*/
0, /*tp_richcompare*/
diff --git a/psycopg/adapter_mxdatetime.c b/psycopg/adapter_mxdatetime.c
index 48ead92..92b2181 100644
--- a/psycopg/adapter_mxdatetime.c
+++ b/psycopg/adapter_mxdatetime.c
@@ -152,8 +152,8 @@ mxdatetime_setup(mxdatetimeObject *self, PyObject *obj, int type)
);
self->type = type;
+ Py_INCREF(obj);
self->wrapped = obj;
- Py_INCREF(self->wrapped);
Dprintf("mxdatetime_setup: good mxdatetime object at %p, refcnt = "
FORMAT_CODE_PY_SSIZE_T,
@@ -162,12 +162,21 @@ mxdatetime_setup(mxdatetimeObject *self, PyObject *obj, int type)
return 0;
}
+static int
+mxdatetime_traverse(PyObject *obj, visitproc visit, void *arg)
+{
+ mxdatetimeObject *self = (mxdatetimeObject *)obj;
+
+ Py_VISIT(self->wrapped);
+ return 0;
+}
+
static void
mxdatetime_dealloc(PyObject* obj)
{
mxdatetimeObject *self = (mxdatetimeObject *)obj;
- Py_XDECREF(self->wrapped);
+ Py_CLEAR(self->wrapped);
Dprintf("mxdatetime_dealloc: deleted mxdatetime object at %p, refcnt = "
FORMAT_CODE_PY_SSIZE_T,
@@ -198,7 +207,7 @@ mxdatetime_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
static void
mxdatetime_del(PyObject* self)
{
- PyObject_Del(self);
+ PyObject_GC_Del(self);
}
static PyObject *
@@ -237,11 +246,11 @@ PyTypeObject mxdatetimeType = {
0, /*tp_setattro*/
0, /*tp_as_buffer*/
- Py_TPFLAGS_DEFAULT|Py_TPFLAGS_BASETYPE, /*tp_flags*/
+ Py_TPFLAGS_DEFAULT|Py_TPFLAGS_BASETYPE|Py_TPFLAGS_HAVE_GC, /*tp_flags*/
mxdatetimeType_doc, /*tp_doc*/
- 0, /*tp_traverse*/
+ mxdatetime_traverse, /*tp_traverse*/
0, /*tp_clear*/
0, /*tp_richcompare*/
diff --git a/psycopg/adapter_pboolean.c b/psycopg/adapter_pboolean.c
index 05d1d04..1ce80dd 100644
--- a/psycopg/adapter_pboolean.c
+++ b/psycopg/adapter_pboolean.c
@@ -106,8 +106,8 @@ pboolean_setup(pbooleanObject *self, PyObject *obj)
self, ((PyObject *)self)->ob_refcnt
);
+ Py_INCREF(obj);
self->wrapped = obj;
- Py_INCREF(self->wrapped);
Dprintf("pboolean_setup: good pboolean object at %p, refcnt = "
FORMAT_CODE_PY_SSIZE_T,
@@ -116,12 +116,21 @@ pboolean_setup(pbooleanObject *self, PyObject *obj)
return 0;
}
+static int
+pboolean_traverse(PyObject *obj, visitproc visit, void *arg)
+{
+ pbooleanObject *self = (pbooleanObject *)obj;
+
+ Py_VISIT(self->wrapped);
+ return 0;
+}
+
static void
pboolean_dealloc(PyObject* obj)
{
pbooleanObject *self = (pbooleanObject *)obj;
- Py_XDECREF(self->wrapped);
+ Py_CLEAR(self->wrapped);
Dprintf("pboolean_dealloc: deleted pboolean object at %p, refcnt = "
FORMAT_CODE_PY_SSIZE_T,
@@ -151,7 +160,7 @@ pboolean_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
static void
pboolean_del(PyObject* self)
{
- PyObject_Del(self);
+ PyObject_GC_Del(self);
}
static PyObject *
@@ -194,10 +203,10 @@ PyTypeObject pbooleanType = {
0, /*tp_setattro*/
0, /*tp_as_buffer*/
- Py_TPFLAGS_DEFAULT|Py_TPFLAGS_BASETYPE, /*tp_flags*/
+ Py_TPFLAGS_DEFAULT|Py_TPFLAGS_BASETYPE|Py_TPFLAGS_HAVE_GC, /*tp_flags*/
pbooleanType_doc, /*tp_doc*/
- 0, /*tp_traverse*/
+ pboolean_traverse, /*tp_traverse*/
0, /*tp_clear*/
0, /*tp_richcompare*/
diff --git a/psycopg/adapter_qstring.c b/psycopg/adapter_qstring.c
index f469fe4..e1eb4e1 100644
--- a/psycopg/adapter_qstring.c
+++ b/psycopg/adapter_qstring.c
@@ -213,10 +213,10 @@ qstring_prepare(qstringObject *self, PyObject *args)
Dprintf("qstring_prepare: set encoding to %s", conn->encoding);
}
- Py_XDECREF(self->conn);
+ Py_CLEAR(self->conn);
if (conn) {
+ Py_INCREF(conn);
self->conn = (PyObject*)conn;
- Py_INCREF(self->conn);
}
Py_INCREF(Py_None);
@@ -277,8 +277,8 @@ qstring_setup(qstringObject *self, PyObject *str, const char *enc)
/* FIXME: remove this orrible strdup */
if (enc) self->encoding = strdup(enc);
+ Py_INCREF(str);
self->wrapped = str;
- Py_INCREF(self->wrapped);
Dprintf("qstring_setup: good qstring object at %p, refcnt = "
FORMAT_CODE_PY_SSIZE_T,
@@ -287,14 +287,25 @@ qstring_setup(qstringObject *self, PyObject *str, const char *enc)
return 0;
}
+static int
+qstring_traverse(PyObject *obj, visitproc visit, void *arg)
+{
+ qstringObject *self = (qstringObject *)obj;
+
+ Py_VISIT(self->wrapped);
+ Py_VISIT(self->buffer);
+ Py_VISIT(self->conn);
+ return 0;
+}
+
static void
qstring_dealloc(PyObject* obj)
{
qstringObject *self = (qstringObject *)obj;
- Py_XDECREF(self->wrapped);
- Py_XDECREF(self->buffer);
- Py_XDECREF(self->conn);
+ Py_CLEAR(self->wrapped);
+ Py_CLEAR(self->buffer);
+ Py_CLEAR(self->conn);
if (self->encoding) free(self->encoding);
@@ -327,7 +338,7 @@ qstring_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
static void
qstring_del(PyObject* self)
{
- PyObject_Del(self);
+ PyObject_GC_Del(self);
}
static PyObject *
@@ -366,11 +377,11 @@ PyTypeObject qstringType = {
0, /*tp_setattro*/
0, /*tp_as_buffer*/
- Py_TPFLAGS_DEFAULT|Py_TPFLAGS_BASETYPE, /*tp_flags*/
+ Py_TPFLAGS_DEFAULT|Py_TPFLAGS_BASETYPE|Py_TPFLAGS_HAVE_GC, /*tp_flags*/
qstringType_doc, /*tp_doc*/
- 0, /*tp_traverse*/
+ qstring_traverse, /*tp_traverse*/
0, /*tp_clear*/
0, /*tp_richcompare*/
diff --git a/psycopg/connection_type.c b/psycopg/connection_type.c
index 35b116a..e03cf3d 100644
--- a/psycopg/connection_type.c
+++ b/psycopg/connection_type.c
@@ -465,11 +465,11 @@ connection_dealloc(PyObject* obj)
if (self->encoding) free(self->encoding);
if (self->critical) free(self->critical);
- Py_XDECREF(self->notice_list);
- Py_XDECREF(self->notifies);
- Py_XDECREF(self->async_cursor);
- Py_XDECREF(self->string_types);
- Py_XDECREF(self->binary_types);
+ Py_CLEAR(self->notice_list);
+ Py_CLEAR(self->notifies);
+ Py_CLEAR(self->async_cursor);
+ Py_CLEAR(self->string_types);
+ Py_CLEAR(self->binary_types);
pthread_mutex_destroy(&(self->lock));
@@ -501,7 +501,7 @@ connection_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
static void
connection_del(PyObject* self)
{
- PyObject_Del(self);
+ PyObject_GC_Del(self);
}
static PyObject *
@@ -512,6 +512,18 @@ connection_repr(connectionObject *self)
self, self->dsn, self->closed);
}
+static int
+connection_traverse(connectionObject *self, visitproc visit, void *arg)
+{
+ Py_VISIT(self->async_cursor);
+ Py_VISIT(self->notice_list);
+ Py_VISIT(self->notice_filter);
+ Py_VISIT(self->notifies);
+ Py_VISIT(self->string_types);
+ Py_VISIT(self->binary_types);
+ return 0;
+}
+
/* object type */
@@ -545,10 +557,10 @@ PyTypeObject connectionType = {
0, /*tp_setattro*/
0, /*tp_as_buffer*/
- Py_TPFLAGS_DEFAULT|Py_TPFLAGS_BASETYPE, /*tp_flags*/
+ Py_TPFLAGS_DEFAULT|Py_TPFLAGS_BASETYPE|Py_TPFLAGS_HAVE_GC, /*tp_flags*/
connectionType_doc, /*tp_doc*/
- 0, /*tp_traverse*/
+ (traverseproc)connection_traverse, /*tp_traverse*/
0, /*tp_clear*/
0, /*tp_richcompare*/
diff --git a/psycopg/cursor_int.c b/psycopg/cursor_int.c
index 483e2c4..9d3c861 100644
--- a/psycopg/cursor_int.c
+++ b/psycopg/cursor_int.c
@@ -34,15 +34,19 @@
void
curs_reset(cursorObject *self)
{
+ PyObject *tmp;
+
/* initialize some variables to default values */
self->notuples = 1;
self->rowcount = -1;
self->row = 0;
- Py_XDECREF(self->description);
+ tmp = self->description;
Py_INCREF(Py_None);
self->description = Py_None;
+ Py_XDECREF(tmp);
- Py_XDECREF(self->casts);
+ tmp = self->casts;
self->casts = NULL;
+ Py_XDECREF(tmp);
}
diff --git a/psycopg/cursor_type.c b/psycopg/cursor_type.c
index 5b0cd02..8000816 100644
--- a/psycopg/cursor_type.c
+++ b/psycopg/cursor_type.c
@@ -1590,8 +1590,8 @@ cursor_setup(cursorObject *self, connectionObject *conn, const char *name)
"argument 1 must be subclass of psycopg2._psycopg.connection");
return 1;
} */
+ Py_INCREF(conn);
self->conn = conn;
- Py_INCREF((PyObject*)self->conn);
self->closed = 0;
self->mark = conn->mark;
@@ -1607,6 +1607,7 @@ cursor_setup(cursorObject *self, connectionObject *conn, const char *name)
self->string_types = NULL;
self->binary_types = NULL;
+ Py_INCREF(Py_None);
self->description = Py_None;
Py_INCREF(Py_None);
self->pgstatus = Py_None;
@@ -1614,11 +1615,10 @@ cursor_setup(cursorObject *self, connectionObject *conn, const char *name)
self->tuple_factory = Py_None;
Py_INCREF(Py_None);
self->query = Py_None;
- Py_INCREF(Py_None);
/* default tzinfo factory */
+ Py_INCREF(pyPsycopgTzFixedOffsetTimezone);
self->tzinfo_factory = pyPsycopgTzFixedOffsetTimezone;
- Py_INCREF(self->tzinfo_factory);
Dprintf("cursor_setup: good cursor object at %p, refcnt = "
FORMAT_CODE_PY_SSIZE_T,
@@ -1634,15 +1634,15 @@ cursor_dealloc(PyObject* obj)
if (self->name) PyMem_Free(self->name);
- Py_XDECREF((PyObject*)self->conn);
- Py_XDECREF(self->casts);
- Py_XDECREF(self->description);
- Py_XDECREF(self->pgstatus);
- Py_XDECREF(self->tuple_factory);
- Py_XDECREF(self->tzinfo_factory);
- Py_XDECREF(self->query);
- Py_XDECREF(self->string_types);
- Py_XDECREF(self->binary_types);
+ Py_CLEAR(self->conn);
+ Py_CLEAR(self->casts);
+ Py_CLEAR(self->description);
+ Py_CLEAR(self->pgstatus);
+ Py_CLEAR(self->tuple_factory);
+ Py_CLEAR(self->tzinfo_factory);
+ Py_CLEAR(self->query);
+ Py_CLEAR(self->string_types);
+ Py_CLEAR(self->binary_types);
IFCLEARPGRES(self->pgres);
@@ -1675,7 +1675,7 @@ cursor_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
static void
cursor_del(PyObject* self)
{
- PyObject_Del(self);
+ PyObject_GC_Del(self);
}
static PyObject *
@@ -1685,6 +1685,23 @@ cursor_repr(cursorObject *self)
"<cursor object at %p; closed: %d>", self, self->closed);
}
+static int
+cursor_traverse(cursorObject *self, visitproc visit, void *arg)
+{
+ Py_VISIT((PyObject *)self->conn);
+ Py_VISIT(self->description);
+ Py_VISIT(self->pgstatus);
+ Py_VISIT(self->casts);
+ Py_VISIT(self->caster);
+ Py_VISIT(self->copyfile);
+ Py_VISIT(self->tuple_factory);
+ Py_VISIT(self->tzinfo_factory);
+ Py_VISIT(self->query);
+ Py_VISIT(self->string_types);
+ Py_VISIT(self->binary_types);
+ return 0;
+}
+
/* object type */
@@ -1714,10 +1731,11 @@ PyTypeObject cursorType = {
0, /*tp_setattro*/
0, /*tp_as_buffer*/
- Py_TPFLAGS_DEFAULT|Py_TPFLAGS_BASETYPE|Py_TPFLAGS_HAVE_ITER, /*tp_flags*/
+ Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE | Py_TPFLAGS_HAVE_ITER |
+ Py_TPFLAGS_HAVE_GC, /*tp_flags*/
cursorType_doc, /*tp_doc*/
- 0, /*tp_traverse*/
+ (traverseproc)cursor_traverse, /*tp_traverse*/
0, /*tp_clear*/
0, /*tp_richcompare*/
diff --git a/psycopg/lobject_type.c b/psycopg/lobject_type.c
index ca0a82b..c4386bf 100644
--- a/psycopg/lobject_type.c
+++ b/psycopg/lobject_type.c
@@ -282,8 +282,8 @@ lobject_setup(lobjectObject *self, connectionObject *conn,
if (lobject_open(self, conn, oid, mode, new_oid, new_file) == -1)
return -1;
- Dprintf("lobject_setup: good lobject object at %p, refcnt = %d",
- self, ((PyObject *)self)->ob_refcnt);
+ Dprintf("lobject_setup: good lobject object at %p, refcnt = "
+ FORMAT_CODE_PY_SSIZE_T, self, ((PyObject *)self)->ob_refcnt);
Dprintf("lobject_setup: oid = %d, fd = %d", self->oid, self->fd);
return 0;
}
@@ -297,8 +297,8 @@ lobject_dealloc(PyObject* obj)
PyErr_Print();
Py_XDECREF((PyObject*)self->conn);
- Dprintf("lobject_dealloc: deleted lobject object at %p, refcnt = %d",
- obj, obj->ob_refcnt);
+ Dprintf("lobject_dealloc: deleted lobject object at %p, refcnt = "
+ FORMAT_CODE_PY_SSIZE_T, obj, obj->ob_refcnt);
obj->ob_type->tp_free(obj);
}
diff --git a/psycopg/python.h b/psycopg/python.h
index 84bacaa..13d6ce7 100644
--- a/psycopg/python.h
+++ b/psycopg/python.h
@@ -41,4 +41,27 @@
#define freefunc destructor
#endif
+/* Py_VISIT and Py_CLEAR introduced in Python 2.4 */
+#ifndef Py_VISIT
+#define Py_VISIT(op) \
+ do { \
+ if (op) { \
+ int vret = visit((op), arg); \
+ if (vret) \
+ return vret; \
+ } \
+ } while (0)
+#endif
+
+#ifndef Py_CLEAR
+#define Py_CLEAR(op) \
+ do { \
+ if (op) { \
+ PyObject *tmp = (PyObject *)(op); \
+ (op) = NULL; \
+ Py_DECREF(tmp); \
+ } \
+ } while (0)
+#endif
+
#endif /* !defined(PSYCOPG_PYTHON_H) */
diff --git a/psycopg/typecast.c b/psycopg/typecast.c
index 86e2149..f786960 100644
--- a/psycopg/typecast.c
+++ b/psycopg/typecast.c
@@ -382,11 +382,28 @@ typecast_dealloc(PyObject *obj)
{
typecastObject *self = (typecastObject*)obj;
- Py_XDECREF(self->values);
- Py_XDECREF(self->name);
- Py_XDECREF(self->pcast);
+ Py_CLEAR(self->values);
+ Py_CLEAR(self->name);
+ Py_CLEAR(self->pcast);
- PyObject_Del(self);
+ obj->ob_type->tp_free(obj);
+}
+
+static int
+typecast_traverse(PyObject *obj, visitproc visit, void *arg)
+{
+ typecastObject *self = (typecastObject*)obj;
+
+ Py_VISIT(self->values);
+ Py_VISIT(self->name);
+ Py_VISIT(self->pcast);
+ return 0;
+}
+
+static void
+typecast_del(void *self)
+{
+ PyObject_GC_Del(self);
}
static PyObject *
@@ -427,10 +444,11 @@ PyTypeObject typecastType = {
0, /*tp_setattro*/
0, /*tp_as_buffer*/
- Py_TPFLAGS_HAVE_RICHCOMPARE, /*tp_flags*/
+ Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_RICHCOMPARE |
+ Py_TPFLAGS_HAVE_GC, /*tp_flags*/
"psycopg type-casting object", /*tp_doc*/
- 0, /*tp_traverse*/
+ typecast_traverse, /*tp_traverse*/
0, /*tp_clear*/
typecast_richcompare, /*tp_richcompare*/
@@ -454,7 +472,7 @@ PyTypeObject typecastType = {
0, /*tp_init*/
0, /*tp_alloc will be set to PyType_GenericAlloc in module init*/
0, /*tp_new*/
- 0, /*tp_free Low-level free-memory routine */
+ typecast_del, /*tp_free Low-level free-memory routine */
0, /*tp_is_gc For PyObject_IS_GC */
0, /*tp_bases*/
0, /*tp_mro method resolution order */
@@ -468,7 +486,7 @@ typecast_new(PyObject *name, PyObject *values, PyObject *cast, PyObject *base)
{
typecastObject *obj;
- obj = PyObject_NEW(typecastObject, &typecastType);
+ obj = PyObject_GC_New(typecastObject, &typecastType);
if (obj == NULL) return NULL;
Dprintf("typecast_new: new type at = %p, refcnt = " FORMAT_CODE_PY_SSIZE_T,
@@ -498,6 +516,8 @@ typecast_new(PyObject *name, PyObject *values, PyObject *cast, PyObject *base)
obj->pcast = cast;
}
+ PyObject_GC_Track(obj);
+
Dprintf("typecast_new: typecast object created at %p", obj);
return (PyObject *)obj;