Author: Ronan Lamy <ronan.l...@gmail.com>
Branch: PyBuffer
Changeset: r90827:3d947926d247
Date: 2017-03-28 00:45 +0100
http://bitbucket.org/pypy/pypy/changeset/3d947926d247/

Log:    Tyr to use composition instead of inheritance to model the
        relationship between Py_buffers and C-style buffers.

diff --git a/pypy/interpreter/baseobjspace.py b/pypy/interpreter/baseobjspace.py
--- a/pypy/interpreter/baseobjspace.py
+++ b/pypy/interpreter/baseobjspace.py
@@ -10,7 +10,7 @@
 from rpython.rlib.rarithmetic import r_uint, SHRT_MIN, SHRT_MAX, \
     INT_MIN, INT_MAX, UINT_MAX, USHRT_MAX
 
-from pypy.interpreter.buffer import StringBuffer
+from pypy.interpreter.buffer import SimpleBuffer, StringBuffer
 from pypy.interpreter.executioncontext import (ExecutionContext, ActionFlag,
     make_finalizer_queue)
 from pypy.interpreter.error import OperationError, new_exception_class, oefmt
@@ -1519,10 +1519,11 @@
             # most API in CPython 3.x no longer do.
             if self.isinstance_w(w_obj, self.w_bytes):
                 return StringBuffer(w_obj.bytes_w(self))
-            if self.isinstance_w(w_obj, self.w_unicode):  # NB. CPython forbids
-                return StringBuffer(w_obj.text_w(self))   # surrogates here
+            if self.isinstance_w(w_obj, self.w_unicode):
+                # NB. CPython forbids surrogates here
+                return StringBuffer(w_obj.text_w(self))
             try:
-                return w_obj.buffer_w(self, self.BUF_SIMPLE)
+                return w_obj.buffer_w(self, self.BUF_SIMPLE).as_binary()
             except BufferInterfaceNotFound:
                 self._getarg_error("bytes or buffer", w_obj)
         elif code == 's#':
diff --git a/pypy/interpreter/buffer.py b/pypy/interpreter/buffer.py
--- a/pypy/interpreter/buffer.py
+++ b/pypy/interpreter/buffer.py
@@ -57,6 +57,10 @@
     def get_raw_address(self):
         raise ValueError("no raw buffer")
 
+    def as_binary(self):
+        # Inefficient. May be overridden.
+        return StringBuffer(self.as_str())
+
     def getformat(self):
         raise NotImplementedError
 
@@ -75,15 +79,34 @@
     def releasebuffer(self):
         pass
 
-class BinaryBuffer(Buffer):
-    """Base class for buffers of bytes"""
-    _attrs_ = ['readonly']
+class SimpleBuffer(Buffer):
+    _attrs_ = ['readonly', 'data']
     _immutable_ = True
 
+    def __init__(self, data):
+        self.data = data
+        self.readonly = self.data.readonly
+
+    def getlength(self):
+        return self.data.getlength()
+
     def as_str(self):
-        "Returns an interp-level string with the whole content of the buffer."
-        # May be overridden.
-        return self.getslice(0, self.getlength(), 1, self.getlength())
+        return self.data.as_str()
+
+    def as_str_and_offset_maybe(self):
+        return self.data.as_str_and_offset_maybe()
+
+    def getitem(self, index):
+        return self.data.getitem(index)
+
+    def setitem(self, index, value):
+        return self.data.setitem(index, value)
+
+    def get_raw_address(self):
+        return self.data.get_raw_address()
+
+    def as_binary(self):
+        return self.data
 
     def getformat(self):
         return 'B'
@@ -100,6 +123,41 @@
     def getstrides(self):
         return [1]
 
