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