[pypy-commit] pypy default: test, fix Py_buffer format, which can be a string (issue #2396 and IRC discussion)

mattip pypy.commits at gmail.com
Fri Sep 9 08:40:35 EDT 2016


Author: Matti Picus <matti.picus at gmail.com>
Branch: 
Changeset: r86972:fe0add22fd7e
Date: 2016-09-09 12:37 +0300
http://bitbucket.org/pypy/pypy/changeset/fe0add22fd7e/

Log:	test, fix Py_buffer format, which can be a string (issue #2396 and
	IRC discussion)

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
@@ -119,7 +119,7 @@
 
 constant_names = """
 Py_TPFLAGS_READY Py_TPFLAGS_READYING Py_TPFLAGS_HAVE_GETCHARBUFFER
-METH_COEXIST METH_STATIC METH_CLASS Py_TPFLAGS_BASETYPE
+METH_COEXIST METH_STATIC METH_CLASS Py_TPFLAGS_BASETYPE Py_MAX_FMT
 METH_NOARGS METH_VARARGS METH_KEYWORDS METH_O Py_TPFLAGS_HAVE_INPLACEOPS
 Py_TPFLAGS_HEAPTYPE Py_TPFLAGS_HAVE_CLASS Py_TPFLAGS_HAVE_NEWBUFFER
 Py_LT Py_LE Py_EQ Py_NE Py_GT Py_GE Py_TPFLAGS_CHECKTYPES Py_MAX_NDIMS
@@ -645,7 +645,7 @@
         ('format', rffi.CCHARP),
         ('shape', Py_ssize_tP),
         ('strides', Py_ssize_tP),
-        ('_format', rffi.UCHAR),
+        ('_format', rffi.CFixedArray(rffi.UCHAR, Py_MAX_FMT)),
         ('_shape', rffi.CFixedArray(Py_ssize_t, Py_MAX_NDIMS)),
         ('_strides', rffi.CFixedArray(Py_ssize_t, Py_MAX_NDIMS)),
         ('suboffsets', Py_ssize_tP),
diff --git a/pypy/module/cpyext/include/object.h b/pypy/module/cpyext/include/object.h
--- a/pypy/module/cpyext/include/object.h
+++ b/pypy/module/cpyext/include/object.h
@@ -144,6 +144,7 @@
 
 /* Py3k buffer interface, adapted for PyPy */
 #define Py_MAX_NDIMS 32
+#define Py_MAX_FMT 5
 typedef struct bufferinfo {
     void *buf;
     PyObject *obj;        /* owned reference */
@@ -158,7 +159,7 @@
     Py_ssize_t *shape;
     Py_ssize_t *strides;
     Py_ssize_t *suboffsets; /* alway NULL for app-level objects*/
-    unsigned char _format;
+    unsigned char _format[Py_MAX_FMT];
     Py_ssize_t _strides[Py_MAX_NDIMS];
     Py_ssize_t _shape[Py_MAX_NDIMS];
     /* static store for shape and strides of
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
@@ -1,5 +1,5 @@
 from pypy.module.cpyext.api import (cpython_api, Py_buffer, CANNOT_FAIL,
-                               Py_MAX_NDIMS, build_type_checkers, Py_ssize_tP)
+                         Py_MAX_FMT, Py_MAX_NDIMS, build_type_checkers, Py_ssize_tP)
 from pypy.module.cpyext.pyobject import PyObject, make_ref, incref
 from rpython.rtyper.lltypesystem import lltype, rffi
 from pypy.objspace.std.memoryobject import W_MemoryView
@@ -41,10 +41,22 @@
     view.c_len = w_obj.getlength()
     view.c_itemsize = w_obj.buf.getitemsize()
     rffi.setintfield(view, 'c_ndim', ndim)
-    view.c__format = rffi.cast(rffi.UCHAR, w_obj.buf.getformat())
     view.c_format = rffi.cast(rffi.CCHARP, view.c__format)
     view.c_shape = rffi.cast(Py_ssize_tP, view.c__shape)
     view.c_strides = rffi.cast(Py_ssize_tP, view.c__strides)
+    fmt = w_obj.buf.getformat()
+    n = Py_MAX_FMT - 1 # NULL terminated buffer
+    if len(fmt) > n:
+        ### WARN?
+        pass
+    else:
+        n = len(fmt)
+    for i in range(n):
+        if ord(fmt[i]) > 255:
+            view.c_format[i] = '*'
+        else:
+            view.c_format[i] = fmt[i]
+    view.c_format[n] = '\x00'        
     shape = w_obj.buf.getshape()
     strides = w_obj.buf.getstrides()
     for i in range(ndim):
diff --git a/pypy/module/cpyext/test/test_api.py b/pypy/module/cpyext/test/test_api.py
--- a/pypy/module/cpyext/test/test_api.py
+++ b/pypy/module/cpyext/test/test_api.py
@@ -1,5 +1,5 @@
 import py, pytest
-from rpython.rtyper.lltypesystem import rffi, lltype
+from rpython.rtyper.lltypesystem import lltype
 from pypy.interpreter.baseobjspace import W_Root
 from pypy.module.cpyext.state import State
 from pypy.module.cpyext import api
diff --git a/pypy/module/cpyext/test/test_bufferobject.py b/pypy/module/cpyext/test/test_bufferobject.py
--- a/pypy/module/cpyext/test/test_bufferobject.py
+++ b/pypy/module/cpyext/test/test_bufferobject.py
@@ -1,4 +1,4 @@
-from rpython.rtyper.lltypesystem import rffi, lltype
+from rpython.rtyper.lltypesystem import lltype
 from pypy.module.cpyext.test.test_api import BaseApiTest
 from pypy.module.cpyext.test.test_cpyext import AppTestCpythonExtensionBase
 from pypy.module.cpyext.api import 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
@@ -1,3 +1,4 @@
+from rpython.rtyper.lltypesystem import rffi
 from pypy.module.cpyext.test.test_api import BaseApiTest
 from pypy.module.cpyext.test.test_cpyext import AppTestCpythonExtensionBase
 from rpython.rlib.buffer import StringBuffer
@@ -16,8 +17,12 @@
         w_buf = space.newbuffer(StringBuffer("hello"))
         w_memoryview = api.PyMemoryView_FromObject(w_buf)
         w_view = api.PyMemoryView_GET_BUFFER(w_memoryview)
-        ndim = w_view.c_ndim
-        assert ndim == 1
+        assert w_view.c_ndim == 1
+        f = rffi.charp2str(w_view.c_format)
+        assert f == 'B'
+        assert w_view.c_shape[0] == 5
+        assert w_view.c_strides[0] == 1
+        assert w_view.c_len == 5
 
 class AppTestBufferProtocol(AppTestCpythonExtensionBase):
     def test_buffer_protocol(self):


More information about the pypy-commit mailing list