[pypy-svn] pypy default: Add buffer() support for PyTypeObjects which define tp_as_buffer.bf_getreadbuffer
amauryfa
commits-noreply at bitbucket.org
Sat Apr 9 00:04:14 CEST 2011
Author: Amaury Forgeot d'Arc <amauryfa at gmail.com>
Branch:
Changeset: r43239:f83b7a19ee72
Date: 2011-04-09 00:03 +0200
http://bitbucket.org/pypy/pypy/changeset/f83b7a19ee72/
Log: Add buffer() support for PyTypeObjects which define
tp_as_buffer.bf_getreadbuffer
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
@@ -10,7 +10,7 @@
cpython_api, cpython_struct, bootstrap_function, Py_ssize_t,
generic_cpy_call, Py_TPFLAGS_READY, Py_TPFLAGS_READYING,
Py_TPFLAGS_HEAPTYPE, METH_VARARGS, METH_KEYWORDS, CANNOT_FAIL,
- PyBufferProcs, build_type_checkers)
+ build_type_checkers)
from pypy.module.cpyext.pyobject import (
PyObject, make_ref, create_ref, from_ref, get_typedescr, make_typedescr,
track_reference, RefcountState, borrow_from)
@@ -24,7 +24,7 @@
from pypy.module.cpyext.structmember import PyMember_GetOne, PyMember_SetOne
from pypy.module.cpyext.typeobjectdefs import (
PyTypeObjectPtr, PyTypeObject, PyGetSetDef, PyMemberDef, newfunc,
- PyNumberMethods, PySequenceMethods)
+ PyNumberMethods, PySequenceMethods, PyBufferProcs)
from pypy.module.cpyext.slotdefs import (
slotdefs_for_tp_slots, slotdefs_for_wrappers, get_slot_tp_function)
from pypy.interpreter.error import OperationError
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
@@ -1,16 +1,18 @@
import re
from pypy.rpython.lltypesystem import rffi, lltype
-from pypy.module.cpyext.api import generic_cpy_call, cpython_api, PyObject
+from pypy.module.cpyext.api import (
+ cpython_api, generic_cpy_call, PyObject, Py_ssize_t)
from pypy.module.cpyext.typeobjectdefs import (
unaryfunc, wrapperfunc, ternaryfunc, PyTypeObjectPtr, binaryfunc,
getattrfunc, getattrofunc, setattrofunc, lenfunc, ssizeargfunc,
ssizessizeargfunc, ssizeobjargproc, iternextfunc, initproc, richcmpfunc,
- cmpfunc, hashfunc, descrgetfunc, descrsetfunc, objobjproc)
+ cmpfunc, hashfunc, descrgetfunc, descrsetfunc, objobjproc, readbufferproc)
from pypy.module.cpyext.pyobject import from_ref
from pypy.module.cpyext.pyerrors import PyErr_Occurred
from pypy.module.cpyext.state import State
from pypy.interpreter.error import OperationError, operationerrfmt
+from pypy.interpreter.buffer import Buffer as W_Buffer
from pypy.interpreter.argument import Arguments
from pypy.rlib.unroll import unrolling_iterable
from pypy.rlib.objectmodel import specialize
@@ -193,6 +195,29 @@
check_num_args(space, w_args, 0)
return space.wrap(generic_cpy_call(space, func_target, w_self))
+class CPyBuffer(W_Buffer):
+ # Similar to Py_buffer
+
+ def __init__(self, ptr, size, w_obj):
+ self.ptr = ptr
+ self.size = size
+ self.w_obj = w_obj # kept alive
+
+ def getlength(self):
+ return self.size
+
+ def getitem(self, index):
+ return self.ptr[index]
+
+def wrap_getreadbuffer(space, w_self, w_args, func):
+ func_target = rffi.cast(readbufferproc, func)
+ with lltype.scoped_alloc(rffi.VOIDPP.TO, 1) as ptr:
+ index = rffi.cast(Py_ssize_t, 0)
+ size = generic_cpy_call(space, func_target, w_self, index, ptr)
+ if size < 0:
+ space.fromcache(State).check_and_raise_exception(always=True)
+ return space.wrap(CPyBuffer(ptr[0], size, w_self))
+
def get_richcmp_func(OP_CONST):
def inner(space, w_self, w_args, func):
func_target = rffi.cast(richcmpfunc, func)
@@ -589,12 +614,19 @@
for regex, repl in slotdef_replacements:
slotdefs_str = re.sub(regex, repl, slotdefs_str)
+slotdefs = eval(slotdefs_str)
+# PyPy addition
+slotdefs += (
+ TPSLOT("__buffer__", "tp_as_buffer.c_bf_getreadbuffer", None, "wrap_getreadbuffer", ""),
+)
+
slotdefs_for_tp_slots = unrolling_iterable(
[(x.method_name, x.slot_name, x.slot_names, x.slot_func)
- for x in eval(slotdefs_str)])
+ for x in slotdefs])
+
slotdefs_for_wrappers = unrolling_iterable(
[(x.method_name, x.slot_names, x.wrapper_func, x.wrapper_func_kwds, x.doc)
- for x in eval(slotdefs_str)])
+ for x in slotdefs])
if __name__ == "__main__":
print slotdefs_str
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
@@ -42,3 +42,13 @@
assert arr[1:].tolist() == [2,3,4]
assert arr[:2].tolist() == [1,2]
assert arr[1:3].tolist() == [2,3]
+
+ def test_buffer(self):
+ module = self.import_module(name='array')
+ arr = module.array('i', [1,2,3,4])
+ # XXX big-endian
+ assert str(buffer(arr)) == ('\x01\0\0\0'
+ '\x02\0\0\0'
+ '\x03\0\0\0'
+ '\x04\0\0\0')
+
diff --git a/pypy/module/cpyext/typeobjectdefs.py b/pypy/module/cpyext/typeobjectdefs.py
--- a/pypy/module/cpyext/typeobjectdefs.py
+++ b/pypy/module/cpyext/typeobjectdefs.py
@@ -1,9 +1,8 @@
from pypy.rpython.lltypesystem import rffi, lltype
from pypy.rpython.lltypesystem.lltype import Ptr, FuncType, Void
-from pypy.module.cpyext.api import cpython_struct, \
- PyVarObjectFields, Py_ssize_t, Py_TPFLAGS_READYING, \
- Py_TPFLAGS_READY, Py_TPFLAGS_HEAPTYPE, \
- PyTypeObject, PyTypeObjectPtr, PyBufferProcs, FILEP
+from pypy.module.cpyext.api import (cpython_struct, Py_ssize_t, Py_ssize_tP,
+ PyVarObjectFields, PyTypeObject, PyTypeObjectPtr, FILEP,
+ Py_TPFLAGS_READYING, Py_TPFLAGS_READY, Py_TPFLAGS_HEAPTYPE)
from pypy.module.cpyext.pyobject import PyObject, make_ref, from_ref
from pypy.module.cpyext.modsupport import PyMethodDef
@@ -55,6 +54,14 @@
wrapperfunc = P(FT([PyO, PyO, rffi.VOIDP], PyO))
wrapperfunc_kwds = P(FT([PyO, PyO, rffi.VOIDP, PyO], PyO))
+readbufferproc = P(FT([PyO, Py_ssize_t, rffi.VOIDPP], Py_ssize_t))
+writebufferproc = P(FT([PyO, Py_ssize_t, rffi.VOIDPP], Py_ssize_t))
+segcountproc = P(FT([PyO, Py_ssize_tP], Py_ssize_t))
+charbufferproc = P(FT([PyO, Py_ssize_t, rffi.CCHARPP], Py_ssize_t))
+## We don't support new buffer interface for now
+getbufferproc = rffi.VOIDP
+releasebufferproc = rffi.VOIDP
+
PyGetSetDef = cpython_struct("PyGetSetDef", (
("name", rffi.CCHARP),
@@ -127,7 +134,6 @@
("mp_ass_subscript", objobjargproc),
))
-"""
PyBufferProcs = cpython_struct("PyBufferProcs", (
("bf_getreadbuffer", readbufferproc),
("bf_getwritebuffer", writebufferproc),
@@ -136,7 +142,6 @@
("bf_getbuffer", getbufferproc),
("bf_releasebuffer", releasebufferproc),
))
-"""
PyMemberDef = cpython_struct("PyMemberDef", (
("name", rffi.CCHARP),
diff --git a/pypy/module/cpyext/api.py b/pypy/module/cpyext/api.py
--- a/pypy/module/cpyext/api.py
+++ b/pypy/module/cpyext/api.py
@@ -400,21 +400,9 @@
# So we need a forward and backward mapping in our State instance
PyObjectStruct = lltype.ForwardReference()
PyObject = lltype.Ptr(PyObjectStruct)
-PyBufferProcs = lltype.ForwardReference()
PyObjectFields = (("ob_refcnt", lltype.Signed), ("ob_type", PyTypeObjectPtr))
-def F(ARGS, RESULT=lltype.Signed):
- return lltype.Ptr(lltype.FuncType(ARGS, RESULT))
-PyBufferProcsFields = (
- ("bf_getreadbuffer", F([PyObject, lltype.Signed, rffi.VOIDPP])),
- ("bf_getwritebuffer", F([PyObject, lltype.Signed, rffi.VOIDPP])),
- ("bf_getsegcount", F([PyObject, rffi.INTP])),
- ("bf_getcharbuffer", F([PyObject, lltype.Signed, rffi.CCHARPP])),
-# we don't support new buffer interface for now
- ("bf_getbuffer", rffi.VOIDP),
- ("bf_releasebuffer", rffi.VOIDP))
PyVarObjectFields = PyObjectFields + (("ob_size", Py_ssize_t), )
cpython_struct('PyObject', PyObjectFields, PyObjectStruct)
-cpython_struct('PyBufferProcs', PyBufferProcsFields, PyBufferProcs)
PyVarObjectStruct = cpython_struct("PyVarObject", PyVarObjectFields)
PyVarObject = lltype.Ptr(PyVarObjectStruct)
More information about the Pypy-commit
mailing list