Commits

Jean-Paul Calderone committed 31d9ac4

some assorted changes trying to add new-style buffer support to PyArg_ParseTuple - not working

Comments (0)

Files changed (5)

pypy/module/cpyext/object.py

 
 @cpython_api([lltype.Ptr(Py_buffer)], lltype.Void, error=CANNOT_FAIL)
 def PyBuffer_Release(space, view):
+    print 'releasing', view.c_obj
     Py_DecRef(space, view.c_obj)

pypy/module/cpyext/src/getargs.c

 	case 's': {/* string */
 		if (*format == '*') {
 			Py_buffer *p = (Py_buffer *)va_arg(*p_va, Py_buffer *);
-
+                        printf("star case\n");
 			if (PyString_Check(arg)) {
 				PyBuffer_FillInfo(p, arg,
 						  PyString_AS_STRING(arg), PyString_GET_SIZE(arg),
 						  1, 0);
-			} else {
-                            PyErr_SetString(
-                                PyExc_NotImplementedError,
-                                "s* not implemented for non-string values");
-                            return NULL;
-                        }
+			}
 #if 0
 #ifdef Py_USING_UNICODE
 			else if (PyUnicode_Check(arg)) {
 						  1, 0);
 			}
 #endif
+#endif
 			else { /* any buffer-like object */
 				char *buf;
+                                printf("about to getbuffer\n");
 				if (getbuffer(arg, p, &buf) < 0)
 					return converterr(buf, arg, msgbuf, bufsize);
 			}
