Rev 4697: Copy the hash and richcompare implementations, and add some tests. in http://bazaar.launchpad.net/~jameinel/bzr/2.1-memory-consumption
John Arbash Meinel
john at arbash-meinel.com
Thu Sep 10 19:36:39 BST 2009
At http://bazaar.launchpad.net/~jameinel/bzr/2.1-memory-consumption
------------------------------------------------------------
revno: 4697
revision-id: john at arbash-meinel.com-20090910183623-16o54sfp451bpeln
parent: john at arbash-meinel.com-20090910182754-20e7ppaducyrx0yh
committer: John Arbash Meinel <john at arbash-meinel.com>
branch nick: 2.1-memory-consumption
timestamp: Thu 2009-09-10 13:36:23 -0500
message:
Copy the hash and richcompare implementations, and add some tests.
Again, all of this is bootstrapped by the fact that there is an 'as_tuple'
representation.
-------------- next part --------------
=== modified file 'bzrlib/_keys_type_c.c'
--- a/bzrlib/_keys_type_c.c 2009-09-10 18:27:54 +0000
+++ b/bzrlib/_keys_type_c.c 2009-09-10 18:36:23 +0000
@@ -61,6 +61,8 @@
static PyObject *Keys_item(Keys *self, Py_ssize_t offset);
+#define Key_CheckExact(op) (Py_TYPE(op) == &KeyType)
+
static PyObject *
Key_as_tuple(Key *self)
{
@@ -133,6 +135,70 @@
return (PyObject *)self;
}
+static PyObject *
+Key_repr(Key *self)
+{
+ PyObject *as_tuple, *result;
+
+ as_tuple = Key_as_tuple(self);
+ if (as_tuple == NULL) {
+ return NULL;
+ }
+ result = PyObject_Repr(as_tuple);
+ Py_DECREF(as_tuple);
+ return result;
+}
+
+static long
+Key_hash(Key *self)
+{
+ PyObject *as_tuple = NULL;
+ long hash = -1;
+
+ as_tuple = Key_as_tuple(self);
+ if (as_tuple == NULL) {
+ return -1;
+ }
+ hash = PyTuple_Type.tp_hash(as_tuple);
+ Py_DECREF(as_tuple);
+ return hash;
+}
+
+static PyObject *
+Key_richcompare(PyObject *v, PyObject *w, int op)
+{
+ PyObject *vt, *wt;
+ PyObject *vt_to_decref = NULL, *wt_to_decref = NULL;
+ PyObject *result;
+
+ if (Key_CheckExact(v)) {
+ vt = Key_as_tuple((Key *)v);
+ vt_to_decref = vt;
+ } else if (PyTuple_Check(v)) {
+ vt = v;
+ vt_to_decref = NULL;
+ } else {
+ Py_INCREF(Py_NotImplemented);
+ return Py_NotImplemented;
+ }
+ if (Key_CheckExact(w)) {
+ wt = Key_as_tuple((Key *)w);
+ wt_to_decref = wt;
+ } else if (PyTuple_Check(w)) {
+ wt = w;
+ wt_to_decref = NULL;
+ } else {
+ Py_XDECREF(vt_to_decref);
+ Py_INCREF(Py_NotImplemented);
+ return Py_NotImplemented;
+ }
+ /* Now we have 2 tuples to compare, do it */
+ result = PyTuple_Type.tp_richcompare(vt, wt, op);
+ Py_XDECREF(vt_to_decref);
+ Py_XDECREF(wt_to_decref);
+ return result;
+}
+
static Py_ssize_t
Key_length(Key *self)
{
@@ -185,11 +251,11 @@
0, /* tp_getattr */
0, /* tp_setattr */
0, /* tp_compare */
- 0, //(reprfunc)Keys_repr, /* tp_repr */
+ (reprfunc)Key_repr, /* tp_repr */
0, /* tp_as_number */
&Key_as_sequence, /* tp_as_sequence */
0, /* tp_as_mapping */
- 0, //(hashfunc)Keys_hash, /* tp_hash */
+ (hashfunc)Key_hash, /* tp_hash */
0, /* tp_call */
0, /* tp_str */
PyObject_GenericGetAttr, /* tp_getattro */
@@ -203,7 +269,7 @@
0, /* tp_clear */
// TODO: implement richcompare, we should probably be able to compare vs an
// tuple, as well as versus another Keys object.
- 0, //Key_richcompare, /* tp_richcompare */
+ Key_richcompare, /* tp_richcompare */
0, /* tp_weaklistoffset */
// We could implement this as returning tuples of keys...
0, /* tp_iter */
=== modified file 'bzrlib/tests/test__keys_type.py'
--- a/bzrlib/tests/test__keys_type.py 2009-09-10 18:27:54 +0000
+++ b/bzrlib/tests/test__keys_type.py 2009-09-10 18:36:23 +0000
@@ -119,6 +119,45 @@
del k
self.assertEqual(num_refs, sys.getrefcount(f))
+ def test__repr__(self):
+ k = self.module.Key('foo', 'bar', 'baz', 'bing')
+ self.assertEqual("('foo', 'bar', 'baz', 'bing')", repr(k))
+
+ def test_compare(self):
+ k1 = self.module.Key('foo', 'bar')
+ k2 = self.module.Key('baz', 'bing')
+ k3 = self.module.Key('foo', 'zzz')
+ k4 = self.module.Key('foo', 'bar')
+ k5 = self.module.Key('foo')
+ # Comparison should be done on the keys themselves, and not based on
+ # object id, etc.
+ self.assertTrue(k1 == k1)
+ self.assertTrue(k1 == k4)
+ self.assertTrue(k1 != k2)
+ self.assertTrue(k1 != k3)
+ self.assertTrue(k1 != k5)
+ self.assertTrue(k2 < k1)
+ self.assertTrue(k2 < k4)
+ self.assertTrue(k3 > k1)
+ self.assertTrue(k3 > k4)
+ self.assertTrue(k5 < k1)
+ self.assertTrue(k1 > k5)
+ # We should also be able to compare against raw tuples
+ self.assertTrue(k1 == ('foo', 'bar'))
+
+ def test_hash(self):
+ k = self.module.Key('foo')
+ self.assertEqual(hash(k), hash(('foo',)))
+ k = self.module.Key('foo', 'bar', 'baz', 'bing')
+ as_tuple = ('foo', 'bar', 'baz', 'bing')
+ self.assertEqual(hash(k), hash(as_tuple))
+ x = {k: 'foo'}
+ # Because k == , it replaces the slot, rather than having both
+ # present in the dict.
+ self.assertEqual('foo', x[as_tuple])
+ x[as_tuple] = 'bar'
+ self.assertEqual({as_tuple: 'bar'}, x)
+
class TestKeysType(tests.TestCase):
@@ -217,5 +256,6 @@
x = {k1: 'foo'}
# Because k1 == as_tuple, it replaces the slot, rather than having both
# present in the dict.
+ self.assertEqual('foo', x[as_tuple])
x[as_tuple] = 'bar'
self.assertEqual({as_tuple: 'bar'}, x)
More information about the bazaar-commits
mailing list