Author: Ronan Lamy <[email protected]>
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
[email protected]
https://mail.python.org/mailman/listinfo/pypy-commit