Author: Amaury Forgeot d'Arc <[email protected]>
Branch: py3k
Changeset: r59261:033e22d48bf2
Date: 2012-12-02 23:36 +0100
http://bitbucket.org/pypy/pypy/changeset/033e22d48bf2/
Log: cpyext: implement PyMemoryView_FromBuffer
diff --git a/pypy/module/cpyext/buffer.py b/pypy/module/cpyext/buffer.py
--- a/pypy/module/cpyext/buffer.py
+++ b/pypy/module/cpyext/buffer.py
@@ -1,8 +1,8 @@
-from pypy.interpreter.error import OperationError
from pypy.rpython.lltypesystem import rffi, lltype
from pypy.module.cpyext.api import (
cpython_api, CANNOT_FAIL, Py_buffer)
-from pypy.module.cpyext.pyobject import PyObject
+from pypy.module.cpyext.pyobject import PyObject, Py_DecRef
+from pypy.interpreter import buffer
@cpython_api([lltype.Ptr(Py_buffer), lltype.Char], rffi.INT_real,
error=CANNOT_FAIL)
def PyBuffer_IsContiguous(space, view, fortran):
@@ -11,3 +11,27 @@
(fortran is 'A'). Return 0 otherwise."""
# PyPy only supports contiguous Py_buffers for now.
return 1
+
+class CBufferMixin(object):
+ _mixin_ = True
+
+ def __init__(self, space, c_buf, c_len, w_obj):
+ self.space = space
+ self.c_buf = c_buf
+ self.c_len = c_len
+ self.w_obj = w_obj
+
+ def __del__(self):
+ Py_DecRef(self.space, self.w_obj)
+
+ def getlength(self):
+ return self.c_len
+
+ def getitem(self, index):
+ return self.c_buf[index]
+
+ def as_str(self):
+ return rffi.charpsize2str(self.c_buf, self.c_len)
+
+class CBuffer(CBufferMixin, buffer.Buffer):
+ pass
diff --git a/pypy/module/cpyext/memoryobject.py
b/pypy/module/cpyext/memoryobject.py
--- a/pypy/module/cpyext/memoryobject.py
+++ b/pypy/module/cpyext/memoryobject.py
@@ -1,6 +1,19 @@
-from pypy.module.cpyext.api import cpython_api
-from pypy.module.cpyext.pyobject import PyObject
+from pypy.module.cpyext.api import cpython_api, Py_buffer
+from pypy.module.cpyext.pyobject import PyObject, from_ref
+from pypy.module.cpyext.buffer import CBuffer
+from pypy.rpython.lltypesystem import rffi, lltype
+from pypy.module.__builtin__.interp_memoryview import W_MemoryView
@cpython_api([PyObject], PyObject)
def PyMemoryView_FromObject(space, w_obj):
return space.call_method(space.builtin, "memoryview", w_obj)
+
+@cpython_api([lltype.Ptr(Py_buffer)], PyObject)
+def PyMemoryView_FromBuffer(space, view):
+ """Create a memoryview object wrapping the given buffer structure view.
+ The memoryview object then owns the buffer represented by view, which
+ means you shouldn't try to call PyBuffer_Release() yourself: it
+ will be done on deallocation of the memoryview object."""
+ w_obj = from_ref(space, view.c_obj)
+ buf = CBuffer(space, view.c_buf, view.c_len, w_obj)
+ return space.wrap(W_MemoryView(space.wrap(buf)))
diff --git a/pypy/module/cpyext/stubs.py b/pypy/module/cpyext/stubs.py
--- a/pypy/module/cpyext/stubs.py
+++ b/pypy/module/cpyext/stubs.py
@@ -1610,15 +1610,6 @@
raise NotImplementedError
-@cpython_api([Py_buffer], PyObject)
-def PyMemoryView_FromBuffer(space, view):
- """Create a memoryview object wrapping the given buffer structure view.
- The memoryview object then owns the buffer represented by view, which
- means you shouldn't try to call PyBuffer_Release() yourself: it
- will be done on deallocation of the memoryview object."""
- raise NotImplementedError
-
-
@cpython_api([PyObject, rffi.INT_real, lltype.Char], PyObject)
def PyMemoryView_GetContiguous(space, obj, buffertype, order):
"""Create a memoryview object to a contiguous chunk of memory (in either
diff --git a/pypy/module/cpyext/test/test_memoryobject.py
b/pypy/module/cpyext/test/test_memoryobject.py
--- a/pypy/module/cpyext/test/test_memoryobject.py
+++ b/pypy/module/cpyext/test/test_memoryobject.py
@@ -1,5 +1,6 @@
import py
from pypy.module.cpyext.test.test_api import BaseApiTest
+from pypy.module.cpyext.test.test_cpyext import AppTestCpythonExtensionBase
class TestMemoryViewObject(BaseApiTest):
def test_fromobject(self, space, api):
@@ -11,3 +12,29 @@
w_view = api.PyMemoryView_FromObject(w_hello)
w_bytes = space.call_method(w_view, "tobytes")
assert space.unwrap(w_bytes) == "hello"
+
+class AppTestPyBuffer_FillInfo(AppTestCpythonExtensionBase):
+ def test_fillWithObject(self):
+ module = self.import_extension('foo', [
+ ("fillinfo", "METH_VARARGS",
+ """
+ Py_buffer buf;
+ PyObject *str = PyBytes_FromString("hello, world.");
+ PyObject *result;
+
+ if (PyBuffer_FillInfo(&buf, str, PyBytes_AsString(str), 13,
+ 0, 0)) {
+ return NULL;
+ }
+
+ /* Get rid of our own reference to the object, but
+ * the Py_buffer should still have a reference.
+ */
+ Py_DECREF(str);
+
+ return PyMemoryView_FromBuffer(&buf);
+ """)])
+ result = module.fillinfo()
+ assert b"hello, world." == result
+
+
_______________________________________________
pypy-commit mailing list
[email protected]
http://mail.python.org/mailman/listinfo/pypy-commit