[pypy-commit] pypy cpyext-from: change frombuffer/fromobject

plan_rich pypy.commits at gmail.com
Thu Jan 5 11:48:40 EST 2017


Author: Richard Plangger <planrichi at gmail.com>
Branch: cpyext-from
Changeset: r89382:34330a47b61f
Date: 2017-01-05 17:43 +0100
http://bitbucket.org/pypy/pypy/changeset/34330a47b61f/

Log:	change frombuffer/fromobject

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
@@ -6,9 +6,11 @@
              decref, from_ref, make_typedescr)
 from rpython.rtyper.lltypesystem import lltype, rffi
 from rpython.rlib.rarithmetic import widen
+from pypy.interpreter.baseobjspace import BufferInterfaceNotFound
 from pypy.objspace.std.memoryobject import W_MemoryView
 from pypy.module.cpyext.object import _dealloc
 from pypy.module.cpyext.import_ import PyImport_Import
+from rpython.rlib.buffer import Buffer
 
 PyMemoryView_Check, PyMemoryView_CheckExact = build_type_checkers("MemoryView")
 
@@ -95,22 +97,7 @@
     if not isinstance(w_obj, W_MemoryView):
         return lltype.nullptr(Py_buffer)
     py_memobj = rffi.cast(PyMemoryViewObject, as_pyobj(space, w_obj)) # no inc_ref
-    view = py_memobj.c_view
-    ndim = w_obj.buf.getndim()
-    if ndim >= Py_MAX_NDIMS:
-        # XXX warn?
-        return view
-    fill_Py_buffer(space, w_obj.buf, view)
-    try:
-        view.c_buf = rffi.cast(rffi.VOIDP, w_obj.buf.get_raw_address())
-        #view.c_obj = make_ref(space, w_obj) # NO - this creates a ref cycle!
-        rffi.setintfield(view, 'c_readonly', w_obj.buf.readonly)
-    except ValueError:
-        w_s = w_obj.descr_tobytes(space)
-        view.c_obj = make_ref(space, w_s)
-        view.c_buf = rffi.cast(rffi.VOIDP, rffi.str2charp(space.str_w(w_s), track_allocation=False))
-        rffi.setintfield(view, 'c_readonly', 1)
-    return view
+    return py_memobj.c_view
 
 def fill_Py_buffer(space, buf, view):
     # c_buf, c_obj have been filled in
@@ -147,6 +134,7 @@
         view.c_strides = lltype.nullptr(Py_ssize_tP.TO)
     view.c_suboffsets = lltype.nullptr(Py_ssize_tP.TO)
     view.c_internal = lltype.nullptr(rffi.VOIDP.TO)
+    rffi.setintfield(view, 'c_readonly', buf.readonly)
     return 0
 
 def _IsFortranContiguous(view):
@@ -202,9 +190,46 @@
         return (_IsCContiguous(view) or _IsFortranContiguous(view))
     return 0
 
+def _py_memoryview_frombuffer(space, buf):
+    mview = W_MemoryView(buf)
+    return mview
+
 @cpython_api([PyObject], PyObject)
 def PyMemoryView_FromObject(space, w_obj):
-    return space.call_method(space.builtin, "memoryview", w_obj)
+    try:
+        buf = space.buffer_w(w_obj, space.BUF_FULL_RO)
+    except BufferInterfaceNotFound:
+        # review, buffer interface is not found
+        raise oefmt(space.w_TypeError, "cannot make memory view because object "
+                                       "does not have the buffer interface")
+
+    # allocate a new pypy memory view and expose it to cpython using as_pyobj
+    w_mview = W_MemoryView(buf)
+    py_mview = rffi.cast(PyMemoryViewObject, as_pyobj(space, w_mview))
+
+    view = py_mview.c_view
+    fill_Py_buffer(space, buf, view)
+    view.c_buf = rffi.cast(rffi.VOIDP, buf.get_raw_address())
+    # the docs say that in PyMemoryView_FromBuffer (and thus FromObject)
+    # this object must be NULL
+    view.c_obj = make_ref(space, w_obj)
+
+    # XXX what about w_mview.base = w_obj (see cpython 2.7 implementation)
+    return py_mview
+
+class Py_bufferBuffer(Buffer):
+    _attrs_ = ['readonly', 'view']
+    _immutable_ = True
+
+    def __init__(self, view):
+        self.view = view
+        self.readonly = view.c_readonly
+
+    def getlength(self):
+        return self.view.c_len
+
+    def get_raw_address(self):
+        return self.view.c_buf
 
 @cpython_api([Py_bufferP], PyObject)
 def PyMemoryView_FromBuffer(space, view):
@@ -212,10 +237,9 @@
     The memoryview object then owns the buffer, which means you shouldn't
     try to release it yourself: it will be released on deallocation of the
     memoryview object."""
-    w_obj = from_ref(space, view.c_obj)
-    if isinstance(w_obj, W_MemoryView):
-        return w_obj
-    return space.call_method(space.builtin, "memoryview", w_obj)
+    w_mview = W_MemoryView(Py_bufferBuffer(view))
+    py_mview = rffi.cast(PyMemoryViewObject, as_pyobj(space, w_mview))
+    return py_mview
 
 @cpython_api([PyObject], PyObject)
 def PyMemoryView_GET_BASE(space, w_obj):
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
@@ -4,6 +4,7 @@
 from pypy.module.cpyext.test.test_api import BaseApiTest
 from pypy.module.cpyext.test.test_cpyext import AppTestCpythonExtensionBase
 from rpython.rlib.buffer import StringBuffer
+from pypy.module.cpyext.pyobject import from_ref
 
 only_pypy ="config.option.runappdirect and '__pypy__' not in sys.builtin_module_names" 
 
@@ -19,8 +20,9 @@
 
     def test_frombuffer(self, space, api):
         w_buf = space.newbuffer(StringBuffer("hello"))
-        w_memoryview = api.PyMemoryView_FromObject(w_buf)
-        view = api.PyMemoryView_GET_BUFFER(w_memoryview)
+        py_memoryview = api.PyMemoryView_FromObject(w_buf)
+        w_memoryview = from_ref(space, py_memoryview)
+        view = api.PyMemoryView_GET_BUFFER(py_memoryview)
         assert view.c_ndim == 1
         f = rffi.charp2str(view.c_format)
         assert f == 'B'
@@ -29,7 +31,7 @@
         assert view.c_len == 5
         o = rffi.charp2str(view.c_buf)
         assert o == 'hello'
-        w_mv = api.PyMemoryView_FromBuffer(view)
+        w_mv = from_ref(space, api.PyMemoryView_FromBuffer(view))
         for f in ('format', 'itemsize', 'ndim', 'readonly', 
                   'shape', 'strides', 'suboffsets'):
             w_f = space.wrap(f)


More information about the pypy-commit mailing list