Author: Manuel Jacob
Branch: 
Changeset: r70053:5cff90211004
Date: 2014-03-18 16:41 +0100
http://bitbucket.org/pypy/pypy/changeset/5cff90211004/

Log:    hg merge refactor-buffer-api

        Separate the interp-level buffer API from the buffer type exposed to
        app-level. The `Buffer` class is now used by `W_MemoryView` and
        `W_Buffer`, which is not present in Python 3. Previously `W_Buffer`
        was an alias to `Buffer`, which was wrappable itself.

diff --git a/pypy/interpreter/baseobjspace.py b/pypy/interpreter/baseobjspace.py
--- a/pypy/interpreter/baseobjspace.py
+++ b/pypy/interpreter/baseobjspace.py
@@ -194,6 +194,15 @@
     def immutable_unique_id(self, space):
         return None
 
+    def buffer_w(self, space):
+        w_impl = space.lookup(self, '__buffer__')
+        if w_impl is not None:
+            w_result = space.get_and_call_function(w_impl, self)
+            from pypy.module.__builtin__.interp_memoryview import W_Buffer
+            if isinstance(w_result, W_Buffer):
+                return w_result.buf
+        self._typed_unwrap_error(space, "buffer")
+
     def str_w(self, space):
         self._typed_unwrap_error(space, "string")
 
@@ -1314,10 +1323,7 @@
                                            'to unsigned int'))
 
     def buffer_w(self, w_obj):
-        # returns a Buffer instance
-        from pypy.interpreter.buffer import Buffer
-        w_buffer = self.buffer(w_obj)
-        return self.interp_w(Buffer, w_buffer)
+        return w_obj.buffer_w(self)
 
     def rwbuffer_w(self, w_obj):
         # returns a RWBuffer instance
@@ -1677,7 +1683,6 @@
     ('set',             'set',       3, ['__set__']),
     ('delete',          'delete',    2, ['__delete__']),
     ('userdel',         'del',       1, ['__del__']),
