[pypy-commit] pypy cpyext-old-buffers: Make the buffer protocol something anyone can opt into, not just str/buffer.

devin.jeanpierre pypy.commits at gmail.com
Mon May 16 16:58:57 EDT 2016


Author: Devin Jeanpierre <jeanpierreda at gmail.com>
Branch: cpyext-old-buffers
Changeset: r84494:de3b021f7d37
Date: 2016-05-16 13:57 -0700
http://bitbucket.org/pypy/pypy/changeset/de3b021f7d37/

Log:	Make the buffer protocol something anyone can opt into, not just
	str/buffer.

diff --git a/pypy/interpreter/typedef.py b/pypy/interpreter/typedef.py
--- a/pypy/interpreter/typedef.py
+++ b/pypy/interpreter/typedef.py
@@ -12,7 +12,8 @@
 
 
 class TypeDef(object):
-    def __init__(self, __name, __base=None, __total_ordering__=None, **rawdict):
+    def __init__(self, __name, __base=None, __total_ordering__=None,
+                 __buffer=None, **rawdict):
         "NOT_RPYTHON: initialization-time only"
         self.name = __name
         if __base is None:
@@ -22,6 +23,8 @@
         else:
             bases = [__base]
         self.bases = bases
+        assert __buffer in {None, 'read-write', 'read'}, "Unknown value for __buffer"
+        self.buffer = __buffer
         self.heaptype = False
         self.hasdict = '__dict__' in rawdict
         # no __del__: use an RPython _finalize_() method and register_finalizer
diff --git a/pypy/module/cpyext/test/test_abstract.py b/pypy/module/cpyext/test/test_abstract.py
--- a/pypy/module/cpyext/test/test_abstract.py
+++ b/pypy/module/cpyext/test/test_abstract.py
@@ -70,3 +70,12 @@
         assert s == buffer_support.readbuffer_as_string(mm)
         assert s == buffer_support.writebuffer_as_string(mm)
         assert s == buffer_support.charbuffer_as_string(mm)
+
+    def test_nonbuffer(self):
+        # e.g. int
+        buffer_support = self.get_buffer_support()
+
+        assert not buffer_support.check_readbuffer(42)
+        assert raises(TypeError, buffer_support.readbuffer_as_string, 42)
+        assert raises(TypeError, buffer_support.writebuffer_as_string, 42)
+        assert raises(TypeError, buffer_support.charbuffer_as_string, 42)
diff --git a/pypy/module/cpyext/typeobject.py b/pypy/module/cpyext/typeobject.py
--- a/pypy/module/cpyext/typeobject.py
+++ b/pypy/module/cpyext/typeobject.py
@@ -475,13 +475,16 @@
         ref[0] = address
         return len(buf)
 
-
 @cpython_api([PyObject, Py_ssize_t, rffi.CCHARPP], lltype.Signed,
              header=None, error=-1)
 def bf_getcharbuffer(space, w_buf, segment, ref):
     return bf_getreadbuffer(space, w_buf, segment, rffi.cast(rffi.VOIDPP, ref))
 
-def setup_string_buffer_procs(space, pto):
+def setup_buffer_procs(space, w_type, pto):
+    bufspec = w_type.layout.typedef.buffer
+    if bufspec is None:
+        # not a buffer
+        return
     c_buf = lltype.malloc(PyBufferProcs, flavor='raw', zero=True)
     lltype.render_immortal(c_buf)
     c_buf.c_bf_getsegcount = llhelper(bf_segcount.api_func.functype,
@@ -490,20 +493,11 @@
                                  bf_getreadbuffer.api_func.get_wrapper(space))
     c_buf.c_bf_getcharbuffer = llhelper(bf_getcharbuffer.api_func.functype,
                                  bf_getcharbuffer.api_func.get_wrapper(space))
+    if bufspec == 'read-write':
+        pass  # TODO: write buffer here.
     pto.c_tp_as_buffer = c_buf
     pto.c_tp_flags |= Py_TPFLAGS_HAVE_GETCHARBUFFER
 
-def setup_buffer_buffer_procs(space, pto):
-    c_buf = lltype.malloc(PyBufferProcs, flavor='raw', zero=True)
-    lltype.render_immortal(c_buf)
-    c_buf.c_bf_getsegcount = llhelper(bf_segcount.api_func.functype,
-                                      bf_segcount.api_func.get_wrapper(space))
-    c_buf.c_bf_getreadbuffer = llhelper(bf_getreadbuffer.api_func.functype,
-                                 bf_getreadbuffer.api_func.get_wrapper(space))
-    c_buf.c_bf_getcharbuffer = llhelper(bf_getcharbuffer.api_func.functype,
-                                 bf_getcharbuffer.api_func.get_wrapper(space))
-    pto.c_tp_as_buffer = c_buf
-
 @cpython_api([PyObject], lltype.Void, header=None)
 def type_dealloc(space, obj):
     from pypy.module.cpyext.object import PyObject_dealloc
@@ -567,10 +561,7 @@
             subtype_dealloc.api_func.functype,
             subtype_dealloc.api_func.get_wrapper(space))
     # buffer protocol
-    if space.is_w(w_type, space.w_str):
-        setup_string_buffer_procs(space, pto)
-    if space.is_w(w_type, space.w_buffer):
-        setup_buffer_buffer_procs(space, pto)
+    setup_buffer_procs(space, w_type, pto)
 
     pto.c_tp_free = llhelper(PyObject_Free.api_func.functype,
             PyObject_Free.api_func.get_wrapper(space))
diff --git a/pypy/objspace/std/bufferobject.py b/pypy/objspace/std/bufferobject.py
--- a/pypy/objspace/std/bufferobject.py
+++ b/pypy/objspace/std/bufferobject.py
@@ -135,7 +135,7 @@
         return space.wrap(rffi.cast(lltype.Signed, ptr))
 
 W_Buffer.typedef = TypeDef(
-    "buffer",
+    "buffer", None, None, "read-write",
     __doc__ = """\
 buffer(object [, offset[, size]])
 
diff --git a/pypy/objspace/std/bytesobject.py b/pypy/objspace/std/bytesobject.py
--- a/pypy/objspace/std/bytesobject.py
+++ b/pypy/objspace/std/bytesobject.py
@@ -848,7 +848,7 @@
 
 
 W_BytesObject.typedef = TypeDef(
-    "str", basestring_typedef,
+    "str", basestring_typedef, None, "read",
     __new__ = interp2app(W_BytesObject.descr_new),
     __doc__ = """str(object='') -> string
 


More information about the pypy-commit mailing list