Commits

Armin Rigo committed 65a3bcb

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

Comments (0)

Files changed (3)

         *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)
 #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 */
     (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,
     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--

doc/source/index.rst

    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]
    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