Rev 4724: Do some work to handle comparison to object that aren't tuples or strings. in http://bazaar.launchpad.net/~jameinel/bzr/2.1-static-tuple

John Arbash Meinel john at arbash-meinel.com
Wed Sep 30 20:43:41 BST 2009


At http://bazaar.launchpad.net/~jameinel/bzr/2.1-static-tuple

------------------------------------------------------------
revno: 4724
revision-id: john at arbash-meinel.com-20090930194334-9rmtwmwimmssqw19
parent: john at arbash-meinel.com-20090930191534-2mi59m6qxtsoaw7j
committer: John Arbash Meinel <john at arbash-meinel.com>
branch nick: 2.1-static-tuple
timestamp: Wed 2009-09-30 14:43:34 -0500
message:
  Do some work to handle comparison to object that aren't tuples or strings.
-------------- next part --------------
=== modified file 'bzrlib/_static_tuple_c.c'
--- a/bzrlib/_static_tuple_c.c	2009-09-30 19:15:34 +0000
+++ b/bzrlib/_static_tuple_c.c	2009-09-30 19:43:34 +0000
@@ -304,12 +304,15 @@
          * might trigger if '__op__' is defined but '__rop__' is not, sort of
          * case. Such as "None == StaticTuple()"
          */
-        fprintf(stderr, "self is tuple\n");
+        fprintf(stderr, "self is not StaticTuple\n");
         Py_INCREF(Py_NotImplemented);
         return Py_NotImplemented;
     }
     vk = (StaticTuple *)v;
-    if (PyTuple_Check(w)) {
+    if (StaticTuple_CheckExact(w)) {
+        /* The most common case */
+        wk = (StaticTuple*)w;
+    } else if (PyTuple_Check(w)) {
         /* One of v or w is a tuple, so we go the 'slow' route and cast up to
          * tuples to compare.
          */
@@ -318,22 +321,26 @@
          *       other is a tuple.
          */
         return StaticTuple_richcompare_to_tuple(vk, w, op);
-    }
-    /* TODO: Py_None is one of the other common cases here, we should probably
-     *       directly support it.
-     */
-    if (!StaticTuple_CheckExact(w)) {
-        /* Both are not StaticTuple objects, and they aren't Tuple objects or the
-         * previous path would have been taken. We don't support comparing with
-         * anything else.
+    } else if (w == Py_None) {
+        // None is always less than the object
+		switch (op) {
+		case Py_NE:case Py_GT:case Py_GE:
+            Py_INCREF(Py_True);
+            return Py_True;
+        case Py_EQ:case Py_LT:case Py_LE:
+            Py_INCREF(Py_False);
+            return Py_False;
+		}
+    } else {
+        /* We don't special case this comparison, we just let python handle
+         * it.
          */
-         fprintf(stderr, "not comparing to key: %s\n", Py_TYPE(w)->tp_name);
          Py_INCREF(Py_NotImplemented);
          return Py_NotImplemented;
     }
     /* Now we know that we have 2 StaticTuple objects, so let's compare them.
      * This code is somewhat borrowed from tuplerichcompare, except we know our
-     * objects are limited in scope, so we cheat a bit.
+     * objects are limited in scope, so we can inline some comparisons.
      */
     if (v == w) {
         /* Identical pointers, we can shortcut this easily. */
@@ -346,7 +353,6 @@
             return Py_False;
 		}
     }
-    wk = (StaticTuple*)w;
 
     /* It will be rare that we compare tuples of different lengths, so we don't
      * start by optimizing the length comparision, same as the tuple code

=== modified file 'bzrlib/_static_tuple_py.py'
--- a/bzrlib/_static_tuple_py.py	2009-09-30 19:15:34 +0000
+++ b/bzrlib/_static_tuple_py.py	2009-09-30 19:43:34 +0000
@@ -29,7 +29,7 @@
     def __new__(cls, *args):
         if not args and _empty_tuple is not None:
             return _empty_tuple
-        return super(StaticTuple, cls).__new__(cls, *args)
+        return object.__new__(cls)
 
     def __init__(self, *args):
         """Create a new 'StaticTuple'"""

=== modified file 'bzrlib/tests/test__static_tuple.py'
--- a/bzrlib/tests/test__static_tuple.py	2009-09-30 19:15:34 +0000
+++ b/bzrlib/tests/test__static_tuple.py	2009-09-30 19:43:34 +0000
@@ -187,6 +187,14 @@
         self.assertTrue(k_small <= k_big)
         self.assertTrue(k_small < k_big)
 
+    def test_compare_vs_none(self):
+        k1 = self.module.StaticTuple('baz', 'bing')
+        self.assertCompareDifferent(None, k1)
+        self.assertCompareDifferent(10, k1)
+        # Comparison with a string is poorly-defined, I seem to get failures
+        # regardless of which one comes first...
+        # self.assertCompareDifferent('baz', k1)
+
     def test_compare_all_different_same_width(self):
         k1 = self.module.StaticTuple('baz', 'bing')
         k2 = self.module.StaticTuple('foo', 'bar')
@@ -264,17 +272,37 @@
         from meliae import scanner
         strs = ['foo', 'bar', 'baz', 'bing']
         k = self.module.StaticTuple(*strs)
-        if isinstance(k, _static_tuple_py.StaticTuple):
+        if self.module is _static_tuple_py:
             # The python version references objects slightly different than the
             # compiled version
             self.assertEqual([k._tuple, _static_tuple_py.StaticTuple],
                              scanner.get_referents(k))
+            self.assertEqual(sorted(strs),
+                             sorted(scanner.get_referents(k._tuple)))
         else:
             self.assertEqual(sorted(strs), sorted(scanner.get_referents(k)))
 
+    def test_nested_referents(self):
+        self.requireFeature(Meliae)
+
     def test_empty_is_singleton(self):
         key = self.module.StaticTuple()
         self.assertIs(key, self.module._empty_tuple)
+        from meliae import scanner
+        strs = ['foo', 'bar', 'baz', 'bing']
+        k1 = self.module.StaticTuple(*strs[:2])
+        k2 = self.module.StaticTuple(*strs[2:])
+        k3 = self.module.StaticTuple(k1, k2)
+        if self.module is _static_tuple_py:
+            # The python version references objects slightly different than the
+            # compiled version
+            self.assertEqual([k3._tuple, _static_tuple_py.StaticTuple],
+                             scanner.get_referents(k3))
+            self.assertEqual(sorted([k1, k2]),
+                             sorted(scanner.get_referents(k3._tuple)))
+        else:
+            self.assertEqual(sorted([k1, k2]),
+                             sorted(scanner.get_referents(k3)))
 
     def test_intern(self):
         unique_str1 = 'unique str ' + osutils.rand_chars(20)



More information about the bazaar-commits mailing list