Author: Ronan Lamy <ronan.l...@gmail.com> Branch: PyBuffer-backport Changeset: r91202:302a031b3560 Date: 2017-05-08 16:50 +0100 http://bitbucket.org/pypy/pypy/changeset/302a031b3560/
Log: Backport cpyext changes diff --git a/pypy/interpreter/baseobjspace.py b/pypy/interpreter/baseobjspace.py --- a/pypy/interpreter/baseobjspace.py +++ b/pypy/interpreter/baseobjspace.py @@ -221,7 +221,8 @@ if w_impl is not None: w_result = space.get_and_call_function(w_impl, self, space.newint(flags)) - if space.isinstance_w(w_result, space.w_buffer): + if (space.isinstance_w(w_result, space.w_buffer) or + space.isinstance_w(w_result, space.w_memoryview)): return w_result.buffer_w(space, flags) raise BufferInterfaceNotFound @@ -233,7 +234,8 @@ if w_impl is not None: w_result = space.get_and_call_function(w_impl, self, space.newint(space.BUF_FULL_RO)) - if space.isinstance_w(w_result, space.w_buffer): + if (space.isinstance_w(w_result, space.w_buffer) or + space.isinstance_w(w_result, space.w_memoryview)): return w_result.readbuf_w(space) raise BufferInterfaceNotFound @@ -245,7 +247,8 @@ if w_impl is not None: w_result = space.get_and_call_function(w_impl, self, space.newint(space.BUF_FULL)) - if space.isinstance_w(w_result, space.w_buffer): + if (space.isinstance_w(w_result, space.w_buffer) or + space.isinstance_w(w_result, space.w_memoryview)): return w_result.writebuf_w(space) raise BufferInterfaceNotFound @@ -254,7 +257,8 @@ if w_impl is not None: w_result = space.get_and_call_function(w_impl, self, space.newint(space.BUF_FULL_RO)) - if space.isinstance_w(w_result, space.w_buffer): + if (space.isinstance_w(w_result, space.w_buffer) or + space.isinstance_w(w_result, space.w_memoryview)): return w_result.charbuf_w(space) raise BufferInterfaceNotFound 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 @@ -41,15 +41,15 @@ assert isinstance(w_obj, W_MemoryView) py_obj = rffi.cast(PyMemoryViewObject, py_obj) view = py_obj.c_view - ndim = w_obj.buf.getndim() + ndim = w_obj.getndim() if ndim >= Py_MAX_NDIMS: # XXX warn? return - fill_Py_buffer(space, w_obj.buf, view) + fill_Py_buffer(space, w_obj.view, view) try: - view.c_buf = rffi.cast(rffi.VOIDP, w_obj.buf.get_raw_address()) + view.c_buf = rffi.cast(rffi.VOIDP, w_obj.view.get_raw_address()) view.c_obj = make_ref(space, w_userdata) - rffi.setintfield(view, 'c_readonly', w_obj.buf.readonly) + rffi.setintfield(view, 'c_readonly', w_obj.view.readonly) except ValueError: w_s = w_obj.descr_tobytes(space) view.c_obj = make_ref(space, w_s) @@ -95,7 +95,6 @@ mem_obj.c_view.c_obj = rffi.cast(PyObject, 0) _dealloc(space, py_obj) - def fill_Py_buffer(space, buf, view): # c_buf, c_obj have been filled in ndim = buf.getndim() diff --git a/pypy/module/cpyext/slotdefs.py b/pypy/module/cpyext/slotdefs.py --- a/pypy/module/cpyext/slotdefs.py +++ b/pypy/module/cpyext/slotdefs.py @@ -19,8 +19,10 @@ from pypy.module.cpyext.memoryobject import fill_Py_buffer from pypy.module.cpyext.state import State from pypy.module.cpyext import userslot +from pypy.interpreter.buffer import BufferView from pypy.interpreter.error import OperationError, oefmt from pypy.interpreter.argument import Arguments + from rpython.rlib.buffer import Buffer from rpython.rlib.unroll import unrolling_iterable from rpython.rlib.objectmodel import specialize, not_rpython @@ -322,7 +324,7 @@ space.fromcache(State).check_and_raise_exception(always=True) return space.newint(res) -class CPyBuffer(Buffer): +class CPyBuffer(BufferView): # Similar to Py_buffer _immutable_ = True @@ -333,9 +335,12 @@ self.space = space self.ptr = ptr self.size = size - self.w_obj = w_obj # kept alive + self.w_obj = w_obj # kept alive self.pyobj = as_pyobj(space, w_obj) self.format = format + self.ndim = ndim + self.itemsize = itemsize + if not shape: self.shape = [size] else: @@ -344,8 +349,6 @@ self.strides = [1] else: self.strides = strides - self.ndim = ndim - self.itemsize = itemsize self.readonly = readonly self.needs_decref = needs_decref self.releasebufferproc = releasebufferproc @@ -378,8 +381,20 @@ def getlength(self): return self.size - def getitem(self, index): - return self.ptr[index] + def getbytes(self, start, size): + return ''.join([self.ptr[i] for i in range(start, start + size)]) + + def setbytes(self, start, string): + # absolutely no safety checks, what could go wrong? + for i in range(len(string)): + self.ptr[start + i] = string[i] + + def as_readbuf(self): + return CBuffer(self) + + def as_writebuf(self): + assert not self.readonly + return CBuffer(self) def get_raw_address(self): return rffi.cast(rffi.CCHARP, self.ptr) @@ -399,10 +414,6 @@ def getndim(self): return self.ndim - def setitem(self, index, char): - # absolutely no safety checks, what could go wrong? - self.ptr[index] = char - class FQ(rgc.FinalizerQueue): Class = CPyBuffer def finalizer_trigger(self): @@ -414,6 +425,37 @@ fq = FQ() + +class CBuffer(Buffer): + _immutable_ = True + def __init__(self, view): + self.view = view + self.readonly = view.readonly + + def getlength(self): + return self.view.getlength() + + def getitem(self, index): + return self.view.ptr[index] + + def getslice(self, start, stop, step, size): + assert step == 1 + assert stop - start == size + ptr = rffi.ptradd(cts.cast('char *', self.view.ptr), start) + return rffi.charpsize2str(ptr, size) + + def setitem(self, index, char): + self.view.ptr[index] = char + + def setslice(self, index, s): + assert s is not None + ptr = rffi.ptradd(cts.cast('char *', self.view.ptr), index) + rffi.str2chararray(s, ptr, len(s)) + + def get_raw_address(self): + return cts.cast('char *', self.view.ptr) + + def wrap_getreadbuffer(space, w_self, w_args, func): func_target = rffi.cast(readbufferproc, func) py_obj = make_ref(space, w_self) @@ -430,7 +472,7 @@ buf = CPyBuffer(space, ptr[0], size, w_self, releasebufferproc=rbp) fq.register_finalizer(buf) - return space.newbuffer(buf) + return buf.wrap(space) def wrap_getwritebuffer(space, w_self, w_args, func): func_target = rffi.cast(readbufferproc, func) @@ -448,7 +490,7 @@ buf = CPyBuffer(space, ptr[0], size, w_self, readonly=False, releasebufferproc=rbp) fq.register_finalizer(buf) - return space.newbuffer(buf) + return buf.wrap(space) def wrap_getbuffer(space, w_self, w_args, func): func_target = rffi.cast(getbufferproc, func) @@ -490,7 +532,7 @@ needs_decref=True, releasebufferproc = rbp) fq.register_finalizer(buf) - return space.newbuffer(buf) + return buf.wrap(space) def get_richcmp_func(OP_CONST): def inner(space, w_self, w_args, func): @@ -667,6 +709,7 @@ def slot_tp_getattro(space, w_self, w_name): return space.call_function(getattr_fn, w_self, w_name) slot_func = slot_tp_getattro + elif name == 'tp_call': call_fn = w_type.getdictvalue(space, '__call__') if call_fn is None: @@ -744,24 +787,24 @@ @slot_function([PyObject, Py_bufferP, rffi.INT_real], rffi.INT_real, error=-1) @func_renamer("cpyext_%s_%s" % (name, typedef.name)) - def buff_w(space, w_self, view, flags): + def buff_w(space, w_self, c_view, flags): args = Arguments(space, [space.newint(flags)]) w_obj = space.call_args(space.get(buff_fn, w_self), args) - if view: + if c_view: #like PyObject_GetBuffer flags = widen(flags) buf = space.buffer_w(w_obj, flags) try: - view.c_buf = rffi.cast(rffi.VOIDP, buf.get_raw_address()) - view.c_obj = make_ref(space, w_obj) + c_view.c_buf = rffi.cast(rffi.VOIDP, buf.get_raw_address()) + c_view.c_obj = make_ref(space, w_obj) except ValueError: s = buf.as_str() w_s = space.newbytes(s) - view.c_obj = make_ref(space, w_s) - view.c_buf = rffi.cast(rffi.VOIDP, rffi.str2charp( + c_view.c_obj = make_ref(space, w_s) + c_view.c_buf = rffi.cast(rffi.VOIDP, rffi.str2charp( s, track_allocation=False)) - rffi.setintfield(view, 'c_readonly', 1) - ret = fill_Py_buffer(space, buf, view) + rffi.setintfield(c_view, 'c_readonly', 1) + ret = fill_Py_buffer(space, buf, c_view) return ret return 0 return buff_w @@ -771,23 +814,23 @@ @slot_function([PyObject, Py_bufferP, rffi.INT_real], rffi.INT_real, error=-1) @func_renamer("cpyext_%s_%s" % (name, typedef.name)) - def buff_w(space, w_self, view, flags): + def buff_w(space, w_self, c_view, flags): w_obj = w_self - if view: + if c_view: #like PyObject_GetBuffer flags = widen(flags) buf = space.buffer_w(w_obj, flags) try: - view.c_buf = rffi.cast(rffi.VOIDP, buf.get_raw_address()) - view.c_obj = make_ref(space, w_obj) + c_view.c_buf = rffi.cast(rffi.VOIDP, buf.get_raw_address()) + c_view.c_obj = make_ref(space, w_obj) except ValueError: s = buf.as_str() w_s = space.newbytes(s) - view.c_obj = make_ref(space, w_s) - view.c_buf = rffi.cast(rffi.VOIDP, rffi.str2charp( + c_view.c_obj = make_ref(space, w_s) + c_view.c_buf = rffi.cast(rffi.VOIDP, rffi.str2charp( s, track_allocation=False)) - rffi.setintfield(view, 'c_readonly', 1) - ret = fill_Py_buffer(space, buf, view) + rffi.setintfield(c_view, 'c_readonly', 1) + ret = fill_Py_buffer(space, buf, c_view) return ret return 0 return buff_w diff --git a/pypy/module/cpyext/test/buffer_test.c b/pypy/module/cpyext/test/buffer_test.c --- a/pypy/module/cpyext/test/buffer_test.c +++ b/pypy/module/cpyext/test/buffer_test.c @@ -344,6 +344,7 @@ #endif if (m == NULL) INITERROR; + PyMyArrayType.tp_new = PyType_GenericNew; if (PyType_Ready(&PyMyArrayType) < 0) INITERROR; Py_INCREF(&PyMyArrayType); 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 @@ -111,7 +111,7 @@ PyObject* obj = PyTuple_GetItem(args, 0); PyObject* memoryview = PyMemoryView_FromObject(obj); if (memoryview == NULL) - return PyLong_FromLong(-1); + return NULL; view = PyMemoryView_GET_BUFFER(memoryview); Py_DECREF(memoryview); return PyLong_FromLong(view->len / view->itemsize); _______________________________________________ pypy-commit mailing list pypy-commit@python.org https://mail.python.org/mailman/listinfo/pypy-commit