[pypy-commit] pypy cpyext-ext: start to implement ByteArrayObject without exposing CAPI ByteArrayObject.ob_* attributes

mattip pypy.commits at gmail.com
Wed Jun 1 15:21:23 EDT 2016


Author: Matti Picus <matti.picus at gmail.com>
Branch: cpyext-ext
Changeset: r84867:0c496ba45fe1
Date: 2016-06-01 22:10 +0300
http://bitbucket.org/pypy/pypy/changeset/0c496ba45fe1/

Log:	start to implement ByteArrayObject without exposing CAPI
	ByteArrayObject.ob_* attributes

diff --git a/pypy/module/cpyext/bytearrayobject.py b/pypy/module/cpyext/bytearrayobject.py
--- a/pypy/module/cpyext/bytearrayobject.py
+++ b/pypy/module/cpyext/bytearrayobject.py
@@ -1,5 +1,6 @@
 from pypy.interpreter.error import OperationError, oefmt
 from rpython.rtyper.lltypesystem import rffi, lltype
+from pypy.objspace.std.bytearrayobject import new_bytearray
 from pypy.module.cpyext.api import (
     cpython_api, cpython_struct, bootstrap_function, build_type_checkers,
     PyVarObjectFields, Py_ssize_t, CONST_STRING, CANNOT_FAIL)
@@ -25,18 +26,18 @@
 
 PyByteArrayObjectStruct = lltype.ForwardReference()
 PyByteArrayObject = lltype.Ptr(PyByteArrayObjectStruct)
-PyByteArrayObjectFields = PyVarObjectFields + \
-    (("ob_exports", rffi.INT), ("ob_alloc", rffi.LONG), ("ob_bytes", rffi.CCHARP))
+PyByteArrayObjectFields = PyVarObjectFields 
+#    (("ob_exports", rffi.INT), ("ob_alloc", rffi.LONG), ("ob_bytes", rffi.CCHARP))
 cpython_struct("PyByteArrayObject", PyByteArrayObjectFields, PyByteArrayObjectStruct)
 
 @bootstrap_function
 def init_bytearrayobject(space):
     "Type description of PyByteArrayObject"
-    make_typedescr(space.w_str.layout.typedef,
-                   basestruct=PyByteArrayObject.TO,
-                   attach=bytearray_attach,
-                   dealloc=bytearray_dealloc,
-                   realize=bytearray_realize)
+    #make_typedescr(space.w_bytearray.layout.typedef,
+    #               basestruct=PyByteArrayObject.TO,
+    #               attach=bytearray_attach,
+    #               dealloc=bytearray_dealloc,
+    #               realize=bytearray_realize)
 
 PyByteArray_Check, PyByteArray_CheckExact = build_type_checkers("ByteArray", "w_bytearray")
 
