summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorGuido van Rossum <guido@python.org>2007-04-09 00:43:24 (GMT)
committerGuido van Rossum <guido@python.org>2007-04-09 00:43:24 (GMT)
commit343e97ff7f939fc16d144a196a95ecf2e82c061e (patch)
tree96fd769c99919c8116eca192247ea7d1647fd64d
parent62cbc8a2618a41c28b8ec25f70f85f2da17705f2 (diff)
downloadcpython-343e97ff7f939fc16d144a196a95ecf2e82c061e.zip
cpython-343e97ff7f939fc16d144a196a95ecf2e82c061e.tar.gz
cpython-343e97ff7f939fc16d144a196a95ecf2e82c061e.tar.bz2
For Make Benefit Glorious Nation of Backwards Compatibility,
bytes objects can now be compared to anything that supports the buffer API.
-rw-r--r--Lib/test/test_bytes.py15
-rw-r--r--Objects/bytesobject.c43
2 files changed, 48 insertions, 10 deletions
diff --git a/Lib/test/test_bytes.py b/Lib/test/test_bytes.py
index 028cbfd..2999aa6 100644
--- a/Lib/test/test_bytes.py
+++ b/Lib/test/test_bytes.py
@@ -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())
diff --git a/Objects/bytesobject.c b/Objects/bytesobject.c
index f07130d..34f381a 100644
--- a/Objects/bytesobject.c
+++ b/Objects/bytesobject.c
@@ -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;
}