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