@@ -83,11 +84,16 @@
     XXX expand about the buffer protocol, at least somewhere"""
     raise NotImplementedError
 
- at cpython_api([rffi.CCHARP, Py_ssize_t], PyObject)
-def PyByteArray_FromStringAndSize(space, string, len):
+ at cpython_api([rffi.CCHARP, Py_ssize_t], PyObject, result_is_ll=True)
+def PyByteArray_FromStringAndSize(space, char_p, length):
     """Create a new bytearray object from string and its length, len.  On
     failure, NULL is returned."""
-    raise NotImplementedError
+    if char_p:
+        s = rffi.charpsize2str(char_p, length)
+    else:
+        s = length
+    w_buffer = space.call_function(space.w_bytearray, space.wrap(s))
+    return make_ref(space, w_buffer)
 
 @cpython_api([PyObject, PyObject], PyObject)
 def PyByteArray_Concat(space, a, b):
@@ -95,12 +101,14 @@
     raise NotImplementedError
 
 @cpython_api([PyObject], Py_ssize_t, error=-1)
-def PyByteArray_Size(space, bytearray):
+def PyByteArray_Size(space, w_obj):
     """Return the size of bytearray after checking for a NULL pointer."""
-    raise NotImplementedError
+    if not w_obj:
+        return 0
+    return space.len_w(w_obj)
 
- at cpython_api([PyObject], rffi.CCHARP)
-def PyByteArray_AsString(space, bytearray):
+ at cpython_api([PyObject], rffi.CCHARP, error=0)
+def PyByteArray_AsString(space, w_obj):
     """Return the contents of bytearray as a char array after checking for a
     NULL pointer."""
     raise NotImplementedError
diff --git a/pypy/module/cpyext/include/bytearrayobject.h b/pypy/module/cpyext/include/bytearrayobject.h
--- a/pypy/module/cpyext/include/bytearrayobject.h
+++ b/pypy/module/cpyext/include/bytearrayobject.h
@@ -14,17 +14,17 @@
  * Bytes are not characters; they may be used to encode characters.
  * The only way to go between bytes and str/unicode is via encoding
  * and decoding.
- * For the convenience of C programmers, the bytes type is considered
- * to contain a char pointer, not an unsigned char pointer.
+ * While CPython exposes interfaces to this object, pypy does not
  */
 
 /* Object layout */
 typedef struct {
     PyObject_VAR_HEAD
-    /* XXX(nnorwitz): should ob_exports be Py_ssize_t? */
+#if 0
     int ob_exports; /* how many buffer exports */
     Py_ssize_t ob_alloc; /* How many bytes allocated */
     char *ob_bytes;
+#endif
 } PyByteArrayObject;
 
 #ifdef __cplusplus
diff --git a/pypy/module/cpyext/test/test_bytearrayobject.py b/pypy/module/cpyext/test/test_bytearrayobject.py
--- a/pypy/module/cpyext/test/test_bytearrayobject.py
+++ b/pypy/module/cpyext/test/test_bytearrayobject.py
@@ -22,7 +22,7 @@
                      result = 1;
                  }
                  #ifdef PYPY_VERSION
-                    expected_size = sizeof(void*)*7;
+                    expected_size = sizeof(void*)*3;
                  #elif defined Py_DEBUG
                     expected_size = 64;
                  #else
@@ -62,6 +62,8 @@
                     return NULL;
                  Py_DECREF(t);
                  c = PyByteArray_AsString(s);
+                 if (c == NULL)
+                    return NULL;
                  c[0] = 'a';
                  c[1] = 'b';
                  c[2] = 0;
@@ -78,7 +80,7 @@
             ("mutable", "METH_NOARGS",
              """
                 PyObject *base;
-                PyByteArrayObject *obj;
+                PyObject *obj;
                 char * p_str;
                 base = PyByteArray_FromStringAndSize("test", 10);
                 if (PyByteArray_GET_SIZE(base) != 10)
@@ -118,6 +120,22 @@
                        PyTuple_GetItem(args, 0)), 4);
              '''
             ),
+            ("str_from_bytearray", "METH_VARARGS",
+             '''
+                char * buf;
+                int n;
+                PyObject * obj;
+                obj = PyTuple_GetItem(args, 0);
+                buf = PyByteArray_AsString(obj);
+                if (buf == NULL)
+                {
+                    PyErr_SetString(PyExc_ValueError, "non-null bytearray object expected");
+                    return NULL;
+                }
+                n = PyByteArray_Size(obj);
+                return PyString_FromStringAndSize(buf, n);
+             '''
+            ),
             ("concat", "METH_VARARGS",
              """
                 PyObject * ret, *right, *left;
@@ -136,6 +154,8 @@
                 return ret;
              """)])
         assert module.bytearray_from_string("huheduwe") == "huhe"
+        assert module.str_from_bytearray(bytearray('abc')) == 'abc'
+        raises(ValueError, module.str_from_bytearray, 4.0)
         ret = module.concat('abc', 'def')
         assert ret == 'abcdef'
         assert not isinstance(ret, str)


More information about the pypy-commit mailing list