[pypy-commit] pypy default: hg merge
mjacob
pypy.commits at gmail.com
Fri Mar 3 11:23:36 EST 2017
Author: Manuel Jacob <me at manueljacob.de>
Branch:
Changeset: r90513:53fee63aea78
Date: 2017-03-03 17:22 +0100
http://bitbucket.org/pypy/pypy/changeset/53fee63aea78/
Log: hg merge
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
@@ -574,6 +574,7 @@
'PyObject_CallMethod', 'PyObject_CallFunctionObjArgs', 'PyObject_CallMethodObjArgs',
'_PyObject_CallFunction_SizeT', '_PyObject_CallMethod_SizeT',
+ 'PyObject_GetBuffer', 'PyBuffer_Release',
'PyBuffer_FromMemory', 'PyBuffer_FromReadWriteMemory', 'PyBuffer_FromObject',
'PyBuffer_FromReadWriteObject', 'PyBuffer_New', 'PyBuffer_Type', '_Py_get_buffer_type',
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,19 +1,10 @@
from rpython.rtyper.lltypesystem import rffi, lltype
from pypy.interpreter.error import oefmt
from pypy.module.cpyext.api import (
- cpython_api, CANNOT_FAIL, Py_TPFLAGS_HAVE_NEWBUFFER, cts, Py_buffer,
+ cpython_api, CANNOT_FAIL, cts, Py_buffer,
Py_ssize_t, Py_ssize_tP, generic_cpy_call,
PyBUF_WRITABLE, PyBUF_FORMAT, PyBUF_ND, PyBUF_STRIDES)
-from pypy.module.cpyext.pyobject import PyObject, Py_IncRef, Py_DecRef
-
- at cpython_api([PyObject], rffi.INT_real, error=CANNOT_FAIL)
-def PyObject_CheckBuffer(space, pyobj):
- """Return 1 if obj supports the buffer interface otherwise 0."""
- as_buffer = pyobj.c_ob_type.c_tp_as_buffer
- flags = pyobj.c_ob_type.c_tp_flags
- if (flags & Py_TPFLAGS_HAVE_NEWBUFFER and as_buffer.c_bf_getbuffer):
- return 1
- return 0
+from pypy.module.cpyext.pyobject import PyObject, Py_IncRef
@cpython_api([lltype.Ptr(Py_buffer), PyObject, rffi.VOIDP, Py_ssize_t,
lltype.Signed, lltype.Signed], rffi.INT, error=-1)
@@ -48,23 +39,3 @@
view.c_internal = lltype.nullptr(rffi.VOIDP.TO)
return 0
-
-
- at cpython_api([lltype.Ptr(Py_buffer)], lltype.Void, error=CANNOT_FAIL)
-def PyBuffer_Release(space, view):
- """
- Release the buffer view. This should be called when the buffer is
- no longer being used as it may free memory from it
- """
- obj = view.c_obj
- if not obj:
- return
- assert obj.c_ob_type
- as_buffer = obj.c_ob_type.c_tp_as_buffer
- if as_buffer:
- func = as_buffer.c_bf_releasebuffer
- if func:
- generic_cpy_call(space, func, obj, view)
- Py_DecRef(space, obj)
- view.c_obj = lltype.nullptr(PyObject.TO)
- # XXX do other fields leak memory?
diff --git a/pypy/module/cpyext/include/Python.h b/pypy/module/cpyext/include/Python.h
--- a/pypy/module/cpyext/include/Python.h
+++ b/pypy/module/cpyext/include/Python.h
@@ -79,6 +79,7 @@
#include "pyconfig.h"
#include "object.h"
+#include "abstract.h"
#include "pymath.h"
#include "pyport.h"
#include "warnings.h"
diff --git a/pypy/module/cpyext/include/abstract.h b/pypy/module/cpyext/include/abstract.h
--- a/pypy/module/cpyext/include/abstract.h
+++ b/pypy/module/cpyext/include/abstract.h
@@ -1,1 +1,35 @@
-/* empty */
+#ifndef Py_ABSTRACTOBJECT_H
+#define Py_ABSTRACTOBJECT_H
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+ /* new buffer API */
+
+#define PyObject_CheckBuffer(obj) \
+ (((obj)->ob_type->tp_as_buffer != NULL) && \
+ (PyType_HasFeature((obj)->ob_type, Py_TPFLAGS_HAVE_NEWBUFFER)) && \
+ ((obj)->ob_type->tp_as_buffer->bf_getbuffer != NULL))
+
+ /* Return 1 if the getbuffer function is available, otherwise
+ return 0 */
+
+ PyAPI_FUNC(int) PyObject_GetBuffer(PyObject *obj, Py_buffer *view,
+ int flags);
+
+ /* This is a C-API version of the getbuffer function call. It checks
+ to make sure object has the required function pointer and issues the
+ call. Returns -1 and raises an error on failure and returns 0 on
+ success
+ */
+
+ PyAPI_FUNC(void) PyBuffer_Release(Py_buffer *view);
+
+ /* Releases a Py_buffer obtained from getbuffer ParseTuple's s*.
+ */
+
+
+#ifdef __cplusplus
+}
+#endif
+#endif /* Py_ABSTRACTOBJECT_H */
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
@@ -97,35 +97,6 @@
_dealloc(space, py_obj)
- at cpython_api([PyObject, Py_bufferP, rffi.INT_real],
- rffi.INT_real, error=-1)
-def PyObject_GetBuffer(space, w_obj, view, flags):
- """Export obj into a Py_buffer, view. These arguments must
- never be NULL. The flags argument is a bit field indicating what
- kind of buffer the caller is prepared to deal with and therefore what
- kind of buffer the exporter is allowed to return. The buffer interface
- allows for complicated memory sharing possibilities, but some caller may
- not be able to handle all the complexity but may want to see if the
- exporter will let them take a simpler view to its memory.
-
- Some exporters may not be able to share memory in every possible way and
- may need to raise errors to signal to some consumers that something is
- just not possible. These errors should be a BufferError unless
- there is another error that is actually causing the problem. The
- exporter can use flags information to simplify how much of the
- Py_buffer structure is filled in with non-default values and/or
- raise an error if the object can't support a simpler view of its memory.
-
- 0 is returned on success and -1 on error."""
- if not PyObject_CheckBuffer(space, w_obj):
- raise oefmt(space.w_TypeError,
- "'%T' does not have the buffer interface", w_obj)
- py_obj = as_pyobj(space, w_obj)
- func = py_obj.c_ob_type.c_tp_as_buffer.c_bf_getbuffer
- ret = generic_cpy_call(space, func, py_obj, view, flags)
- keepalive_until_here(w_obj)
- return ret
-
def fill_Py_buffer(space, buf, view):
# c_buf, c_obj have been filled in
ndim = buf.getndim()
diff --git a/pypy/module/cpyext/src/abstract.c b/pypy/module/cpyext/src/abstract.c
--- a/pypy/module/cpyext/src/abstract.c
+++ b/pypy/module/cpyext/src/abstract.c
@@ -101,6 +101,30 @@
return 0;
}
+/* Buffer C-API for Python 3.0 */
+
+int
+PyObject_GetBuffer(PyObject *obj, Py_buffer *view, int flags)
+{
+ if (!PyObject_CheckBuffer(obj)) {
+ PyErr_Format(PyExc_TypeError,
+ "'%100s' does not have the buffer interface",
+ Py_TYPE(obj)->tp_name);
+ return -1;
+ }
+ return (*(obj->ob_type->tp_as_buffer->bf_getbuffer))(obj, view, flags);
+}
+
+void
+PyBuffer_Release(Py_buffer *view)
+{
+ PyObject *obj = view->obj;
+ if (obj && Py_TYPE(obj)->tp_as_buffer && Py_TYPE(obj)->tp_as_buffer->bf_releasebuffer)
+ Py_TYPE(obj)->tp_as_buffer->bf_releasebuffer(obj, view);
+ Py_XDECREF(obj);
+ view->obj = NULL;
+}
+
/* Operations on callable objects */
static PyObject*
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
@@ -10,15 +10,6 @@
only_pypy ="config.option.runappdirect and '__pypy__' not in sys.builtin_module_names"
class TestMemoryViewObject(BaseApiTest):
- def test_fromobject(self, space, api):
- w_hello = space.newbytes("hello")
- assert api.PyObject_CheckBuffer(w_hello)
- w_view = from_ref(space, api.PyMemoryView_FromObject(w_hello))
- w_char = space.call_method(w_view, '__getitem__', space.wrap(0))
- assert space.eq_w(w_char, space.wrap('h'))
- w_bytes = space.call_method(w_view, "tobytes")
- assert space.unwrap(w_bytes) == "hello"
-
def test_frombuffer(self, space, api):
w_buf = space.newbuffer(StringBuffer("hello"))
c_memoryview = rffi.cast(
@@ -74,6 +65,19 @@
del result
class AppTestBufferProtocol(AppTestCpythonExtensionBase):
+ def test_fromobject(self):
+ foo = self.import_extension('foo', [
+ ("make_view", "METH_O",
+ """
+ if (!PyObject_CheckBuffer(args))
+ return Py_None;
+ return PyMemoryView_FromObject(args);
+ """)])
+ hello = b'hello'
+ mview = foo.make_view(hello)
+ assert mview[0] == hello[0]
+ assert mview.tobytes() == hello
+
def test_buffer_protocol_app(self):
import struct
module = self.import_module(name='buffer_test')
More information about the pypy-commit
mailing list