-#endif
 			if (addcleanup(p, freelist, cleanup_buffer)) {
 				return converterr(
 					"(cleanup problem)",
 {
 	PyBufferProcs *pb = arg->ob_type->tp_as_buffer;
 	Py_ssize_t count;
+#if 0
 	if (pb == NULL ||
 	    pb->bf_getreadbuffer == NULL ||
 	    pb->bf_getsegcount == NULL ||
 		*errmsg = "string or single-segment read-only buffer";
 		return -1;
 	}
+#endif
 	if ((count = (*pb->bf_getreadbuffer)(arg, 0, p)) < 0) {
 		*errmsg = "(unspecified)";
 	}
 	return count;
 }
 
-#if 0 //YYY
 static int
 getbuffer(PyObject *arg, Py_buffer *view, char **errmsg)
 {
 	void *buf;
 	Py_ssize_t count;
 	PyBufferProcs *pb = arg->ob_type->tp_as_buffer;
+        printf("pb %p\n", pb);
 	if (pb == NULL) {
 		*errmsg = "string or buffer";
 		return -1;
 	}
+
 	if (pb->bf_getbuffer) {
 		if (pb->bf_getbuffer(arg, view, 0) < 0) {
 			*errmsg = "convertible to a buffer";
 			return -1;
 		}
+#if 0
 		if (!PyBuffer_IsContiguous(view, 'C')) {
 			*errmsg = "contiguous buffer";
 			return -1;
 		}
+#endif
 		return 0;
 	}
 
+        printf("about to convertbuffer\n");
 	count = convertbuffer(arg, &buf, errmsg);
 	if (count < 0) {
+            printf("error converting it\n");
 		*errmsg = "convertible to a buffer";
 		return count;
 	}
+        printf("converted it\n");
 	PyBuffer_FillInfo(view, NULL, buf, count, 1, 0);
 	return 0;
 }
-#endif
 
 /* Support for keyword arguments donated by
    Geoff Philbrick <philbric@delphi.hks.com> */

pypy/module/cpyext/test/test_getargs.py

         assert 'foo\0bar\0baz' == pybuffer('foo\0bar\0baz')
 
 
+    def test_pyarg_parse_buffer_py_buffer(self):
+        """
+        The `s*` format specifier can also be used to parse a memoryview into a
+        Py_buffer structure containing a pointer to the memoryview's data and
+        the length of that data.
+        """
+        memview = self.import_parser(
+            '''
+            Py_buffer buf;
+            PyObject *result;
+            printf("about to parse\\n");
+            if (!PyArg_ParseTuple(args, "s*", &buf)) {
+                printf("parse fail\\n");
+                return NULL;
+            }
+            printf("parse win\\n");
+            result = PyString_FromStringAndSize(buf.buf, buf.len);
+            printf("release\\n");
+            PyBuffer_Release(&buf);
+            printf("return\\n");
+            return result;
+            ''')
+        raises(TypeError, "memview(None)")
+        raises(TypeError, "memview(3)")
+        assert 'foo\0bar\0baz' == memview(memoryview('foo\0bar\0baz'))
+        assert 'foo\0bar\0baz' == memview(buffer('foo\0bar\0baz'))
+
+
     def test_pyarg_parse_charbuf_and_length(self):
         """
         The `t#` format specifier can be used to parse a read-only 8-bit

pypy/module/cpyext/typeobject.py

     cpython_api, cpython_struct, bootstrap_function, Py_ssize_t, Py_ssize_tP,
     generic_cpy_call, Py_TPFLAGS_READY, Py_TPFLAGS_READYING,
     Py_TPFLAGS_HEAPTYPE, METH_VARARGS, METH_KEYWORDS, CANNOT_FAIL,
-    Py_TPFLAGS_HAVE_GETCHARBUFFER,
+    Py_TPFLAGS_HAVE_GETCHARBUFFER, Py_buffer,
     build_type_checkers)
 from pypy.module.cpyext.pyobject import (
     PyObject, make_ref, create_ref, from_ref, get_typedescr, make_typedescr,
     pto.c_tp_as_buffer = c_buf
     pto.c_tp_flags |= Py_TPFLAGS_HAVE_GETCHARBUFFER
 
+
+@cpython_api([PyObject, lltype.Ptr(Py_buffer), lltype.Signed], lltype.Signed,
+             external=False, error=-1)
+def memoryview_getbuffer(space, w_view, buf, flags):
+    # buf.c_obj = lltype.nullptr(PyObject.TO)
+    buf.c_buf = rffi.cast(rffi.VOIDP, rffi.str2charp(w_view.as_str()))
+    buf.c_len = w_view.getlength()
+    print 'set length to', buf.c_len
+    print 'set buf to', buf.c_buf
+    return 0
+
+def setup_memoryview_buffer_procs(space, pto):
+    c_buf = lltype.malloc(PyBufferProcs, flavor='raw', zero=True)
+    c_buf.c_bf_getbuffer = llhelper(
+        memoryview_getbuffer.api_func.functype,
+        memoryview_getbuffer.api_func.get_wrapper(space))
+    pto.c_tp_as_buffer = c_buf
+    pto.c_tp_flags |= Py_TPFLAGS_HAVE_GETCHARBUFFER
+
+
 @cpython_api([PyObject], lltype.Void, external=False)
 def type_dealloc(space, obj):
     from pypy.module.cpyext.object import PyObject_dealloc
     # buffer protocol
     if space.is_w(w_type, space.w_str):
         setup_string_buffer_procs(space, pto)
+    elif space.is_w(
+        w_type, space.getattr(space.builtin, space.wrap("memoryview"))):
+        setup_memoryview_buffer_procs(space, pto)
 
     pto.c_tp_flags |= Py_TPFLAGS_HEAPTYPE
     pto.c_tp_free = llhelper(PyObject_Del.api_func.functype,

pypy/module/cpyext/typeobjectdefs.py

 from pypy.rpython.lltypesystem import rffi, lltype
 from pypy.rpython.lltypesystem.lltype import Ptr, FuncType, Void
 from pypy.module.cpyext.api import (cpython_struct, Py_ssize_t, Py_ssize_tP,
-    PyVarObjectFields, PyTypeObject, PyTypeObjectPtr, FILEP,
+    PyVarObjectFields, PyTypeObject, PyTypeObjectPtr, FILEP, Py_buffer,
     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
 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
+
+## We don't support new buffer interface for now !!! YEA RIGHT
+getbufferproc = P(FT([PyO, P(Py_buffer), lltype.Signed], lltype.Signed))
 releasebufferproc = rffi.VOIDP
 
 
Tip: Filter by directory path e.g. /media app.js to search for public/media/app.js.
Tip: Use camelCasing e.g. ProjME to search for ProjectModifiedEvent.java.
Tip: Filter by extension type e.g. /repo .js to search for all .js files in the /repo directory.
Tip: Separate your search with spaces e.g. /ssh pom.xml to search for src/ssh/pom.xml.
Tip: Use ↑ and ↓ arrow keys to navigate and return to view the file.
Tip: You can also navigate files with Ctrl+j (next) and Ctrl+k (previous) and view the file with Ctrl+o.
Tip: You can also navigate files with Alt+j (next) and Alt+k (previous) and view the file with Alt+o.