Author: Manuel Jacob <m...@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
-
-@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
-
-
-@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)
 
 
-@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')
_______________________________________________
pypy-commit mailing list
pypy-commit@python.org
https://mail.python.org/mailman/listinfo/pypy-commit

Reply via email to