Author: Ronan Lamy <ronan.l...@gmail.com> Branch: py3.5 Changeset: r91682:a5510f559b24 Date: 2017-07-04 20:24 +0100 http://bitbucket.org/pypy/pypy/changeset/a5510f559b24/
Log: Move CPyBuffer and dependencies to buffer.py 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,158 @@ from rpython.rtyper.lltypesystem import rffi, lltype +from rpython.rlib import rgc # Force registration of gc.collect +from rpython.rlib.buffer import RawBuffer from pypy.interpreter.error import oefmt +from pypy.interpreter.buffer import BufferView from pypy.module.cpyext.api import ( 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, incref, Py_DecRef +from pypy.module.cpyext.typeobjectdefs import releasebufferproc +from pypy.module.cpyext.pyobject import PyObject, incref, decref, as_pyobj + +class CBuffer(RawBuffer): + _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) + +class CPyBuffer(BufferView): + # Similar to Py_buffer + _immutable_ = True + + def __init__(self, space, ptr, size, w_obj, format='B', shape=None, + strides=None, ndim=1, itemsize=1, readonly=True, + needs_decref=False, + releasebufferproc=rffi.cast(rffi.VOIDP, 0)): + self.space = space + self.ptr = ptr + self.size = size + self.w_obj = w_obj # kept alive + self.pyobj = as_pyobj(space, w_obj) + self.format = format + self.ndim = ndim + self.itemsize = itemsize + + # cf. Objects/memoryobject.c:init_shape_strides() + if ndim == 0: + self.shape = [] + self.strides = [] + elif ndim == 1: + if shape is None: + self.shape = [size // itemsize] + else: + self.shape = shape + if strides is None: + self.strides = [itemsize] + else: + self.strides = strides + else: + assert len(shape) == ndim + self.shape = shape + # XXX: missing init_strides_from_shape + self.strides = strides + self.readonly = readonly + self.needs_decref = needs_decref + self.releasebufferproc = releasebufferproc + + def releasebuffer(self): + if self.pyobj: + if self.needs_decref: + if self.releasebufferproc: + func_target = rffi.cast(releasebufferproc, self.releasebufferproc) + with lltype.scoped_alloc(Py_buffer) as pybuf: + pybuf.c_buf = self.ptr + pybuf.c_len = self.size + pybuf.c_ndim = cts.cast('int', self.ndim) + pybuf.c_shape = cts.cast('Py_ssize_t*', pybuf.c__shape) + pybuf.c_strides = cts.cast('Py_ssize_t*', pybuf.c__strides) + for i in range(self.ndim): + pybuf.c_shape[i] = self.shape[i] + pybuf.c_strides[i] = self.strides[i] + if self.format: + pybuf.c_format = rffi.str2charp(self.format) + else: + pybuf.c_format = rffi.str2charp("B") + generic_cpy_call(self.space, func_target, self.pyobj, pybuf) + decref(self.space, self.pyobj) + self.pyobj = lltype.nullptr(PyObject.TO) + else: + #do not call twice + return + + def getlength(self): + return self.size + + 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_str(self): + return CBuffer(self).as_str() + + 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) + + def getformat(self): + return self.format + + def getshape(self): + return self.shape + + def getstrides(self): + return self.strides + + def getitemsize(self): + return self.itemsize + + def getndim(self): + return self.ndim + +class FQ(rgc.FinalizerQueue): + Class = CPyBuffer + def finalizer_trigger(self): + while 1: + buf = self.next_dead() + if not buf: + break + buf.releasebuffer() + +fq = FQ() + @cpython_api([PyObject, CONST_STRINGP, Py_ssize_tP], rffi.INT_real, error=-1) def PyObject_AsCharBuffer(space, obj, bufferp, sizep): @@ -32,7 +180,7 @@ if pb.c_bf_releasebuffer: generic_cpy_call(space, pb.c_bf_releasebuffer, obj, view) - Py_DecRef(space, view.c_obj) + decref(space, view.c_obj) return 0 def fill_buffer(space, view, pybuf, py_obj): @@ -71,7 +219,6 @@ share a contiguous chunk of memory of "unsigned bytes" of the given length. Returns 0 on success and -1 (with raising an error) on error. """ - flags = rffi.cast(lltype.Signed, flags) if flags & PyBUF_WRITABLE and readonly: raise oefmt(space.w_ValueError, "Object is not writable") view.c_buf = buf 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,11 +6,11 @@ get_typedescr, track_reference) from rpython.rtyper.lltypesystem import lltype, rffi from rpython.rlib.rarithmetic import widen -from pypy.interpreter.error import oefmt from pypy.module.cpyext.api import PyBUF_WRITE from pypy.objspace.std.memoryobject import W_MemoryView from pypy.module.cpyext.object import _dealloc from pypy.module.cpyext.import_ import PyImport_Import +from pypy.module.cpyext.buffer import CPyBuffer, fq cts.parse_header(parse_dir / 'cpyext_memoryobject.h') PyMemoryViewObject = cts.gettype('PyMemoryViewObject*') @@ -55,7 +55,6 @@ """ Creates the memory object in the interpreter """ - from pypy.module.cpyext.slotdefs import CPyBuffer, fq py_mem = rffi.cast(PyMemoryViewObject, obj) view = py_mem.c_view ndim = widen(view.c_ndim) @@ -169,7 +168,6 @@ (fort is 'A'). Return 0 otherwise.""" # traverse the strides, checking for consistent stride increases from # right-to-left (c) or left-to-right (fortran). Copied from cpython - if view.c_suboffsets: return 0 if (fort == 'C'): @@ -193,7 +191,6 @@ PyBUF_READ or PyBUF_WRITE. view->format is set to "B" (unsigned bytes). The memoryview has complete buffer information. """ - from pypy.module.cpyext.slotdefs import CPyBuffer readonly = int(widen(flags) == PyBUF_WRITE) view = CPyBuffer(space, cts.cast('void*', mem), size, None, readonly=readonly) 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 @@ -4,7 +4,6 @@ from rpython.rtyper.lltypesystem import rffi, lltype from rpython.rlib.rarithmetic import widen -from rpython.rlib import rgc # Force registration of gc.collect from pypy.module.cpyext.api import ( slot_function, generic_cpy_call, PyObject, Py_ssize_t, Py_buffer, Py_bufferP, PyTypeObjectPtr, cts) @@ -13,22 +12,20 @@ getattrfunc, getattrofunc, setattrofunc, lenfunc, ssizeargfunc, inquiry, ssizessizeargfunc, ssizeobjargproc, iternextfunc, initproc, richcmpfunc, cmpfunc, hashfunc, descrgetfunc, descrsetfunc, objobjproc, objobjargproc, - getbufferproc, releasebufferproc, ssizessizeobjargproc) -from pypy.module.cpyext.pyobject import make_ref, decref, as_pyobj, from_ref + getbufferproc, ssizessizeobjargproc) +from pypy.module.cpyext.pyobject import make_ref, decref, from_ref from pypy.module.cpyext.pyerrors import PyErr_Occurred 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.module.cpyext.buffer import CBuffer, CPyBuffer, fq from pypy.interpreter.error import OperationError, oefmt from pypy.interpreter.argument import Arguments -from rpython.rlib.buffer import RawBuffer from rpython.rlib.unroll import unrolling_iterable from rpython.rlib.objectmodel import specialize, not_rpython from rpython.tool.sourcetools import func_renamer from rpython.flowspace.model import Constant from rpython.flowspace.specialcase import register_flow_sc -from rpython.rtyper.annlowlevel import llhelper from pypy.module.sys.version import CPYTHON_VERSION PY3 = CPYTHON_VERSION[0] == 3 @@ -315,151 +312,6 @@ space.fromcache(State).check_and_raise_exception(always=True) return space.newint(res) -class CPyBuffer(BufferView): - # Similar to Py_buffer - _immutable_ = True - - def __init__(self, space, ptr, size, w_obj, format='B', shape=None, - strides=None, ndim=1, itemsize=1, readonly=True, - needs_decref=False, - releasebufferproc=rffi.cast(rffi.VOIDP, 0)): - self.space = space - self.ptr = ptr - self.size = size - self.w_obj = w_obj # kept alive - self.pyobj = as_pyobj(space, w_obj) - self.format = format - self.ndim = ndim - self.itemsize = itemsize - - # cf. Objects/memoryobject.c:init_shape_strides() - if ndim == 0: - self.shape = [] - self.strides = [] - elif ndim == 1: - if shape is None: - self.shape = [size // itemsize] - else: - self.shape = shape - if strides is None: - self.strides = [itemsize] - else: - self.strides = strides - else: - assert len(shape) == ndim - self.shape = shape - # XXX: missing init_strides_from_shape - self.strides = strides - self.readonly = readonly - self.needs_decref = needs_decref - self.releasebufferproc = releasebufferproc - - def releasebuffer(self): - if self.pyobj: - if self.needs_decref: - if self.releasebufferproc: - func_target = rffi.cast(releasebufferproc, self.releasebufferproc) - with lltype.scoped_alloc(Py_buffer) as pybuf: - pybuf.c_buf = self.ptr - pybuf.c_len = self.size - pybuf.c_ndim = cts.cast('int', self.ndim) - pybuf.c_shape = cts.cast('Py_ssize_t*', pybuf.c__shape) - pybuf.c_strides = cts.cast('Py_ssize_t*', pybuf.c__strides) - for i in range(self.ndim): - pybuf.c_shape[i] = self.shape[i] - pybuf.c_strides[i] = self.strides[i] - if self.format: - pybuf.c_format = rffi.str2charp(self.format) - else: - pybuf.c_format = rffi.str2charp("B") - generic_cpy_call(self.space, func_target, self.pyobj, pybuf) - decref(self.space, self.pyobj) - self.pyobj = lltype.nullptr(PyObject.TO) - else: - #do not call twice - return - - def getlength(self): - return self.size - - 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_str(self): - return CBuffer(self).as_str() - - 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) - - def getformat(self): - return self.format - - def getshape(self): - return self.shape - - def getstrides(self): - return self.strides - - def getitemsize(self): - return self.itemsize - - def getndim(self): - return self.ndim - -class FQ(rgc.FinalizerQueue): - Class = CPyBuffer - def finalizer_trigger(self): - while 1: - buf = self.next_dead() - if not buf: - break - buf.releasebuffer() - -fq = FQ() - - -class CBuffer(RawBuffer): - _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) _______________________________________________ pypy-commit mailing list pypy-commit@python.org https://mail.python.org/mailman/listinfo/pypy-commit