Rev 4746: (jam) Update SimpleSet to properly handle NotImplemented in file:///home/pqm/archives/thelove/bzr/%2Btrunk/

Canonical.com Patch Queue Manager pqm at pqm.ubuntu.com
Thu Oct 15 02:36:50 BST 2009


At file:///home/pqm/archives/thelove/bzr/%2Btrunk/

------------------------------------------------------------
revno: 4746 [merge]
revision-id: pqm at pqm.ubuntu.com-20091015013646-k4nv3t54nby3tmnq
parent: pqm at pqm.ubuntu.com-20091014085144-t3bcnsw7rvm7b6ge
parent: john at arbash-meinel.com-20091014155706-zfqfohnjfido8umi
committer: Canonical.com Patch Queue Manager <pqm at pqm.ubuntu.com>
branch nick: +trunk
timestamp: Thu 2009-10-15 02:36:46 +0100
message:
  (jam) Update SimpleSet to properly handle NotImplemented
  	richcomparisons.
modified:
  bzrlib/_simple_set_pyx.pyx     _static_tuple_intern-20091002053806-sid67p8spedru51w-1
  bzrlib/tests/test__simple_set.py test__static_tuple_i-20091002053806-sid67p8spedru51w-2
=== modified file 'bzrlib/_simple_set_pyx.pyx'
--- a/bzrlib/_simple_set_pyx.pyx	2009-10-13 16:44:43 +0000
+++ b/bzrlib/_simple_set_pyx.pyx	2009-10-14 15:57:06 +0000
@@ -21,13 +21,11 @@
 
 cdef extern from "Python.h":
     ctypedef unsigned long size_t
-    ctypedef long (*hashfunc)(PyObject*)
-    ctypedef PyObject *(*richcmpfunc)(PyObject *, PyObject *, int)
+    ctypedef long (*hashfunc)(PyObject*) except -1
+    ctypedef object (*richcmpfunc)(PyObject *, PyObject *, int)
     ctypedef int (*visitproc)(PyObject *, void *)
     ctypedef int (*traverseproc)(PyObject *, visitproc, void *)
     int Py_EQ
-    PyObject *Py_True
-    PyObject *Py_NotImplemented
     void Py_INCREF(PyObject *)
     void Py_DECREF(PyObject *)
     ctypedef struct PyTypeObject:
@@ -36,7 +34,6 @@
         traverseproc tp_traverse
 
     PyTypeObject *Py_TYPE(PyObject *)
-    int PyObject_IsTrue(PyObject *)
     # Note: *Don't* use hash(), Pyrex 0.9.8.5 thinks it returns an 'int', and
     #       thus silently truncates to 32-bits on 64-bit machines.
     long PyObject_Hash(PyObject *) except -1
@@ -58,9 +55,12 @@
 _dummy = <PyObject *>_dummy_obj
 
 
+cdef object _NotImplemented
+_NotImplemented = NotImplemented
+
+
 cdef int _is_equal(PyObject *this, long this_hash, PyObject *other) except -1:
     cdef long other_hash
-    cdef PyObject *res
 
     if this == other:
         return 1
@@ -76,20 +76,12 @@
     #      equal. (It doesn't try to cast them both to some intermediate form
     #      that would compare equal.)
     res = Py_TYPE(this).tp_richcompare(this, other, Py_EQ)
-    if res == NULL: # Exception
-        return -1
-    if PyObject_IsTrue(res):
-        Py_DECREF(res)
-        return 1
-    if res == Py_NotImplemented:
-        Py_DECREF(res)
+    if res is _NotImplemented:
         res = Py_TYPE(other).tp_richcompare(other, this, Py_EQ)
-    if res == NULL:
-        return -1
-    if PyObject_IsTrue(res):
-        Py_DECREF(res)
+        if res is _NotImplemented:
+            return 0
+    if res:
         return 1
-    Py_DECREF(res)
     return 0
 
 

=== modified file 'bzrlib/tests/test__simple_set.py'
--- a/bzrlib/tests/test__simple_set.py	2009-10-12 15:55:26 +0000
+++ b/bzrlib/tests/test__simple_set.py	2009-10-14 15:53:34 +0000
@@ -69,6 +69,12 @@
         raise RuntimeError('I refuse to play nice')
 
 
+class _NoImplementCompare(_Hashable):
+
+    def __eq__(self, other):
+        return NotImplemented
+
+
 # Even though this is an extension, we don't permute the tests for a python
 # version. As the plain python version is just a dict or set
 
@@ -329,6 +335,20 @@
         # Tries to compare with k1, fails
         self.assertRaises(RuntimeError, obj.add, k2)
 
+    def test_richcompare_not_implemented(self):
+        obj = self.module.SimpleSet()
+        # Even though their hashes are the same, tp_richcompare returns
+        # NotImplemented, which means we treat them as not equal
+        k1 = _NoImplementCompare(200)
+        k2 = _NoImplementCompare(200)
+        self.assertLookup(200, '<null>', obj, k1)
+        self.assertLookup(200, '<null>', obj, k2)
+        self.assertIs(k1, obj.add(k1))
+        self.assertLookup(200, k1, obj, k1)
+        self.assertLookup(201, '<null>', obj, k2)
+        self.assertIs(k2, obj.add(k2))
+        self.assertIs(k1, obj[k1])
+
     def test_add_and_remove_lots_of_items(self):
         obj = self.module.SimpleSet()
         chars = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz1234567890'




More information about the bazaar-commits mailing list