Author: Ronan Lamy <[email protected]>
Branch: buffer-cleanup
Changeset: r89988:6f7a4aa078bd
Date: 2017-02-07 03:08 +0000
http://bitbucket.org/pypy/pypy/changeset/6f7a4aa078bd/
Log: Test and fix for the fields of the Py_buffer not being set correctly
in our bf_getbuffer
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/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
_______________________________________________
pypy-commit mailing list
[email protected]
https://mail.python.org/mailman/listinfo/pypy-commit