-    ('buffer',          'buffer',    1, ['__buffer__']),   # see buffer.py
 ]
 
 ObjSpace.BuiltinModuleTable = [
diff --git a/pypy/interpreter/buffer.py b/pypy/interpreter/buffer.py
--- a/pypy/interpreter/buffer.py
+++ b/pypy/interpreter/buffer.py
@@ -1,30 +1,12 @@
 """
 Buffer protocol support.
 """
+from pypy.interpreter.error import OperationError
+from rpython.rlib.objectmodel import import_from_mixin
 
-# The implementation of the buffer protocol.  The basic idea is that we
-# can ask any app-level object for a 'buffer' view on it, by calling its
-# __buffer__() special method.  It should return a wrapped instance of a
-# subclass of the Buffer class defined below.  Note that __buffer__() is
-# a PyPy-only extension to the Python language, made necessary by the
-# fact that it's not natural in PyPy to hack an interp-level-only
-# interface.
 
-# In normal usage, the convenience method space.buffer_w() should be
-# used to get directly a Buffer instance.  Doing so also gives you for
-# free the typecheck that __buffer__() really returned a wrapped Buffer.
-
-import operator
-from pypy.interpreter.baseobjspace import W_Root
-from pypy.interpreter.typedef import TypeDef
-from pypy.interpreter.gateway import interp2app, unwrap_spec
-from pypy.interpreter.error import OperationError
-from rpython.rlib.objectmodel import compute_hash, import_from_mixin
-from rpython.rlib.rstring import StringBuilder
-
-
-class Buffer(W_Root):
-    """Abstract base class for memory views."""
+class Buffer(object):
+    """Abstract base class for buffers."""
 
     __slots__ = ()     # no extra slot here
 
@@ -47,94 +29,12 @@
     def get_raw_address(self):
         raise ValueError("no raw buffer")
 
+
     def is_writable(self):
         return False
 
-    # __________ app-level support __________
-
-    def descr_len(self, space):
-        return space.wrap(self.getlength())
-
-    def descr_getitem(self, space, w_index):
-        start, stop, step, size = space.decode_index4(w_index, 
self.getlength())
-        if step == 0:  # index only
-            return space.wrap(self.getitem(start))
-        res = self.getslice(start, stop, step, size)
-        return space.wrap(res)
-
-    @unwrap_spec(newstring='bufferstr')
-    def descr_setitem(self, space, w_index, newstring):
-        if not isinstance(self, RWBuffer):
-            raise OperationError(space.w_TypeError,
-                                 space.wrap("buffer is read-only"))
-        start, stop, step, size = space.decode_index4(w_index, 
self.getlength())
-        if step == 0:  # index only
-            if len(newstring) != 1:
-                msg = 'buffer[index]=x: x must be a single character'
-                raise OperationError(space.w_TypeError, space.wrap(msg))
-            char = newstring[0]   # annotator hint
-            self.setitem(start, char)
-        elif step == 1:
-            if len(newstring) != size:
-                msg = "right operand length must match slice length"
-                raise OperationError(space.w_ValueError, space.wrap(msg))
-            self.setslice(start, newstring)
-        else:
-            raise OperationError(space.w_ValueError,
-                                 space.wrap("buffer object does not support"
-                                            " slicing with a step"))
-
-    def descr__buffer__(self, space):
-        return space.wrap(self)
-
-    def descr_str(self, space):
-        return space.wrap(self.as_str())
-
-    @unwrap_spec(other='bufferstr')
-    def descr_add(self, space, other):
-        return space.wrap(self.as_str() + other)
-
-    def _make_descr__cmp(name):
-        def descr__cmp(self, space, w_other):
-            if not isinstance(w_other, Buffer):
-                return space.w_NotImplemented
-            # xxx not the most efficient implementation
-            str1 = self.as_str()
-            str2 = w_other.as_str()
-            return space.wrap(getattr(operator, name)(str1, str2))
-        descr__cmp.func_name = name
-        return descr__cmp
-
-    descr_eq = _make_descr__cmp('eq')
-    descr_ne = _make_descr__cmp('ne')
-    descr_lt = _make_descr__cmp('lt')
-    descr_le = _make_descr__cmp('le')
-    descr_gt = _make_descr__cmp('gt')
-    descr_ge = _make_descr__cmp('ge')
-
-    def descr_hash(self, space):
-        return space.wrap(compute_hash(self.as_str()))
-
-    def descr_mul(self, space, w_times):
-        # xxx not the most efficient implementation
-        w_string = space.wrap(self.as_str())
-        # use the __mul__ method instead of space.mul() so that we
-        # return NotImplemented instead of raising a TypeError
-        return space.call_method(w_string, '__mul__', w_times)
-
-    def descr_repr(self, space):
-        if isinstance(self, RWBuffer):
-            info = 'read-write buffer'
-        else:
-            info = 'read-only buffer'
-        addrstring = self.getaddrstring(space)
-
-        return space.wrap("<%s for 0x%s, size %d>" %
-                          (info, addrstring, self.getlength()))
-
-
 class RWBuffer(Buffer):
-    """Abstract base class for read-write memory views."""
+    """Abstract base class for read-write buffers."""
 
     __slots__ = ()     # no extra slot here
 
@@ -151,72 +51,6 @@
             self.setitem(start + i, string[i])
 
 
-@unwrap_spec(offset=int, size=int)
-def descr_buffer__new__(space, w_subtype, w_object, offset=0, size=-1):
-    # w_subtype can only be exactly 'buffer' for now
-    if not space.is_w(w_subtype, space.gettypefor(Buffer)):
-        raise OperationError(space.w_TypeError,
-                             space.wrap("argument 1 must be 'buffer'"))
-
-    if space.isinstance_w(w_object, space.w_unicode):
-        # unicode objects support the old buffer interface
-        # but not the new buffer interface (change in python  2.7)
-        from rpython.rlib.rstruct.unichar import pack_unichar, UNICODE_SIZE
-        unistr = space.unicode_w(w_object)
-        builder = StringBuilder(len(unistr) * UNICODE_SIZE)
-        for unich in unistr:
-            pack_unichar(unich, builder)
-        from pypy.interpreter.buffer import StringBuffer
-        w_buffer = space.wrap(StringBuffer(builder.build()))
-    else:
-        w_buffer = space.buffer(w_object)
-
-    buffer = space.interp_w(Buffer, w_buffer)    # type-check
-    if offset == 0 and size == -1:
-        return w_buffer
-    # handle buffer slices
-    if offset < 0:
-        raise OperationError(space.w_ValueError,
-                             space.wrap("offset must be zero or positive"))
-    if size < -1:
-        raise OperationError(space.w_ValueError,
-                             space.wrap("size must be zero or positive"))
-    if isinstance(buffer, RWBuffer):
-        buffer = RWSubBuffer(buffer, offset, size)
-    else:
-        buffer = SubBuffer(buffer, offset, size)
-    return space.wrap(buffer)
-
-
-Buffer.typedef = TypeDef(
-    "buffer",
-    __doc__ = """\
-buffer(object [, offset[, size]])
-
-Create a new buffer object which references the given object.
-The buffer will reference a slice of the target object from the
-start of the object (or at the specified offset). The slice will
-extend to the end of the target object (or with the specified size).
-""",
-    __new__ = interp2app(descr_buffer__new__),
-    __len__ = interp2app(Buffer.descr_len),
-    __getitem__ = interp2app(Buffer.descr_getitem),
-    __setitem__ = interp2app(Buffer.descr_setitem),
-    __buffer__ = interp2app(Buffer.descr__buffer__),
-    __str__ = interp2app(Buffer.descr_str),
-    __add__ = interp2app(Buffer.descr_add),
-    __eq__ = interp2app(Buffer.descr_eq),
-    __ne__ = interp2app(Buffer.descr_ne),
-    __lt__ = interp2app(Buffer.descr_lt),
-    __le__ = interp2app(Buffer.descr_le),
-    __gt__ = interp2app(Buffer.descr_gt),
-    __ge__ = interp2app(Buffer.descr_ge),
-    __hash__ = interp2app(Buffer.descr_hash),
-    __mul__ = interp2app(Buffer.descr_mul),
-    __rmul__ = interp2app(Buffer.descr_mul),
-    __repr__ = interp2app(Buffer.descr_repr),
-)
-Buffer.typedef.acceptable_as_base_class = False
 
 # ____________________________________________________________
 
diff --git a/pypy/interpreter/test/test_buffer.py 
b/pypy/interpreter/test/test_buffer.py
--- a/pypy/interpreter/test/test_buffer.py
+++ b/pypy/interpreter/test/test_buffer.py
@@ -1,5 +1,5 @@
 import py
-from pypy.interpreter.buffer import Buffer
+from pypy.module.__builtin__.interp_memoryview import W_Buffer
 from rpython.tool.udir import udir
 
 testdir = udir.ensure('test_buffer', dir=1)
@@ -11,19 +11,17 @@
         space = self.space
         w_hello = space.wrap('hello world')
         buf = space.buffer_w(w_hello)
-        assert isinstance(buf, Buffer)
         assert buf.getlength() == 11
         assert buf.as_str() == 'hello world'
         assert buf.getslice(1, 6, 1, 5) == 'ello '
-        assert space.buffer_w(space.wrap(buf)) is buf
+        assert space.buffer_w(W_Buffer(buf)) is buf
         assert space.bufferstr_w(w_hello) == 'hello world'
-        assert space.bufferstr_w(space.buffer(w_hello)) == 'hello world'
+        assert space.bufferstr_w(W_Buffer(space.buffer_w(w_hello))) == 'hello 
world'
         space.raises_w(space.w_TypeError, space.buffer_w, space.wrap(5))
-        space.raises_w(space.w_TypeError, space.buffer, space.wrap(5))
 
     def test_file_write(self):
         space = self.space
-        w_buffer = space.buffer(space.wrap('hello world'))
+        w_buffer = W_Buffer(space.buffer_w(space.wrap('hello world')))
         filename = str(testdir.join('test_file_write'))
         space.appexec([w_buffer, space.wrap(filename)], """(buffer, filename):
             f = open(filename, 'wb')
diff --git a/pypy/module/__builtin__/interp_memoryview.py 
b/pypy/module/__builtin__/interp_memoryview.py
--- a/pypy/module/__builtin__/interp_memoryview.py
+++ b/pypy/module/__builtin__/interp_memoryview.py
@@ -1,14 +1,168 @@
 """
 Implementation of the 'buffer' and 'memoryview' types.
 """
+import operator
+
+from pypy.interpreter import buffer
 from pypy.interpreter.baseobjspace import W_Root
-from pypy.interpreter import buffer
+from pypy.interpreter.error import OperationError
 from pypy.interpreter.gateway import interp2app, unwrap_spec
 from pypy.interpreter.typedef import TypeDef, GetSetProperty
-from pypy.interpreter.error import OperationError
-import operator
+from rpython.rlib.objectmodel import compute_hash
+from rpython.rlib.rstring import StringBuilder
 
-W_Buffer = buffer.Buffer      # actually implemented in pypy.interpreter.buffer
+
+def _buffer_setitem(space, buf, w_index, newstring):
+    start, stop, step, size = space.decode_index4(w_index, buf.getlength())
+    if step == 0:  # index only
+        if len(newstring) != 1:
+            msg = 'buffer[index]=x: x must be a single character'
+            raise OperationError(space.w_TypeError, space.wrap(msg))
+        char = newstring[0]   # annotator hint
+        buf.setitem(start, char)
+    elif step == 1:
+        if len(newstring) != size:
+            msg = "right operand length must match slice length"
+            raise OperationError(space.w_ValueError, space.wrap(msg))
+        buf.setslice(start, newstring)
+    else:
+        raise OperationError(space.w_ValueError,
+                             space.wrap("buffer object does not support"
+                                        " slicing with a step"))
+
+
+class W_Buffer(W_Root):
+    """Implement the built-in 'buffer' type as a thin wrapper around
+    an interp-level buffer.
+    """
+
+    def __init__(self, buf):
+        self.buf = buf
+
+    def buffer_w(self, space):
+        return self.buf
+
+    @staticmethod
+    @unwrap_spec(offset=int, size=int)
+    def descr_new_buffer(space, w_subtype, w_object, offset=0, size=-1):
+        if space.isinstance_w(w_object, space.w_unicode):
+            # unicode objects support the old buffer interface
+            # but not the new buffer interface (change in python 2.7)
+            from rpython.rlib.rstruct.unichar import pack_unichar, UNICODE_SIZE
+            unistr = space.unicode_w(w_object)
+            builder = StringBuilder(len(unistr) * UNICODE_SIZE)
+            for unich in unistr:
+                pack_unichar(unich, builder)
+            from pypy.interpreter.buffer import StringBuffer
+            buf = StringBuffer(builder.build())
+        else:
+            buf = space.buffer_w(w_object)
+
+        if offset == 0 and size == -1:
+            return W_Buffer(buf)
+        # handle buffer slices
+        if offset < 0:
+            raise OperationError(space.w_ValueError,
+                                 space.wrap("offset must be zero or positive"))
+        if size < -1:
+            raise OperationError(space.w_ValueError,
+                                 space.wrap("size must be zero or positive"))
+        if isinstance(buf, buffer.RWBuffer):
+            buf = buffer.RWSubBuffer(buf, offset, size)
+        else:
+            buf = buffer.SubBuffer(buf, offset, size)
+        return W_Buffer(buf)
+
+    def descr_len(self, space):
+        return space.wrap(self.buf.getlength())
+
+    def descr_getitem(self, space, w_index):
+        start, stop, step, size = space.decode_index4(w_index, 
self.buf.getlength())
+        if step == 0:  # index only
+            return space.wrap(self.buf.getitem(start))
+        res = self.buf.getslice(start, stop, step, size)
+        return space.wrap(res)
+
+    @unwrap_spec(newstring='bufferstr')
+    def descr_setitem(self, space, w_index, newstring):
+        if not isinstance(self.buf, buffer.RWBuffer):
+            raise OperationError(space.w_TypeError,
+                                 space.wrap("buffer is read-only"))
+        _buffer_setitem(space, self.buf, w_index, newstring)
+
+    def descr_str(self, space):
+        return space.wrap(self.buf.as_str())
+
+    @unwrap_spec(other='bufferstr')
+    def descr_add(self, space, other):
+        return space.wrap(self.buf.as_str() + other)
+
+    def _make_descr__cmp(name):
+        def descr__cmp(self, space, w_other):
+            if not isinstance(w_other, W_Buffer):
+                return space.w_NotImplemented
+            # xxx not the most efficient implementation
+            str1 = self.buf.as_str()
+            str2 = w_other.buf.as_str()
+            return space.wrap(getattr(operator, name)(str1, str2))
+        descr__cmp.func_name = name
+        return descr__cmp
+
+    descr_eq = _make_descr__cmp('eq')
+    descr_ne = _make_descr__cmp('ne')
+    descr_lt = _make_descr__cmp('lt')
+    descr_le = _make_descr__cmp('le')
+    descr_gt = _make_descr__cmp('gt')
+    descr_ge = _make_descr__cmp('ge')
+
+    def descr_hash(self, space):
+        return space.wrap(compute_hash(self.buf.as_str()))
+
+    def descr_mul(self, space, w_times):
+        # xxx not the most efficient implementation
+        w_string = space.wrap(self.buf.as_str())
+        # use the __mul__ method instead of space.mul() so that we
+        # return NotImplemented instead of raising a TypeError
+        return space.call_method(w_string, '__mul__', w_times)
+
+    def descr_repr(self, space):
+        if isinstance(self.buf, buffer.RWBuffer):
+            info = 'read-write buffer'
+        else:
+            info = 'read-only buffer'
+        addrstring = self.getaddrstring(space)
+
+        return space.wrap("<%s for 0x%s, size %d>" %
+                          (info, addrstring, self.buf.getlength()))
+
+W_Buffer.typedef = TypeDef(
+    "buffer",
+    __doc__ = """\
+buffer(object [, offset[, size]])
+
+Create a new buffer object which references the given object.
+The buffer will reference a slice of the target object from the
+start of the object (or at the specified offset). The slice will
+extend to the end of the target object (or with the specified size).
+""",
+    __new__ = interp2app(W_Buffer.descr_new_buffer),
+    __len__ = interp2app(W_Buffer.descr_len),
+    __getitem__ = interp2app(W_Buffer.descr_getitem),
+    __setitem__ = interp2app(W_Buffer.descr_setitem),
+    __str__ = interp2app(W_Buffer.descr_str),
+    __add__ = interp2app(W_Buffer.descr_add),
+    __eq__ = interp2app(W_Buffer.descr_eq),
+    __ne__ = interp2app(W_Buffer.descr_ne),
+    __lt__ = interp2app(W_Buffer.descr_lt),
+    __le__ = interp2app(W_Buffer.descr_le),
+    __gt__ = interp2app(W_Buffer.descr_gt),
+    __ge__ = interp2app(W_Buffer.descr_ge),
+    __hash__ = interp2app(W_Buffer.descr_hash),
+    __mul__ = interp2app(W_Buffer.descr_mul),
+    __rmul__ = interp2app(W_Buffer.descr_mul),
+    __repr__ = interp2app(W_Buffer.descr_repr),
+)
+W_Buffer.typedef.acceptable_as_base_class = False
 
 
 class W_MemoryView(W_Root):
@@ -17,9 +171,16 @@
     """
 
     def __init__(self, buf):
-        assert isinstance(buf, buffer.Buffer)
         self.buf = buf
 
+    def buffer_w(self, space):
+        return self.buf
+
+    @staticmethod
+    def descr_new_memoryview(space, w_subtype, w_object):
+        w_memoryview = W_MemoryView(space.buffer_w(w_object))
+        return w_memoryview
+
     def _make_descr__cmp(name):
         def descr__cmp(self, space, w_other):
             if isinstance(w_other, W_MemoryView):
@@ -29,14 +190,14 @@
                 return space.wrap(getattr(operator, name)(str1, str2))
 
             try:
-                w_buf = space.buffer(w_other)
+                buf = space.buffer_w(w_other)
             except OperationError, e:
                 if not e.match(space, space.w_TypeError):
                     raise
                 return space.w_NotImplemented
             else:
                 str1 = self.as_str()
-                str2 = space.buffer_w(w_buf).as_str()
+                str2 = buf.as_str()
                 return space.wrap(getattr(operator, name)(str1, str2))
         descr__cmp.func_name = name
         return descr__cmp
@@ -102,15 +263,13 @@
 
     @unwrap_spec(newstring='bufferstr')
     def descr_setitem(self, space, w_index, newstring):
-        buf = self.buf
-        if isinstance(buf, buffer.RWBuffer):
-            buf.descr_setitem(space, w_index, newstring)
-        else:
+        if not isinstance(self.buf, buffer.RWBuffer):
             raise OperationError(space.w_TypeError,
                                  space.wrap("cannot modify read-only memory"))
+        _buffer_setitem(space, self.buf, w_index, newstring)
 
     def descr_len(self, space):
-        return self.buf.descr_len(space)
+        return space.wrap(self.buf.getlength())
 
     def w_get_format(self, space):
         return space.wrap("B")
@@ -134,18 +293,12 @@
         # I've never seen anyone filling this field
         return space.w_None
 
-
-def descr_new(space, w_subtype, w_object):
-    memoryview = W_MemoryView(space.buffer(w_object))
-    return space.wrap(memoryview)
-
 W_MemoryView.typedef = TypeDef(
     "memoryview",
     __doc__ = """\
 Create a new memoryview object which references the given object.
 """,
-    __new__ = interp2app(descr_new),
-    __buffer__  = interp2app(W_MemoryView.descr_buffer),
+    __new__ = interp2app(W_MemoryView.descr_new_memoryview),
     __eq__      = interp2app(W_MemoryView.descr_eq),
     __ge__      = interp2app(W_MemoryView.descr_ge),
     __getitem__ = interp2app(W_MemoryView.descr_getitem),
diff --git a/pypy/module/__pypy__/bytebuffer.py 
b/pypy/module/__pypy__/bytebuffer.py
--- a/pypy/module/__pypy__/bytebuffer.py
+++ b/pypy/module/__pypy__/bytebuffer.py
@@ -4,6 +4,7 @@
 
 from pypy.interpreter.buffer import RWBuffer
 from pypy.interpreter.gateway import unwrap_spec
+from pypy.module.__builtin__.interp_memoryview import W_Buffer
 
 
 class ByteBuffer(RWBuffer):
@@ -23,4 +24,4 @@
 
 @unwrap_spec(length=int)
 def bytebuffer(space, length):
-    return space.wrap(ByteBuffer(length))
+    return W_Buffer(ByteBuffer(length))
diff --git a/pypy/module/_cffi_backend/cbuffer.py 
b/pypy/module/_cffi_backend/cbuffer.py
--- a/pypy/module/_cffi_backend/cbuffer.py
+++ b/pypy/module/_cffi_backend/cbuffer.py
@@ -4,6 +4,7 @@
 from pypy.interpreter.gateway import unwrap_spec, interp2app
 from pypy.interpreter.typedef import TypeDef, make_weakref_descr
 from pypy.module._cffi_backend import cdataobj, ctypeptr, ctypearray
+from pypy.module.__builtin__.interp_memoryview import W_Buffer
 
 from rpython.rtyper.annlowlevel import llstr
 from rpython.rtyper.lltypesystem import rffi
@@ -39,38 +40,19 @@
         copy_string_to_raw(llstr(string), raw_cdata, 0, len(string))
 
 
-class MiniBuffer(W_Root):
-    # a different subclass of W_Root for the MiniBuffer, because we
-    # want a slightly different (simplified) API at the level of Python.
+# Override the typedef to narrow down the interface that's exposed to app-level
 
+class MiniBuffer(W_Buffer):
     def __init__(self, buffer, keepalive=None):
-        self.buffer = buffer
+        W_Buffer.__init__(self, buffer)
         self.keepalive = keepalive
 
-    def descr_len(self, space):
-        return self.buffer.descr_len(space)
-
-    def descr_getitem(self, space, w_index):
-        return self.buffer.descr_getitem(space, w_index)
-
-    @unwrap_spec(newstring='bufferstr')
-    def descr_setitem(self, space, w_index, newstring):
-        self.buffer.descr_setitem(space, w_index, newstring)
-
-    def descr__buffer__(self, space):
-        return self.buffer.descr__buffer__(space)
-
-    def descr_str(self, space):
-        return space.wrap(self.buffer.as_str())
-
-
 MiniBuffer.typedef = TypeDef(
     "buffer",
     __module__ = "_cffi_backend",
     __len__ = interp2app(MiniBuffer.descr_len),
     __getitem__ = interp2app(MiniBuffer.descr_getitem),
     __setitem__ = interp2app(MiniBuffer.descr_setitem),
-    __buffer__ = interp2app(MiniBuffer.descr__buffer__),
     __weakref__ = make_weakref_descr(MiniBuffer),
     __str__ = interp2app(MiniBuffer.descr_str),
     )
diff --git a/pypy/module/_io/interp_bufferedio.py 
b/pypy/module/_io/interp_bufferedio.py
--- a/pypy/module/_io/interp_bufferedio.py
+++ b/pypy/module/_io/interp_bufferedio.py
@@ -5,6 +5,7 @@
     TypeDef, GetSetProperty, generic_new_descr, interp_attrproperty_w)
 from pypy.interpreter.gateway import interp2app, unwrap_spec, WrappedDefault
 from pypy.interpreter.buffer import RWBuffer
+from pypy.module.__builtin__.interp_memoryview import W_Buffer
 from rpython.rlib.rstring import StringBuilder
 from rpython.rlib.rarithmetic import r_longlong, intmask
 from rpython.rlib import rposix
@@ -511,7 +512,7 @@
 
     def _raw_read(self, space, buffer, start, length):
         length = intmask(length)
-        w_buf = space.wrap(RawBuffer(buffer, start, length))
+        w_buf = W_Buffer(RawBuffer(buffer, start, length))
         while True:
             try:
                 w_size = space.call_method(self.w_raw, "readinto", w_buf)
diff --git a/pypy/module/_rawffi/array.py b/pypy/module/_rawffi/array.py
--- a/pypy/module/_rawffi/array.py
+++ b/pypy/module/_rawffi/array.py
@@ -207,7 +207,6 @@
     __setitem__ = interp2app(W_ArrayInstance.descr_setitem),
     __getitem__ = interp2app(W_ArrayInstance.descr_getitem),
     __len__     = interp2app(W_ArrayInstance.getlength),
-    __buffer__  = interp2app(W_ArrayInstance.descr_buffer),
     buffer      = GetSetProperty(W_ArrayInstance.getbuffer),
     shape       = interp_attrproperty('shape', W_ArrayInstance),
     free        = interp2app(W_ArrayInstance.free),
@@ -232,7 +231,6 @@
     __setitem__ = interp2app(W_ArrayInstance.descr_setitem),
     __getitem__ = interp2app(W_ArrayInstance.descr_getitem),
     __len__     = interp2app(W_ArrayInstance.getlength),
-    __buffer__  = interp2app(W_ArrayInstance.descr_buffer),
     buffer      = GetSetProperty(W_ArrayInstance.getbuffer),
     shape       = interp_attrproperty('shape', W_ArrayInstance),
     byptr       = interp2app(W_ArrayInstance.byptr),
diff --git a/pypy/module/_rawffi/interp_rawffi.py 
b/pypy/module/_rawffi/interp_rawffi.py
--- a/pypy/module/_rawffi/interp_rawffi.py
+++ b/pypy/module/_rawffi/interp_rawffi.py
@@ -352,9 +352,9 @@
         lltype.free(self.ll_buffer, flavor='raw')
         self.ll_buffer = lltype.nullptr(rffi.VOIDP.TO)
 
-    def descr_buffer(self, space):
+    def buffer_w(self, space):
         from pypy.module._rawffi.buffer import RawFFIBuffer
-        return space.wrap(RawFFIBuffer(self))
+        return RawFFIBuffer(self)
 
     def getrawsize(self):
         raise NotImplementedError("abstract base class")
diff --git a/pypy/module/_rawffi/structure.py b/pypy/module/_rawffi/structure.py
--- a/pypy/module/_rawffi/structure.py
+++ b/pypy/module/_rawffi/structure.py
@@ -364,7 +364,6 @@
     __repr__    = interp2app(W_StructureInstance.descr_repr),
     __getattr__ = interp2app(W_StructureInstance.getattr),
     __setattr__ = interp2app(W_StructureInstance.setattr),
-    __buffer__  = interp2app(W_StructureInstance.descr_buffer),
     buffer      = GetSetProperty(W_StructureInstance.getbuffer),
     free        = interp2app(W_StructureInstance.free),
     shape       = interp_attrproperty('shape', W_StructureInstance),
@@ -387,7 +386,6 @@
     __repr__    = interp2app(W_StructureInstance.descr_repr),
     __getattr__ = interp2app(W_StructureInstance.getattr),
     __setattr__ = interp2app(W_StructureInstance.setattr),
-    __buffer__  = interp2app(W_StructureInstance.descr_buffer),
     buffer      = GetSetProperty(W_StructureInstance.getbuffer),
     shape       = interp_attrproperty('shape', W_StructureInstance),
     byptr       = interp2app(W_StructureInstance.byptr),
diff --git a/pypy/module/array/interp_array.py 
b/pypy/module/array/interp_array.py
--- a/pypy/module/array/interp_array.py
+++ b/pypy/module/array/interp_array.py
@@ -132,6 +132,9 @@
         self.len = 0
         self.allocated = 0
 
+    def buffer_w(self, space):
+        return ArrayBuffer(self)
+
     def descr_append(self, space, w_x):
         """ append(x)
 
@@ -462,9 +465,6 @@
 
     # Misc methods
 
-    def descr_buffer(self, space):
-        return space.wrap(ArrayBuffer(self))
-
     def descr_repr(self, space):
         if self.len == 0:
             return space.wrap("array('%s')" % self.typecode)
@@ -508,7 +508,6 @@
     __radd__ = interp2app(W_ArrayBase.descr_radd),
     __rmul__ = interp2app(W_ArrayBase.descr_rmul),
 
-    __buffer__ = interp2app(W_ArrayBase.descr_buffer),
     __repr__ = interp2app(W_ArrayBase.descr_repr),
 
     itemsize = GetSetProperty(descr_itemsize),
diff --git a/pypy/module/cpyext/bufferobject.py 
b/pypy/module/cpyext/bufferobject.py
--- a/pypy/module/cpyext/bufferobject.py
+++ b/pypy/module/cpyext/bufferobject.py
@@ -3,8 +3,9 @@
     cpython_api, Py_ssize_t, cpython_struct, bootstrap_function,
     PyObjectFields, PyObject)
 from pypy.module.cpyext.pyobject import make_typedescr, Py_DecRef, make_ref
-from pypy.interpreter.buffer import Buffer, StringBuffer, SubBuffer
+from pypy.interpreter.buffer import StringBuffer, SubBuffer
 from pypy.interpreter.error import OperationError
+from pypy.module.__builtin__.interp_memoryview import W_Buffer
 from pypy.module.array.interp_array import ArrayBuffer
 
 
@@ -24,7 +25,7 @@
 @bootstrap_function
 def init_bufferobject(space):
     "Type description of PyBufferObject"
-    make_typedescr(space.gettypefor(Buffer).instancetypedef,
+    make_typedescr(space.gettypefor(W_Buffer).instancetypedef,
                    basestruct=PyBufferObject.TO,
                    attach=buffer_attach,
                    dealloc=buffer_dealloc,
@@ -39,23 +40,26 @@
     rffi.setintfield(py_buf, 'c_b_readonly', 1)
     rffi.setintfield(py_buf, 'c_b_hash', -1)
 
-    if isinstance(w_obj, SubBuffer):
-        py_buf.c_b_offset = w_obj.offset
-        w_obj = w_obj.buffer
+    assert isinstance(w_obj, W_Buffer)
+    buf = w_obj.buf
 
-    # If w_obj already allocated a fixed buffer, use it, and keep a
-    # reference to w_obj.
+    if isinstance(buf, SubBuffer):
+        py_buf.c_b_offset = buf.offset
+        buf = buf.buffer
+
+    # If buf already allocated a fixed buffer, use it, and keep a
+    # reference to buf.
     # Otherwise, b_base stays NULL, and we own the b_ptr.
 
-    if isinstance(w_obj, StringBuffer):
+    if isinstance(buf, StringBuffer):
         py_buf.c_b_base = lltype.nullptr(PyObject.TO)
-        py_buf.c_b_ptr = rffi.cast(rffi.VOIDP, rffi.str2charp(w_obj.value))
-        py_buf.c_b_size = w_obj.getlength()
-    elif isinstance(w_obj, ArrayBuffer):
-        w_base = w_obj.array
+        py_buf.c_b_ptr = rffi.cast(rffi.VOIDP, rffi.str2charp(buf.value))
+        py_buf.c_b_size = buf.getlength()
+    elif isinstance(buf, ArrayBuffer):
+        w_base = buf.array
         py_buf.c_b_base = make_ref(space, w_base)
-        py_buf.c_b_ptr = rffi.cast(rffi.VOIDP, w_obj.array._charbuf_start())
-        py_buf.c_b_size = w_obj.getlength()
+        py_buf.c_b_ptr = rffi.cast(rffi.VOIDP, buf.array._charbuf_start())
+        py_buf.c_b_size = buf.getlength()
     else:
         raise OperationError(space.w_NotImplementedError, space.wrap(
             "buffer flavor not supported"))
diff --git a/pypy/module/cpyext/slotdefs.py b/pypy/module/cpyext/slotdefs.py
--- a/pypy/module/cpyext/slotdefs.py
+++ b/pypy/module/cpyext/slotdefs.py
@@ -14,8 +14,9 @@
 from pypy.module.cpyext.pyobject import from_ref
 from pypy.module.cpyext.pyerrors import PyErr_Occurred
 from pypy.module.cpyext.state import State
+from pypy.module.__builtin__.interp_memoryview import W_Buffer
 from pypy.interpreter.error import OperationError, oefmt
-from pypy.interpreter.buffer import Buffer as W_Buffer
+from pypy.interpreter.buffer import Buffer
 from pypy.interpreter.argument import Arguments
 from rpython.rlib.unroll import unrolling_iterable
 from rpython.rlib.objectmodel import specialize
@@ -228,7 +229,7 @@
     check_num_args(space, w_args, 0)
     return space.wrap(generic_cpy_call(space, func_target, w_self))
 
-class CPyBuffer(W_Buffer):
+class CPyBuffer(Buffer):
     # Similar to Py_buffer
 
     def __init__(self, ptr, size, w_obj):
@@ -249,7 +250,7 @@
         size = generic_cpy_call(space, func_target, w_self, index, ptr)
         if size < 0:
             space.fromcache(State).check_and_raise_exception(always=True)
-        return space.wrap(CPyBuffer(ptr[0], size, w_self))
+        return W_Buffer(CPyBuffer(ptr[0], size, w_self))
 
 def get_richcmp_func(OP_CONST):
     def inner(space, w_self, w_args, func):
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
@@ -28,7 +28,7 @@
     PyNumberMethods, PyMappingMethods, PySequenceMethods, PyBufferProcs)
 from pypy.module.cpyext.slotdefs import (
     slotdefs_for_tp_slots, slotdefs_for_wrappers, get_slot_tp_function)
-from pypy.interpreter.buffer import Buffer
+from pypy.module.__builtin__.interp_memoryview import W_Buffer
 from pypy.interpreter.error import OperationError
 from rpython.rlib.rstring import rsplit
 from rpython.rlib.objectmodel import specialize
@@ -509,7 +509,7 @@
     # buffer protocol
     if space.is_w(w_type, space.w_str):
         setup_string_buffer_procs(space, pto)
-    if space.is_w(w_type, space.gettypefor(Buffer)):
+    if space.is_w(w_type, space.gettypefor(W_Buffer)):
         setup_buffer_buffer_procs(space, pto)
 
     pto.c_tp_free = llhelper(PyObject_Del.api_func.functype,
diff --git a/pypy/module/micronumpy/boxes.py b/pypy/module/micronumpy/boxes.py
--- a/pypy/module/micronumpy/boxes.py
+++ b/pypy/module/micronumpy/boxes.py
@@ -342,8 +342,8 @@
     def descr_copy(self, space):
         return self.convert_to(space, self.get_dtype(space))
 
-    def descr_buffer(self, space):
-        return self.descr_ravel(space).descr_get_data(space)
+    def buffer_w(self, space):
+        return self.descr_ravel(space).buffer_w(space)
 
     def descr_byteswap(self, space):
         return self.get_dtype(space).itemtype.byteswap(self)
@@ -553,7 +553,6 @@
     __nonzero__ = interp2app(W_GenericBox.descr_nonzero),
     __oct__ = interp2app(W_GenericBox.descr_oct),
     __hex__ = interp2app(W_GenericBox.descr_hex),
-    __buffer__ = interp2app(W_GenericBox.descr_buffer),
 
     __add__ = interp2app(W_GenericBox.descr_add),
     __sub__ = interp2app(W_GenericBox.descr_sub),
diff --git a/pypy/module/micronumpy/ndarray.py 
b/pypy/module/micronumpy/ndarray.py
--- a/pypy/module/micronumpy/ndarray.py
+++ b/pypy/module/micronumpy/ndarray.py
@@ -7,6 +7,7 @@
 from rpython.rlib.rawstorage import RAW_STORAGE_PTR
 from rpython.rtyper.lltypesystem import rffi
 from rpython.tool.sourcetools import func_with_new_name
+from pypy.module.__builtin__.interp_memoryview import W_Buffer
 from pypy.module.micronumpy import descriptor, ufuncs, boxes, arrayops, loop, \
     support, constants as NPY
 from pypy.module.micronumpy.appbridge import get_appbridge_cache
@@ -602,8 +603,11 @@
         raise OperationError(space.w_NotImplementedError, space.wrap(
             "ctypes not implemented yet"))
 
+    def buffer_w(self, space):
+        return self.implementation.get_buffer(space)
+
     def descr_get_data(self, space):
-        return self.implementation.get_buffer(space)
+        return W_Buffer(self.buffer_w(space))
 
     @unwrap_spec(offset=int, axis1=int, axis2=int)
     def descr_diagonal(self, space, offset=0, axis1=0, axis2=1):
@@ -1259,7 +1263,6 @@
     __float__ = interp2app(W_NDimArray.descr_float),
     __hex__ = interp2app(W_NDimArray.descr_hex),
     __oct__ = interp2app(W_NDimArray.descr_oct),
-    __buffer__ = interp2app(W_NDimArray.descr_get_data),
     __index__ = interp2app(W_NDimArray.descr_index),
 
     __pos__ = interp2app(W_NDimArray.descr_pos),
diff --git a/pypy/module/mmap/interp_mmap.py b/pypy/module/mmap/interp_mmap.py
--- a/pypy/module/mmap/interp_mmap.py
+++ b/pypy/module/mmap/interp_mmap.py
@@ -17,6 +17,10 @@
         self.space = space
         self.mmap = mmap_obj
 
+    def buffer_w(self, space):
+        self.check_valid()
+        return MMapBuffer(self.space, self.mmap)
+
     def close(self):
         self.mmap.close()
 
@@ -196,10 +200,6 @@
                     self.mmap.setitem(start, value[i])
                     start += step
 
-    def descr_buffer(self):
-        self.check_valid()
-        return self.space.wrap(MMapBuffer(self.space, self.mmap))
-
 if rmmap._POSIX:
 
     @unwrap_spec(fileno=int, length=int, flags=int,
@@ -256,7 +256,6 @@
     __len__ = interp2app(W_MMap.__len__),
     __getitem__ = interp2app(W_MMap.descr_getitem),
     __setitem__ = interp2app(W_MMap.descr_setitem),
-    __buffer__ = interp2app(W_MMap.descr_buffer),
 )
 
 constants = rmmap.constants
diff --git a/pypy/module/pyexpat/interp_pyexpat.py 
b/pypy/module/pyexpat/interp_pyexpat.py
--- a/pypy/module/pyexpat/interp_pyexpat.py
+++ b/pypy/module/pyexpat/interp_pyexpat.py
@@ -429,7 +429,7 @@
 
         self.handlers = [None] * NB_HANDLERS
 
-        self.buffer_w = None
+        self.buffer_w_ = None
         self.buffer_size = 8192
         self.buffer_used = 0
         self.w_character_data_handler = None
@@ -541,7 +541,7 @@
 
     def buffer_string(self, space, w_string, length):
         ll_length = rffi.cast(lltype.Signed, length)
-        if self.buffer_w is not None:
+        if self.buffer_w_ is not None:
             if self.buffer_used + ll_length > self.buffer_size:
                 self.flush_character_buffer(space)
                 # handler might have changed; drop the rest on the floor
@@ -549,11 +549,11 @@
                 if self.w_character_data_handler is None:
                     return True
             if ll_length <= self.buffer_size:
-                self.buffer_w.append(w_string)
+                self.buffer_w_.append(w_string)
                 self.buffer_used += ll_length
                 return True
             else:
-                self.buffer_w = []
+                self.buffer_w_ = []
                 self.buffer_used = 0
         return False
 
@@ -685,12 +685,12 @@
         return space.wrap(parser)
 
     def flush_character_buffer(self, space):
-        if not self.buffer_w:
+        if not self.buffer_w_:
             return
         w_data = space.call_function(
             space.getattr(space.wrap(''), space.wrap('join')),
-            space.newlist(self.buffer_w))
-        self.buffer_w = []
+            space.newlist(self.buffer_w_))
+        self.buffer_w_ = []
         self.buffer_used = 0
 
         if self.w_character_data_handler:
@@ -735,14 +735,14 @@
         self.buffer_size = value
 
     def get_buffer_text(self, space):
-        return space.wrap(self.buffer_w is not None)
+        return space.wrap(self.buffer_w_ is not None)
     def set_buffer_text(self, space, w_value):
         if space.is_true(w_value):
-            self.buffer_w = []
+            self.buffer_w_ = []
             self.buffer_used = 0
         else:
             self.flush_character_buffer(space)
-            self.buffer_w = None
+            self.buffer_w_ = None
 
     def get_intern(self, space):
         if self.w_intern:
diff --git a/pypy/objspace/fake/objspace.py b/pypy/objspace/fake/objspace.py
--- a/pypy/objspace/fake/objspace.py
+++ b/pypy/objspace/fake/objspace.py
@@ -292,6 +292,11 @@
         ec._py_repr = None
         return ec
 
+    def buffer_w(self, w_obj):
+        from pypy.interpreter.buffer import Buffer
+        is_root(w_obj)
+        return Buffer()
+
     def unicode_from_object(self, w_obj):
         return w_some_obj()
 
diff --git a/pypy/objspace/std/bytearrayobject.py 
b/pypy/objspace/std/bytearrayobject.py
--- a/pypy/objspace/std/bytearrayobject.py
+++ b/pypy/objspace/std/bytearrayobject.py
@@ -27,6 +27,9 @@
         """representation for debugging purposes"""
         return "%s(%s)" % (w_self.__class__.__name__, ''.join(w_self.data))
 
+    def buffer_w(w_self, space):
+        return BytearrayBuffer(w_self.data)
+
     def _new(self, value):
         return W_BytearrayObject(_make_data(value))
 
@@ -295,9 +298,6 @@
     def descr_iter(self, space):
         return space.newseqiter(self)
 
-    def descr_buffer(self, space):
-        return BytearrayBuffer(self.data)
-
     def descr_inplace_add(self, space, w_other):
         if isinstance(w_other, W_BytearrayObject):
             self.data += w_other.data
@@ -1011,7 +1011,6 @@
 
     __init__ = interp2app(W_BytearrayObject.descr_init,
                           doc=BytearrayDocstrings.__init__.__doc__),
-    __buffer__ = interp2app(W_BytearrayObject.descr_buffer),
 
     __iadd__ = interp2app(W_BytearrayObject.descr_inplace_add,
                           doc=BytearrayDocstrings.__iadd__.__doc__),
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
@@ -424,9 +424,6 @@
         of the specified width. The string S is never truncated.
         """
 
-    def descr_buffer(self, space):
-        pass
-
 
 class W_BytesObject(W_AbstractBytesObject):
     import_from_mixin(StringMethods)
@@ -445,6 +442,9 @@
     def str_w(self, space):
         return self._value
 
+    def buffer_w(w_self, space):
+        return StringBuffer(w_self._value)
+
     def listview_bytes(self):
         return _create_list_from_bytes(self._value)
 
@@ -567,9 +567,6 @@
     def descr_mod(self, space, w_values):
         return mod_format(space, self, w_values, do_unicode=False)
 
-    def descr_buffer(self, space):
-        return space.wrap(StringBuffer(self._value))
-
     def descr_eq(self, space, w_other):
         if space.config.objspace.std.withstrbuf:
             from pypy.objspace.std.strbufobject import W_StringBufferObject
@@ -853,7 +850,6 @@
     format = interpindirect2app(W_BytesObject.descr_format),
     __format__ = interpindirect2app(W_BytesObject.descr__format__),
     __mod__ = interpindirect2app(W_BytesObject.descr_mod),
-    __buffer__ = interpindirect2app(W_AbstractBytesObject.descr_buffer),
     __getnewargs__ = interpindirect2app(
         W_AbstractBytesObject.descr_getnewargs),
     _formatter_parser = interp2app(W_BytesObject.descr_formatter_parser),
diff --git a/pypy/objspace/std/intobject.py b/pypy/objspace/std/intobject.py
--- a/pypy/objspace/std/intobject.py
+++ b/pypy/objspace/std/intobject.py
@@ -696,7 +696,7 @@
         else:
             # If object supports the buffer interface
             try:
-                w_buffer = space.buffer(w_value)
+                buf = space.buffer_w(w_value)
             except OperationError as e:
                 if not e.match(space, space.w_TypeError):
                     raise
@@ -704,7 +704,6 @@
                             "int() argument must be a string or a number, "
                             "not '%T'", w_value)
             else:
-                buf = space.interp_w(Buffer, w_buffer)
                 value, w_longval = _string_to_int_or_long(space, w_value,
                                                           buf.as_str())
                 ok = True
diff --git a/pypy/objspace/std/longobject.py b/pypy/objspace/std/longobject.py
--- a/pypy/objspace/std/longobject.py
+++ b/pypy/objspace/std/longobject.py
@@ -513,7 +513,7 @@
                                      unicode_to_decimal_w(space, w_value))
         else:
             try:
