[pypy-commit] cffi default: Fix for issue #129: 'bytes(buffer)' needs to work on Python 2,

arigo noreply at buildbot.pypy.org
Fri Dec 6 19:52:35 CET 2013


Author: Armin Rigo <arigo at tunes.org>
Branch: 
Changeset: r1437:65a3bcbcb054
Date: 2013-12-06 19:52 +0100
http://bitbucket.org/cffi/cffi/changeset/65a3bcbcb054/

Log:	Fix for issue #129: 'bytes(buffer)' needs to work on Python 2,
	because it works on Python 3 and cannot be prevented to.

diff --git a/c/minibuffer.h b/c/minibuffer.h
--- a/c/minibuffer.h
+++ b/c/minibuffer.h
@@ -93,6 +93,26 @@
         *lenp = self->mb_size;
     return 1;
 }
+
+static PyObject *mb_str(MiniBufferObj *self)
+{
+    /* Python 2: we want str(buffer) to behave like buffer[:], because
+       that's what bytes(buffer) does on Python 3 and there is no way
+       we can prevent this. */
+    return PyString_FromStringAndSize(self->mb_data, self->mb_size);
+}
+
+static PyObject *MiniBuffer_unicode(PyObject *self, PyObject *ignored)
+{
+    /* Python 2: we *don't* want unicode(buffer) to return the
+       unicodified str(buffer)! */
+    return PyObject_Repr(self);
+}
+
+static PyMethodDef MiniBuffer_methods[] = {
+    {"__unicode__", MiniBuffer_unicode, METH_NOARGS},
+    {0}
+};
 #endif
 
 static int mb_getbuf(MiniBufferObj *self, Py_buffer *view, int flags)
@@ -249,7 +269,11 @@
 #endif
     0,                                          /* tp_hash */
     0,                                          /* tp_call */
+#if PY_MAJOR_VERSION < 3
+    (reprfunc)mb_str,                           /* tp_str */
+#else
     0,                                          /* tp_str */
+#endif
     PyObject_GenericGetAttr,                    /* tp_getattro */
     0,                                          /* tp_setattro */
     &mb_as_buffer,                              /* tp_as_buffer */
@@ -260,6 +284,13 @@
     (inquiry)mb_clear,                          /* tp_clear */
     0,                                          /* tp_richcompare */
     offsetof(MiniBufferObj, mb_weakreflist),    /* tp_weaklistoffset */
+    0,                                          /* tp_iter */
+    0,                                          /* tp_iternext */
+#if PY_MAJOR_VERSION < 3
+    MiniBuffer_methods,                         /* tp_methods */
+#else
+    0,                                          /* tp_methods */
+#endif
 };
 
 static PyObject *minibuffer_new(char *data, Py_ssize_t size,
diff --git a/c/test_c.py b/c/test_c.py
--- a/c/test_c.py
+++ b/c/test_c.py
@@ -2154,7 +2154,8 @@
     c = newp(BCharArray, b"hi there")
     #
     buf = buffer(c)
-    assert str(buf).startswith('<_cffi_backend.buffer object at 0x')
+    assert unicode(buf).startswith('<_cffi_backend.buffer object at 0x')
+    assert bytes(buf) == b"hi there\x00"
     # --mb_length--
     assert len(buf) == len(b"hi there\x00")
     # --mb_item--
diff --git a/doc/source/index.rst b/doc/source/index.rst
--- a/doc/source/index.rst
+++ b/doc/source/index.rst
@@ -1172,7 +1172,7 @@
    because these objects' API changes too much across Python versions.
    Instead it has the following Python API (a subset of ``buffer``):
 
-- ``buf[:]``: fetch a copy as a regular byte string (or
+- ``buf[:]`` or ``bytes(buf)``: fetch a copy as a regular byte string (or
   ``buf[start:end]`` for a part)
 
 - ``buf[:] = newstr``: change the original content (or ``buf[start:end]
@@ -1187,6 +1187,10 @@
    owned memory will not be freed as long as the buffer is alive.
    Moreover buffer objects now support weakrefs to them.
 
+.. versionchanged:: 0.9
+   Before version 0.9, ``bytes(buf)`` was supported in Python 3 but not
+   Python 2.
+
 
 ``ffi.typeof("C type" or cdata object)``: return an object of type
 ``<ctype>`` corresponding to the parsed string, or to the C type of the


More information about the pypy-commit mailing list