Skip to content

Commit e645c4d

Browse files
committed
Backport minor fixes from trunk to 4.x
Fixed one reference counting issue with setting the notice receiver, also support unmounting the notice receiver callback. Replaced some overly complicated or unofficial ways of calling Python functions with cleaner code.
1 parent f5c5d70 commit e645c4d

2 files changed

Lines changed: 21 additions & 18 deletions

File tree

pgmodule.c

Lines changed: 17 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -1787,10 +1787,11 @@ void notice_receiver(void *arg, const PGresult *res)
17871787
PyGILState_STATE gstate = PyGILState_Ensure();
17881788
pgobject *self = (pgobject*) arg;
17891789
PyObject *proc = self->notice_receiver;
1790+
17901791
if (proc && PyCallable_Check(proc))
17911792
{
17921793
pgnoticeobject *notice = PyObject_NEW(pgnoticeobject, &PgNoticeType);
1793-
PyObject *args, *ret;
1794+
PyObject *ret;
17941795
if (notice)
17951796
{
17961797
notice->pgcnx = arg;
@@ -1801,10 +1802,8 @@ void notice_receiver(void *arg, const PGresult *res)
18011802
Py_INCREF(Py_None);
18021803
notice = (pgnoticeobject *)(void *)Py_None;
18031804
}
1804-
args = Py_BuildValue("(O)", notice);
1805-
ret = PyObject_CallObject(proc, args);
1805+
ret = PyObject_CallFunction(proc, "(O)", notice);
18061806
Py_XDECREF(ret);
1807-
Py_DECREF(args);
18081807
}
18091808
PyGILState_Release(gstate);
18101809
}
@@ -1963,9 +1962,15 @@ pg_set_notice_receiver(pgobject * self, PyObject * args)
19631962

19641963
if (PyArg_ParseTuple(args, "O", &proc))
19651964
{
1966-
if (PyCallable_Check(proc))
1965+
if (proc == Py_None)
1966+
{
1967+
Py_XDECREF(self->notice_receiver);
1968+
self->notice_receiver = NULL;
1969+
Py_INCREF(Py_None); ret = Py_None;
1970+
}
1971+
else if (PyCallable_Check(proc))
19671972
{
1968-
Py_XINCREF(proc);
1973+
Py_XINCREF(proc); Py_XDECREF(self->notice_receiver);
19691974
self->notice_receiver = proc;
19701975
PQsetNoticeReceiver(self->cnx, notice_receiver, self);
19711976
Py_INCREF(Py_None); ret = Py_None;
@@ -2202,15 +2207,14 @@ pgquery_getresult(pgqueryobject *self, PyObject *args)
22022207
case PYGRES_DECIMAL:
22032208
if (decimal)
22042209
{
2205-
tmp_obj = Py_BuildValue("(s)", s);
2206-
val = PyEval_CallObject(decimal, tmp_obj);
2210+
val = PyObject_CallFunction(decimal, "(s)", s);
22072211
}
22082212
else
22092213
{
22102214
tmp_obj = PyString_FromString(s);
22112215
val = PyFloat_FromString(tmp_obj, NULL);
2216+
Py_DECREF(tmp_obj);
22122217
}
2213-
Py_DECREF(tmp_obj);
22142218
break;
22152219

22162220
case PYGRES_BOOL:
@@ -2343,15 +2347,14 @@ pgquery_dictresult(pgqueryobject *self, PyObject *args)
23432347
case PYGRES_DECIMAL:
23442348
if (decimal)
23452349
{
2346-
tmp_obj = Py_BuildValue("(s)", s);
2347-
val = PyEval_CallObject(decimal, tmp_obj);
2350+
val = PyObject_CallFunction(decimal, "(s)", s);
23482351
}
23492352
else
23502353
{
23512354
tmp_obj = PyString_FromString(s);
23522355
val = PyFloat_FromString(tmp_obj, NULL);
2356+
Py_DECREF(tmp_obj);
23532357
}
2354-
Py_DECREF(tmp_obj);
23552358
break;
23562359

23572360
case PYGRES_BOOL:
@@ -2401,8 +2404,7 @@ static char pgquery_namedresult__doc__[] =
24012404
static PyObject *
24022405
pgquery_namedresult(pgqueryobject *self, PyObject *args)
24032406
{
2404-
PyObject *arglist,
2405-
*ret;
2407+
PyObject *ret;
24062408

24072409
/* checks args (args == NULL for an internal call) */
24082410
if (args && !PyArg_ParseTuple(args, ""))
@@ -2419,9 +2421,7 @@ pgquery_namedresult(pgqueryobject *self, PyObject *args)
24192421
return NULL;
24202422
}
24212423

2422-
arglist = Py_BuildValue("(O)", self);
2423-
ret = PyObject_CallObject(namedresult, arglist);
2424-
Py_DECREF(arglist);
2424+
ret = PyObject_CallFunction(namedresult, "(O)", self);
24252425

24262426
if (ret == NULL)
24272427
return NULL;

tests/test_classic_connection.py

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -903,14 +903,17 @@ def testGetNoticeReceiver(self):
903903
self.assertIsNone(self.c.get_notice_receiver())
904904

905905
def testSetNoticeReceiver(self):
906-
self.assertRaises(TypeError, self.c.set_notice_receiver, None)
907906
self.assertRaises(TypeError, self.c.set_notice_receiver, 42)
907+
self.assertRaises(TypeError, self.c.set_notice_receiver, 'invalid')
908908
self.assertIsNone(self.c.set_notice_receiver(lambda notice: None))
909+
self.assertIsNone(self.c.set_notice_receiver(None))
909910

910911
def testSetAndGetNoticeReceiver(self):
911912
r = lambda notice: None
912913
self.assertIsNone(self.c.set_notice_receiver(r))
913914
self.assertIs(self.c.get_notice_receiver(), r)
915+
self.assertIsNone(self.c.set_notice_receiver(None))
916+
self.assertIsNone(self.c.get_notice_receiver())
914917

915918
def testNoticeReceiver(self):
916919
self.c.query('''create function bilbo_notice() returns void AS $$

0 commit comments

Comments
 (0)