Author: Ronan Lamy <[email protected]>
Branch: py3.5
Changeset: r90013:3059a0362786
Date: 2017-02-08 20:40 +0000
http://bitbucket.org/pypy/pypy/changeset/3059a0362786/

Log:    Merged in buffer-cleanup (pull request #515)

        Buffer cleanup

diff --git a/pypy/interpreter/baseobjspace.py b/pypy/interpreter/baseobjspace.py
--- a/pypy/interpreter/baseobjspace.py
+++ b/pypy/interpreter/baseobjspace.py
@@ -25,15 +25,6 @@
                                       reds=['items', 'w_iterator'])
 
 
[email protected]()
-def _does_override_buffer_w(type):
-    return type.buffer_w != W_Root.buffer_w
-
[email protected]()
-def _does_override_buffer_w_ex(type):
-    return type.buffer_w_ex != W_Root.buffer_w_ex
-
-
 class W_Root(object):
     """This is the abstract root class of all wrapped objects that live
     in a 'normal' object space like StdObjSpace."""
@@ -223,15 +214,8 @@
         return None
 
     def buffer_w(self, space, flags):
-        if _does_override_buffer_w_ex(self.__class__):
-            return self.buffer_w_ex(space, flags)[0]
         return self.__buffer_w(space, flags).buffer_w(space, flags)
 
-    def buffer_w_ex(self, space, flags):
-        if _does_override_buffer_w(self.__class__):
-            return self.buffer_w(space, flags), 'B', 1
-        return self.__buffer_w(space, flags).buffer_w_ex(space, flags)
-
     def __buffer_w(self, space, flags):
         if flags & space.BUF_WRITABLE:
             w_impl = space.lookup(self, '__wbuffer__')
@@ -1469,15 +1453,6 @@
             raise oefmt(self.w_TypeError,
                         "'%T' does not support the buffer interface", w_obj)
 
-    def buffer_w_ex(self, w_obj, flags):
-        # New buffer interface, returns a buffer based on flags 
(PyObject_GetBuffer)
-        # Returns extra information: (buffer, typecode, itemsize)
-        try:
-            return w_obj.buffer_w_ex(self, flags)
-        except BufferInterfaceNotFound:
-            raise oefmt(self.w_TypeError,
-                        "'%T' does not support the buffer interface", w_obj)
-
     def readbuf_w(self, w_obj):
         # Old buffer interface, returns a readonly buffer 
(PyObject_AsReadBuffer)
         try:
diff --git a/pypy/module/_rawffi/array.py b/pypy/module/_rawffi/array.py
--- a/pypy/module/_rawffi/array.py
+++ b/pypy/module/_rawffi/array.py
@@ -91,6 +91,8 @@
         W_DataInstance.__init__(self, space, memsize, address)
         self.length = length
         self.shape = shape
+        self.fmt = shape.itemcode
+        self.itemsize = shape.size
 
     def descr_repr(self, space):
         addr = rffi.cast(lltype.Unsigned, self.ll_buffer)
@@ -105,8 +107,7 @@
             raise segfault_exception(space, "setting element of freed array")
         if num >= self.length or num < 0:
             raise OperationError(space.w_IndexError, space.w_None)
-        unwrap_value(space, write_ptr, self.ll_buffer, num,
-                     self.shape.itemcode, w_value)
+        unwrap_value(space, write_ptr, self.ll_buffer, num, self.fmt, w_value)
 
     def descr_setitem(self, space, w_index, w_value):
         try:
@@ -123,8 +124,7 @@
             raise segfault_exception(space, "accessing elements of freed 
array")
         if num >= self.length or num < 0:
             raise OperationError(space.w_IndexError, space.w_None)
-        return wrap_value(space, read_ptr, self.ll_buffer, num,
-                          self.shape.itemcode)
+        return wrap_value(space, read_ptr, self.ll_buffer, num, self.fmt)
 
     def descr_getitem(self, space, w_index):
         try:
@@ -141,19 +141,16 @@
 
     @unwrap_spec(num=int)
     def descr_itemaddress(self, space, num):
-        itemsize = self.shape.size
-        ptr = rffi.ptradd(self.ll_buffer, itemsize * num)
+        ptr = rffi.ptradd(self.ll_buffer, self.itemsize * num)
         return space.wrap(rffi.cast(lltype.Unsigned, ptr))
 
     def getrawsize(self):
-        itemsize = self.shape.size
-        return itemsize * self.length
+        return self.itemsize * self.length
 
     def decodeslice(self, space, w_slice):
         if not space.isinstance_w(w_slice, space.w_slice):
             raise oefmt(space.w_TypeError, "index must be int or slice")
-        letter = self.shape.itemcode
-        if letter != 'c':
+        if self.fmt != 'c':
             raise oefmt(space.w_TypeError, "only 'c' arrays support slicing")
         w_start = space.getattr(w_slice, space.wrap('start'))
         w_stop = space.getattr(w_slice, space.wrap('stop'))
@@ -192,9 +189,6 @@
         for i in range(len(value)):
             ll_buffer[start + i] = value[i]
 
-    def buffer_w_ex(self, space, flags):
-        return self.buffer_w(space, flags), self.shape.itemcode, 
self.shape.size
-
 
 W_ArrayInstance.typedef = TypeDef(
     'ArrayInstance',
diff --git a/pypy/module/_rawffi/buffer.py b/pypy/module/_rawffi/buffer.py
--- a/pypy/module/_rawffi/buffer.py
+++ b/pypy/module/_rawffi/buffer.py
@@ -14,6 +14,12 @@
     def getlength(self):
         return self.datainstance.getrawsize()
 
+    def getformat(self):
+        return self.datainstance.fmt
+
+    def getitemsize(self):
+        return self.datainstance.itemsize
+
     def getitem(self, index):
         ll_buffer = self.datainstance.ll_buffer
         return ll_buffer[index]
diff --git a/pypy/module/_rawffi/interp_rawffi.py 
b/pypy/module/_rawffi/interp_rawffi.py
--- a/pypy/module/_rawffi/interp_rawffi.py
+++ b/pypy/module/_rawffi/interp_rawffi.py
@@ -337,6 +337,8 @@
 
 
 class W_DataInstance(W_Root):
+    fmt = 'B'
+    itemsize = 1
     def __init__(self, space, size, address=r_uint(0)):
         if address:
             self.ll_buffer = rffi.cast(rffi.VOIDP, address)
diff --git a/pypy/module/array/interp_array.py 
b/pypy/module/array/interp_array.py
--- a/pypy/module/array/interp_array.py
+++ b/pypy/module/array/interp_array.py
@@ -256,8 +256,8 @@
         if oldbuffer:
             lltype.free(oldbuffer, flavor='raw')
 
-    def buffer_w_ex(self, space, flags):
-        return ArrayBuffer(self, False), self.typecode, self.itemsize
+    def buffer_w(self, space, flags):
+        return ArrayBuffer(self, False)
 
     def descr_append(self, space, w_x):
         """ append(x)
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,10 +1,10 @@
 from rpython.rtyper.lltypesystem import rffi, lltype
 from pypy.interpreter.error import oefmt
 from pypy.module.cpyext.api import (
-    cpython_api, Py_buffer, Py_ssize_t, Py_ssize_tP, CONST_STRINGP,
+    cpython_api, Py_buffer, Py_ssize_t, Py_ssize_tP, CONST_STRINGP, cts,
     generic_cpy_call,
     PyBUF_WRITABLE, PyBUF_FORMAT, PyBUF_ND, PyBUF_STRIDES, PyBUF_SIMPLE)
-from pypy.module.cpyext.pyobject import PyObject, Py_IncRef, Py_DecRef
+from pypy.module.cpyext.pyobject import PyObject, incref, Py_DecRef
 
 @cpython_api([PyObject, CONST_STRINGP, Py_ssize_tP], rffi.INT_real, error=-1)
 def PyObject_AsCharBuffer(space, obj, bufferp, sizep):
@@ -35,6 +35,33 @@
         Py_DecRef(space, view.c_obj)
     return 0
 
+def fill_buffer(space, view, pybuf, py_obj):
+    view.c_buf = cts.cast('void *', pybuf.get_raw_address())
+    view.c_obj = py_obj
+    if py_obj:
+        incref(space, py_obj)
+    view.c_len = pybuf.getlength()
+    view.c_itemsize = pybuf.getitemsize()
+    rffi.setintfield(view, 'c_readonly', int(pybuf.readonly))
+    rffi.setintfield(view, 'c_ndim', pybuf.getndim())
+    view.c_format = rffi.str2charp(pybuf.getformat())
+    shape = pybuf.getshape()
+    if not shape:
+        view.c_shape = lltype.nullptr(Py_ssize_tP.TO)
+    else:
+        view.c_shape = cts.cast('Py_ssize_t*', view.c__shape)
+        for i, n in enumerate(shape):
+            view.c_shape[i] = n
+    strides = pybuf.getstrides()
+    if not strides:
+        view.c_strides = lltype.nullptr(Py_ssize_tP.TO)
+    else:
+        view.c_strides = cts.cast('Py_ssize_t*', view.c__strides)
+        for i, n in enumerate(strides):
+            view.c_strides[i] = n
+    view.c_suboffsets = lltype.nullptr(Py_ssize_tP.TO)
+    view.c_internal = lltype.nullptr(rffi.VOIDP.TO)
+
 
 @cpython_api([lltype.Ptr(Py_buffer), PyObject, rffi.VOIDP, Py_ssize_t,
               lltype.Signed, lltype.Signed], rffi.INT, error=-1)
@@ -51,7 +78,7 @@
     view.c_len = length
     view.c_obj = obj
     if obj:
-        Py_IncRef(space, obj)
+        incref(space, obj)
     view.c_itemsize = 1
     rffi.setintfield(view, 'c_readonly', readonly)
     rffi.setintfield(view, 'c_ndim', 1)
diff --git a/pypy/module/cpyext/test/array.c b/pypy/module/cpyext/test/array.c
--- a/pypy/module/cpyext/test/array.c
+++ b/pypy/module/cpyext/test/array.c
@@ -2871,7 +2871,17 @@
     return PyBytes_FromStringAndSize((char*)ptr, size);
 }
 
-
+static PyObject *
+write_buffer_len(PyObject * self, PyObject * obj)
+{
+    void* buf;
+    Py_ssize_t buf_len;
+    if (PyObject_AsWriteBuffer(obj, &buf, &buf_len) < 0) {
+        PyErr_SetString(PyExc_ValueError, "bad value");
+        return NULL;
+    }
+    return PyLong_FromLong(buf_len);
+}
 
 /*********************** Install Module **************************/
 
@@ -2880,6 +2890,7 @@
      PyDoc_STR("Internal. Used for pickling support.")},
     {"switch_multiply",   (PyCFunction)switch_multiply, METH_NOARGS, NULL},
     {"readbuffer_as_string",   (PyCFunction)readbuffer_as_string, 
METH_VARARGS, NULL},
+    {"write_buffer_len", write_buffer_len, METH_O, NULL},
     {NULL, NULL, 0, NULL}        /* Sentinel */
 };
 
diff --git a/pypy/module/cpyext/test/test_arraymodule.py 
b/pypy/module/cpyext/test/test_arraymodule.py
--- a/pypy/module/cpyext/test/test_arraymodule.py
+++ b/pypy/module/cpyext/test/test_arraymodule.py
@@ -84,6 +84,9 @@
         arr = module.array('u', '123')
         view = memoryview(arr)
         assert view.itemsize == 4
+        assert module.write_buffer_len(arr) == 12
+        assert len(module.readbuffer_as_string(arr)) == 12
+        assert len(module.readbuffer_as_string(view)) == 12
 
     def test_subclass(self):
         import struct
diff --git a/pypy/module/cpyext/test/test_buffer.py 
b/pypy/module/cpyext/test/test_buffer.py
--- a/pypy/module/cpyext/test/test_buffer.py
+++ b/pypy/module/cpyext/test/test_buffer.py
@@ -1,5 +1,23 @@
 from pypy.module.cpyext.test.test_cpyext import AppTestCpythonExtensionBase
 
+class AppTestBuffer(AppTestCpythonExtensionBase):
+    def test_AsWriteBuffer(self):
+        import array
+        module = self.import_extension('buffer', [
+            ('write_buffer_len', 'METH_O',
+             """
+             void* buf;
+             Py_ssize_t buf_len;
+             if (PyObject_AsWriteBuffer(args, &buf, &buf_len) < 0) {
+                PyErr_SetString(PyExc_ValueError, "bad value");
+                return NULL;
+             }
+             return PyLong_FromLong(buf_len);
+             """)])
+        assert module.write_buffer_len(bytearray(b'123')) == 3
+        assert module.write_buffer_len(array.array('i', [1, 2, 3])) == 12
+
+
 class AppTestMmap(AppTestCpythonExtensionBase):
     def test_mmap_buffer(self):
         module = self.import_extension('mmap_buffer', [
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
@@ -555,11 +555,10 @@
 
 @slot_function([PyObject, lltype.Ptr(Py_buffer), rffi.INT_real], 
rffi.INT_real, error=-1)
 def bf_getbuffer(space, w_obj, view, flags):
-    from pypy.module.cpyext.buffer import PyBuffer_FillInfo
+    from pypy.module.cpyext.buffer import fill_buffer
     buf = space.buffer_w(w_obj, rffi.cast(lltype.Signed, flags))
-    c_buf = rffi.cast(rffi.VOIDP, buf.get_raw_address())
-    return PyBuffer_FillInfo(space, view, w_obj, c_buf,
-                             space.len_w(w_obj), 0, flags)
+    fill_buffer(space, view, buf, as_pyobj(space, w_obj))
+    return 0
 
 def setup_buffer_procs(space, w_type, pto):
     bufspec = w_type.layout.typedef.buffer
diff --git a/pypy/objspace/std/memoryobject.py 
b/pypy/objspace/std/memoryobject.py
--- a/pypy/objspace/std/memoryobject.py
+++ b/pypy/objspace/std/memoryobject.py
@@ -74,17 +74,18 @@
     def setformat(self, value):
         self.format = value
 
-    def buffer_w_ex(self, space, flags):
+    def buffer_w(self, space, flags):
         self._check_released(space)
         space.check_buf_flags(flags, self.buf.readonly)
-        return self.buf, self.getformat(), self.itemsize
+        return self.buf
 
     @staticmethod
     def descr_new_memoryview(space, w_subtype, w_object):
         if isinstance(w_object, W_MemoryView):
             w_object._check_released(space)
             return W_MemoryView.copy(w_object)
-        return W_MemoryView(*space.buffer_w_ex(w_object, space.BUF_FULL_RO))
+        buf = space.buffer_w(w_object, space.BUF_FULL_RO)
+        return W_MemoryView(buf, buf.getformat(), buf.getitemsize())
 
     def _make_descr__cmp(name):
         def descr__cmp(self, space, w_other):
diff --git a/pypy/objspace/std/test/test_memoryobject.py 
b/pypy/objspace/std/test/test_memoryobject.py
--- a/pypy/objspace/std/test/test_memoryobject.py
+++ b/pypy/objspace/std/test/test_memoryobject.py
@@ -345,9 +345,6 @@
         return MockBuffer(space, self.w_list, self.w_dim, self.w_fmt, \
                           self.w_size, self.w_strides, self.w_shape)
 
-    def buffer_w_ex(self, space, flags):
-        return self.buffer_w(space, flags), space.str_w(self.w_fmt), 
space.int_w(self.w_size)
-
 W_MockArray.typedef = TypeDef("MockArray",
     __new__ = interp2app(W_MockArray.descr_new),
 )
_______________________________________________
pypy-commit mailing list
[email protected]
https://mail.python.org/mailman/listinfo/pypy-commit

Reply via email to