]> granicus.if.org Git - python/commitdiff
For Make Benefit Glorious Nation of Backwards Compatibility,
authorGuido van Rossum <guido@python.org>
Mon, 9 Apr 2007 00:43:24 +0000 (00:43 +0000)
committerGuido van Rossum <guido@python.org>
Mon, 9 Apr 2007 00:43:24 +0000 (00:43 +0000)
bytes objects can now be compared to anything that supports the buffer API.

Lib/test/test_bytes.py
Objects/bytesobject.c

index 028cbfdf351a495ad8414a2b54fe5f039326d1c9..2999aa6545f8f2d7b596c767bdbc8c7d31252401 100644 (file)
@@ -99,6 +99,21 @@ class BytesTest(unittest.TestCase):
         self.failIf(b3 <  b2)
         self.failIf(b3 <= b2)
 
+    def test_compare_to_str(self):
+        self.assertEqual(b"abc" == "abc", True)
+        self.assertEqual(b"ab" != "abc", True)
+        self.assertEqual(b"ab" <= "abc", True)
+        self.assertEqual(b"ab" < "abc", True)
+        self.assertEqual(b"abc" >= "ab", True)
+        self.assertEqual(b"abc" > "ab", True)
+
+        self.assertEqual(b"abc" != "abc", False)
+        self.assertEqual(b"ab" == "abc", False)
+        self.assertEqual(b"ab" > "abc", False)
+        self.assertEqual(b"ab" >= "abc", False)
+        self.assertEqual(b"abc" < "ab", False)
+        self.assertEqual(b"abc" <= "ab", False)
+
     def test_nohash(self):
         self.assertRaises(TypeError, hash, bytes())
 
index f07130d809d340da6573858032a3abbd5b8b7f52..34f381a7ce77248813606de768ed1344c1885999 100644 (file)
@@ -838,33 +838,56 @@ bytes_str(PyBytesObject *self)
 }
 
 static PyObject *
-bytes_richcompare(PyBytesObject *self, PyBytesObject *other, int op)
+bytes_richcompare(PyObject *self, PyObject *other, int op)
 {
+    PyBufferProcs *self_buffer, *other_buffer;
+    Py_ssize_t self_size, other_size;
+    void *self_bytes, *other_bytes;
     PyObject *res;
-    int minsize;
+    Py_ssize_t minsize;
     int cmp;
 
-    if (!PyBytes_Check(self) || !PyBytes_Check(other)) {
+    /* For backwards compatibility, bytes can be compared to anything that
+       supports the (binary) buffer API. */
+
+    self_buffer = self->ob_type->tp_as_buffer;
+    if (self_buffer == NULL ||
+        self_buffer->bf_getreadbuffer == NULL ||
+        self_buffer->bf_getsegcount == NULL ||
+        self_buffer->bf_getsegcount(self, NULL) != 1)
+    {
+        Py_INCREF(Py_NotImplemented);
+        return Py_NotImplemented;
+    }
+    self_size = self_buffer->bf_getreadbuffer(self, 0, &self_bytes);
+
+    other_buffer = other->ob_type->tp_as_buffer;
+    if (other_buffer == NULL ||
+        other_buffer->bf_getreadbuffer == NULL ||
+        other_buffer->bf_getsegcount == NULL ||
+        other_buffer->bf_getsegcount(self, NULL) != 1)
+    {
         Py_INCREF(Py_NotImplemented);
         return Py_NotImplemented;
     }
+    other_size = other_buffer->bf_getreadbuffer(other, 0, &other_bytes);
 
-    if (self->ob_size != other->ob_size && (op == Py_EQ || op == Py_NE)) {
+    if (self_size != other_size && (op == Py_EQ || op == Py_NE)) {
         /* Shortcut: if the lengths differ, the objects differ */
         cmp = (op == Py_NE);
     }
     else {
-        minsize = self->ob_size;
-        if (other->ob_size < minsize)
-            minsize = other->ob_size;
+        minsize = self_size;
+        if (other_size < minsize)
+            minsize = other_size;
 
-        cmp = memcmp(self->ob_bytes, other->ob_bytes, minsize);
+        cmp = memcmp(self_bytes, other_bytes, minsize);
         /* In ISO C, memcmp() guarantees to use unsigned bytes! */
 
         if (cmp == 0) {
-            if (self->ob_size < other->ob_size)
+            if (self_size < other_size)
                 cmp = -1;
-            else if (self->ob_size > other->ob_size)
+            else if (self_size > other_size)
                 cmp = 1;
         }