+class BinaryBuffer(Buffer):
+    """Base class for buffers of bytes"""
+    _attrs_ = ['readonly']
+    _immutable_ = True
+
+    def as_str(self):
+        "Returns an interp-level string with the whole content of the buffer."
+        # May be overridden.
+        return self.getslice(0, self.getlength(), 1, self.getlength())
+
+    def getslice(self, start, stop, step, size):
+        # May be overridden.  No bounds checks.
+        return ''.join([self.getitem(i) for i in range(start, stop, step)])
+
+
+    def setslice(self, start, string):
+        # May be overridden.  No bounds checks.
+        for i in range(len(string)):
+            self.setitem(start + i, string[i])
+
+
+    def getformat(self):
+        return 'B'
+
+    def getitemsize(self):
+        return 1
+
+    def getndim(self):
+        return 1
+
+    def getshape(self):
+        return [self.getlength()]
+
+    def getstrides(self):
+        return [1]
 
 
 class ByteBuffer(BinaryBuffer):
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
@@ -2,9 +2,9 @@
 # A convenient read-write buffer.  Located here for want of a better place.
 #
 
-from pypy.interpreter.buffer import ByteBuffer
+from pypy.interpreter.buffer import SimpleBuffer, ByteBuffer
 from pypy.interpreter.gateway import unwrap_spec
 
 @unwrap_spec(length=int)
 def bytebuffer(space, length):
-    return space.newbuffer(ByteBuffer(length))
+    return space.newbuffer(SimpleBuffer(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
@@ -5,7 +5,7 @@
 from pypy.module._cffi_backend import cdataobj, ctypeptr, ctypearray
 from pypy.module._cffi_backend import ctypestruct
 
-from pypy.interpreter.buffer import BinaryBuffer
+from pypy.interpreter.buffer import SimpleBuffer, BinaryBuffer
 from rpython.rtyper.annlowlevel import llstr
 from rpython.rtyper.lltypesystem import rffi
 from rpython.rtyper.lltypesystem.rstr import copy_string_to_raw
@@ -47,7 +47,7 @@
         self.keepalive = keepalive
 
     def buffer_w(self, space, flags):
-        return self.buffer
+        return SimpleBuffer(self.buffer)
 
     def descr_len(self, space):
         return space.newint(self.buffer.getlength())
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
@@ -4,7 +4,7 @@
 from pypy.interpreter.typedef import (
     TypeDef, GetSetProperty, generic_new_descr, interp_attrproperty_w)
 from pypy.interpreter.gateway import interp2app, unwrap_spec, WrappedDefault
-from pypy.interpreter.buffer import BinaryBuffer, SubBuffer
+from pypy.interpreter.buffer import SimpleBuffer, BinaryBuffer, SubBuffer
 from rpython.rlib.rgc import (
     nonmoving_raw_ptr_for_resizable_list, resizable_list_supporting_raw_ptr)
 from rpython.rlib.rstring import StringBuilder
@@ -579,7 +579,7 @@
     def _raw_read(self, space, buffer, start, length):
         length = intmask(length)
         start = intmask(start)
-        w_buf = space.newbuffer(SubBuffer(buffer, start, length))
+        w_buf = space.newbuffer(SimpleBuffer(SubBuffer(buffer, start, length)))
         while True:
             try:
                 w_size = space.call_method(self.w_raw, "readinto", w_buf)
diff --git a/pypy/module/_io/interp_bytesio.py 
b/pypy/module/_io/interp_bytesio.py
--- a/pypy/module/_io/interp_bytesio.py
+++ b/pypy/module/_io/interp_bytesio.py
@@ -2,7 +2,7 @@
 from pypy.interpreter.typedef import (
     TypeDef, generic_new_descr, GetSetProperty)
 from pypy.interpreter.gateway import interp2app, unwrap_spec
-from pypy.interpreter.buffer import BinaryBuffer
+from pypy.interpreter.buffer import SimpleBuffer, BinaryBuffer
 from rpython.rlib.rStringIO import RStringIO
 from rpython.rlib.rarithmetic import r_longlong
 from rpython.rlib.objectmodel import import_from_mixin
@@ -125,7 +125,7 @@
 
     def getbuffer_w(self, space):
         self._check_closed(space)
-        return W_MemoryView(BytesIOBuffer(self))
+        return W_MemoryView(SimpleBuffer(BytesIOBuffer(self)))
 
     def getvalue_w(self, space):
         self._check_closed(space)
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
@@ -1,5 +1,6 @@
 import sys
 from pypy.interpreter.baseobjspace import W_Root
+from pypy.interpreter.buffer import SimpleBuffer
 from pypy.interpreter.error import OperationError, oefmt, wrap_oserror
 from pypy.interpreter.gateway import interp2app, unwrap_spec
 from pypy.interpreter.typedef import interp_attrproperty
@@ -380,7 +381,7 @@
         self._ll_buffer = self.ll_buffer
 
     def buffer_w(self, space, flags):
-        return RawFFIBuffer(self)
+        return SimpleBuffer(RawFFIBuffer(self))
 
     def getrawsize(self):
         raise NotImplementedError("abstract base class")
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
@@ -858,6 +858,9 @@
     def getlength(self):
         return self.array.len * self.array.itemsize
 
+    def as_str(self):
+        return self.getslice(0, self.getlength(), 1, self.getlength())
+
     def getformat(self):
         return self.array.typecode
 
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
@@ -17,7 +17,7 @@
     getbytevalue, makebytesdata_w, newbytesdata_w)
 from pypy.interpreter.gateway import WrappedDefault, interp2app, unwrap_spec
 from pypy.interpreter.typedef import TypeDef
-from pypy.interpreter.buffer import BinaryBuffer
+from pypy.interpreter.buffer import SimpleBuffer, BinaryBuffer
 from pypy.objspace.std.sliceobject import W_SliceObject, unwrap_start_stop
 from pypy.objspace.std.stringmethods import StringMethods, _get_buffer
 from pypy.objspace.std.stringmethods import _descr_getslice_slowpath
@@ -52,7 +52,7 @@
                            ''.join(self._data[self._offset:]))
 
     def buffer_w(self, space, flags):
