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