-                w_buffer = space.buffer(w_value)
+                buf = space.buffer_w(w_value)
             except OperationError, e:
                 if not e.match(space, space.w_TypeError):
                     raise
@@ -521,7 +521,6 @@
                             "long() argument must be a string or a number, "
                             "not '%T'", w_value)
             else:
-                buf = space.interp_w(Buffer, w_buffer)
                 return _string_to_w_long(space, w_longtype, w_value,
                                          buf.as_str())
     else:
diff --git a/pypy/objspace/std/strbufobject.py 
b/pypy/objspace/std/strbufobject.py
--- a/pypy/objspace/std/strbufobject.py
+++ b/pypy/objspace/std/strbufobject.py
@@ -2,12 +2,12 @@
 
 import py
 
-from pypy.objspace.std.basestringtype import basestring_typedef
-from pypy.objspace.std.bytesobject import W_AbstractBytesObject, W_BytesObject
-from pypy.objspace.std.stdtypedef import StdTypeDef
+from pypy.objspace.std.bytesobject import (W_AbstractBytesObject,
+    W_BytesObject, StringBuffer)
 from pypy.interpreter.gateway import interp2app, unwrap_spec
 from rpython.rlib.rstring import StringBuilder
 
+
 class W_StringBufferObject(W_AbstractBytesObject):
     w_str = None
 
@@ -36,6 +36,9 @@
     def str_w(self, space):
         return self.force()
 
+    def buffer_w(self, space):
+        return StringBuffer(self.force())
+
     def descr_len(self, space):
         return space.wrap(self.length)
 
_______________________________________________
pypy-commit mailing list
pypy-commit@python.org
https://mail.python.org/mailman/listinfo/pypy-commit

Reply via email to