-        return BytearrayBuffer(self)
+        return SimpleBuffer(BytearrayBuffer(self))
 
     def bytearray_list_of_chars_w(self, space):
         return self.getdata()
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
@@ -7,7 +7,7 @@
 from rpython.rlib.rstring import StringBuilder
 
 from pypy.interpreter.baseobjspace import W_Root
-from pypy.interpreter.buffer import StringBuffer
+from pypy.interpreter.buffer import SimpleBuffer, StringBuffer
 from pypy.interpreter.error import OperationError, oefmt
 from pypy.interpreter.gateway import (
     WrappedDefault, interp2app, interpindirect2app, unwrap_spec)
@@ -419,7 +419,7 @@
 
     def buffer_w(self, space, flags):
         space.check_buf_flags(flags, True)
-        return StringBuffer(self._value)
+        return SimpleBuffer(StringBuffer(self._value))
 
     def readbuf_w(self, space):
         return StringBuffer(self._value)
diff --git a/pypy/objspace/std/memoryobject.py 
b/pypy/objspace/std/memoryobject.py
--- a/pypy/objspace/std/memoryobject.py
+++ b/pypy/objspace/std/memoryobject.py
@@ -682,11 +682,7 @@
     def descr_hex(self, space):
         from pypy.objspace.std.bytearrayobject import _array_to_hexstring
         self._check_released(space)
-        if memory_view_c_contiguous(space, self.flags):
-            return _array_to_hexstring(space, self.buf, 0, 1, self.getlength())
-        else:
-            bytes = self.as_str()
-            return _array_to_hexstring(space, StringBuffer(bytes), 0, 1, 
len(bytes))
+        return _array_to_hexstring(space, self.buf.as_binary(), 0, 1, 
self.getlength())
 
 def is_byte_format(char):
     return char == 'b' or char == 'B' or char == 'c'
_______________________________________________
pypy-commit mailing list
pypy-commit@python.org
https://mail.python.org/mailman/listinfo/pypy-commit

Reply via email to