mirror of
https://github.com/psycopg/psycopg2.git
synced 2024-11-14 04:56:33 +03:00
The Notify type is hashable.
If there is no payload, hash the same way the equivalent 2-tuple does. Otherwise hash on the payload too.
This commit is contained in:
parent
56ae1fe4bf
commit
77c0ab02d8
|
@ -125,22 +125,24 @@ notify_del(PyObject *self)
|
||||||
PyObject_GC_Del(self);
|
PyObject_GC_Del(self);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Convert a notify into a 3-items tuple.
|
|
||||||
* This is done for help hashing and comparison, *not* for comparison
|
/* Convert a notify into a 2 or 3 items tuple. */
|
||||||
* against other tuples, where the payload is discarded.
|
|
||||||
*/
|
|
||||||
static PyObject *
|
static PyObject *
|
||||||
notify_astuple(NotifyObject *self)
|
notify_astuple(NotifyObject *self, int with_payload)
|
||||||
{
|
{
|
||||||
PyObject *tself;
|
PyObject *tself;
|
||||||
if (!(tself = PyTuple_New(3))) { return NULL; }
|
if (!(tself = PyTuple_New(with_payload ? 3 : 2))) { return NULL; }
|
||||||
|
|
||||||
Py_INCREF(self->pid);
|
Py_INCREF(self->pid);
|
||||||
PyTuple_SET_ITEM(tself, 0, self->pid);
|
PyTuple_SET_ITEM(tself, 0, self->pid);
|
||||||
|
|
||||||
Py_INCREF(self->channel);
|
Py_INCREF(self->channel);
|
||||||
PyTuple_SET_ITEM(tself, 1, self->channel);
|
PyTuple_SET_ITEM(tself, 1, self->channel);
|
||||||
Py_INCREF(self->payload);
|
|
||||||
PyTuple_SET_ITEM(tself, 2, self->payload);
|
if (with_payload) {
|
||||||
|
Py_INCREF(self->payload);
|
||||||
|
PyTuple_SET_ITEM(tself, 2, self->payload);
|
||||||
|
}
|
||||||
|
|
||||||
return tself;
|
return tself;
|
||||||
}
|
}
|
||||||
|
@ -153,16 +155,12 @@ notify_richcompare(NotifyObject *self, PyObject *other, int op)
|
||||||
PyObject *tother = NULL;
|
PyObject *tother = NULL;
|
||||||
|
|
||||||
if (Py_TYPE(other) == &NotifyType) {
|
if (Py_TYPE(other) == &NotifyType) {
|
||||||
if (!(tself = notify_astuple(self))) { goto exit; }
|
if (!(tself = notify_astuple(self, 1))) { goto exit; }
|
||||||
if (!(tother = notify_astuple((NotifyObject *)other))) { goto exit; }
|
if (!(tother = notify_astuple((NotifyObject *)other, 1))) { goto exit; }
|
||||||
rv = PyObject_RichCompare(tself, tother, op);
|
rv = PyObject_RichCompare(tself, tother, op);
|
||||||
}
|
}
|
||||||
else if (PyTuple_Check(other)) {
|
else if (PyTuple_Check(other)) {
|
||||||
if (!(tself = PyTuple_New(2))) { goto exit; };
|
if (!(tself = notify_astuple(self, 0))) { goto exit; }
|
||||||
Py_INCREF(self->pid);
|
|
||||||
PyTuple_SET_ITEM(tself, 0, self->pid);
|
|
||||||
Py_INCREF(self->channel);
|
|
||||||
PyTuple_SET_ITEM(tself, 1, self->channel);
|
|
||||||
rv = PyObject_RichCompare(tself, other, op);
|
rv = PyObject_RichCompare(tself, other, op);
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
|
@ -176,6 +174,24 @@ exit:
|
||||||
return rv;
|
return rv;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
long
|
||||||
|
notify_hash(NotifyObject *self)
|
||||||
|
{
|
||||||
|
long rv = -1L;
|
||||||
|
PyObject *tself = NULL;
|
||||||
|
|
||||||
|
/* if self == a tuple, then their hashes are the same. */
|
||||||
|
int has_payload = PyObject_IsTrue(self->payload);
|
||||||
|
if (!(tself = notify_astuple(self, has_payload))) { goto exit; }
|
||||||
|
rv = PyObject_Hash(tself);
|
||||||
|
|
||||||
|
exit:
|
||||||
|
Py_XDECREF(tself);
|
||||||
|
return rv;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
static PyObject*
|
static PyObject*
|
||||||
notify_repr(NotifyObject *self)
|
notify_repr(NotifyObject *self)
|
||||||
{
|
{
|
||||||
|
@ -263,7 +279,7 @@ PyTypeObject NotifyType = {
|
||||||
0, /*tp_as_number*/
|
0, /*tp_as_number*/
|
||||||
¬ify_sequence, /*tp_as_sequence*/
|
¬ify_sequence, /*tp_as_sequence*/
|
||||||
0, /*tp_as_mapping*/
|
0, /*tp_as_mapping*/
|
||||||
0, /*tp_hash */
|
(hashfunc)notify_hash, /*tp_hash */
|
||||||
|
|
||||||
0, /*tp_call*/
|
0, /*tp_call*/
|
||||||
0, /*tp_str*/
|
0, /*tp_str*/
|
||||||
|
|
|
@ -170,6 +170,11 @@ conn.close()
|
||||||
self.assertNotEqual((10, 'foo'), Notify(20, 'foo'))
|
self.assertNotEqual((10, 'foo'), Notify(20, 'foo'))
|
||||||
self.assertNotEqual((10, 'foo'), Notify(10, 'bar'))
|
self.assertNotEqual((10, 'foo'), Notify(10, 'bar'))
|
||||||
|
|
||||||
|
def test_hash(self):
|
||||||
|
from psycopg2.extensions import Notify
|
||||||
|
self.assertEqual(hash((10, 'foo')), hash(Notify(10, 'foo')))
|
||||||
|
self.assertNotEqual(hash(Notify(10, 'foo', 'bar')),
|
||||||
|
hash(Notify(10, 'foo')))
|
||||||
|
|
||||||
def test_suite():
|
def test_suite():
|
||||||
return unittest.TestLoader().loadTestsFromName(__name__)
|
return unittest.TestLoader().loadTestsFromName(__name__)
|
||||||
|
|
Loading…
Reference in New Issue
Block a user