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