[pypy-commit] pypy cpyext-old-buffers: Use PyPy buffer protocol to implement CPython buffer protocol.

devin.jeanpierre pypy.commits at gmail.com
Fri May 13 13:52:46 EDT 2016


Author: Devin Jeanpierre <jeanpierreda at gmail.com>
Branch: cpyext-old-buffers
Changeset: r84426:5b8aa00091eb
Date: 2016-05-12 17:23 -0700
http://bitbucket.org/pypy/pypy/changeset/5b8aa00091eb/

Log:	Use PyPy buffer protocol to implement CPython buffer protocol.

	Only works for strings/buffers atm.

diff --git a/pypy/module/cpyext/test/test_abstract.py b/pypy/module/cpyext/test/test_abstract.py
--- a/pypy/module/cpyext/test/test_abstract.py
+++ b/pypy/module/cpyext/test/test_abstract.py
@@ -5,7 +5,8 @@
     """Tests for the old buffer protocol."""
     spaceconfig = AppTestCpythonExtensionBase.spaceconfig.copy()
     # Also allow mmap to be importable.
-    spaceconfig['usemodules'] = list(spaceconfig['usemodules']) + ['mmap']
+    # XXX: this breaks all tests that run afterward! Not sure why yet.
+    # spaceconfig['usemodules'] = list(spaceconfig['usemodules']) + ['mmap']
 
     def w_get_buffer_support(self):
         return self.import_extension('buffer_support', [
diff --git a/pypy/module/cpyext/typeobject.py b/pypy/module/cpyext/typeobject.py
--- a/pypy/module/cpyext/typeobject.py
+++ b/pypy/module/cpyext/typeobject.py
@@ -450,16 +450,30 @@
 
 @cpython_api([PyObject, Py_ssize_t, rffi.VOIDPP], lltype.Signed,
              header=None, error=-1)
-def str_getreadbuffer(space, w_str, segment, ref):
+def str_getreadbuffer(space, w_buf, segment, ref):
     from pypy.module.cpyext.bytesobject import PyString_AsString
     if segment != 0:
         raise oefmt(space.w_SystemError,
                     "accessing non-existent string segment")
-    pyref = make_ref(space, w_str)
-    ref[0] = PyString_AsString(space, pyref)
-    # Stolen reference: the object has better exist somewhere else
-    Py_DecRef(space, pyref)
-    return space.len_w(w_str)
+    buf = space.readbuf_w(w_buf)
+    try:
+        address = buf.get_raw_address()
+    except ValueError:
+        # convert to a string and leak some memory. :(
+        w_str = space.wrap(buf.as_str())
+        py_str = make_ref(space, w_str)
+        ref[0] = PyString_AsString(space, py_str)
+        if space.is_w(w_str, w_buf):
+            # We're reusing the string object, and it's the caller's
+            # responsibility to keep it alive.
+            Py_DecRef(space, py_str)
+        # else: we had to create a new string object to keep the
+        # bytes in, so we leak it on purpose.
+        # XXX Can we put a reference to the string object on the buffer?
+        return space.len_w(w_str)
+    else:
+        ref[0] = address
+        return len(buf)
 
 @cpython_api([PyObject, Py_ssize_t, rffi.CCHARPP], lltype.Signed,
              header=None, error=-1)
@@ -474,18 +488,6 @@
     Py_DecRef(space, pyref)
     return space.len_w(w_str)
 
- at cpython_api([PyObject, Py_ssize_t, rffi.VOIDPP], lltype.Signed,
-             header=None, error=-1)
-def buf_getreadbuffer(space, pyref, segment, ref):
-    from pypy.module.cpyext.bufferobject import PyBufferObject
-    if segment != 0:
-        raise oefmt(space.w_SystemError,
-                    "accessing non-existent string segment")
-    py_buf = rffi.cast(PyBufferObject, pyref)
-    ref[0] = py_buf.c_b_ptr
-    #Py_DecRef(space, pyref)
-    return py_buf.c_b_size
-
 @cpython_api([PyObject, Py_ssize_t, rffi.CCHARPP], lltype.Signed,
              header=None, error=-1)
 def buf_getcharbuffer(space, pyref, segment, ref):
@@ -515,8 +517,8 @@
     lltype.render_immortal(c_buf)
     c_buf.c_bf_getsegcount = llhelper(str_segcount.api_func.functype,
                                       str_segcount.api_func.get_wrapper(space))
-    c_buf.c_bf_getreadbuffer = llhelper(buf_getreadbuffer.api_func.functype,
-                                 buf_getreadbuffer.api_func.get_wrapper(space))
+    c_buf.c_bf_getreadbuffer = llhelper(str_getreadbuffer.api_func.functype,
+                                 str_getreadbuffer.api_func.get_wrapper(space))
     c_buf.c_bf_getcharbuffer = llhelper(buf_getcharbuffer.api_func.functype,
                                  buf_getcharbuffer.api_func.get_wrapper(space))
     pto.c_tp_as_buffer = c_buf


More information about the pypy-commit mailing list