[pypy-commit] pypy py3k: merge default (8a2e9e0c1676)
pjenvey
noreply at buildbot.pypy.org
Wed Apr 30 01:11:57 CEST 2014
Author: Philip Jenvey <pjenvey at underboss.org>
Branch: py3k
Changeset: r71070:67528c976db5
Date: 2014-04-28 18:04 -0700
http://bitbucket.org/pypy/pypy/changeset/67528c976db5/
Log: merge default (8a2e9e0c1676)
diff too long, truncating to 2000 out of 3538 lines
diff --git a/lib-python/2.7/test/test_array.py b/lib-python/2.7/test/test_array.py
--- a/lib-python/2.7/test/test_array.py
+++ b/lib-python/2.7/test/test_array.py
@@ -298,6 +298,7 @@
b = array.array(self.badtypecode())
with self.assertRaises(TypeError):
a + b
+
with self.assertRaises(TypeError):
a + 'bad'
@@ -320,6 +321,7 @@
b = array.array(self.badtypecode())
with self.assertRaises(TypeError):
a += b
+
with self.assertRaises(TypeError):
a += 'bad'
diff --git a/lib-python/2.7/test/test_file2k.py b/lib-python/2.7/test/test_file2k.py
--- a/lib-python/2.7/test/test_file2k.py
+++ b/lib-python/2.7/test/test_file2k.py
@@ -479,11 +479,10 @@
def _create_file(self):
if self.use_buffering:
- f = open(self.filename, "w+", buffering=1024*16)
+ self.f = open(self.filename, "w+", buffering=1024*16)
else:
- f = open(self.filename, "w+")
- self.f = f
- self.all_files.append(f)
+ self.f = open(self.filename, "w+")
+ self.all_files.append(self.f)
oldf = self.all_files.pop(0)
if oldf is not None:
oldf.close()
diff --git a/lib-python/2.7/test/test_memoryview.py b/lib-python/2.7/test/test_memoryview.py
--- a/lib-python/2.7/test/test_memoryview.py
+++ b/lib-python/2.7/test/test_memoryview.py
@@ -115,8 +115,8 @@
self.assertRaises(TypeError, setitem, (0,), b"a")
self.assertRaises(TypeError, setitem, "a", b"a")
# Trying to resize the memory object
- self.assertRaises((ValueError, TypeError), setitem, 0, b"")
- self.assertRaises((ValueError, TypeError), setitem, 0, b"ab")
+ self.assertRaises(ValueError, setitem, 0, b"")
+ self.assertRaises(ValueError, setitem, 0, b"ab")
self.assertRaises(ValueError, setitem, slice(1,1), b"a")
self.assertRaises(ValueError, setitem, slice(0,2), b"a")
@@ -166,18 +166,11 @@
self.assertTrue(m[0:6] == m[:])
self.assertFalse(m[0:5] == m)
- if test_support.check_impl_detail(cpython=True):
- # what is supported and what is not supported by memoryview is
- # very inconsisten on CPython. In PyPy, memoryview supports
- # the buffer interface, and thus the following comparison
- # succeeds. See also the comment in
- # pypy.objspace.std.memoryview.W_MemoryView.descr_buffer
- #
- # Comparison with objects which don't support the buffer API
- self.assertFalse(m == u"abcdef", "%s %s" % (self, tp))
- self.assertTrue(m != u"abcdef")
- self.assertFalse(u"abcdef" == m)
- self.assertTrue(u"abcdef" != m)
+ # Comparison with objects which don't support the buffer API
+ self.assertFalse(m == u"abcdef")
+ self.assertTrue(m != u"abcdef")
+ self.assertFalse(u"abcdef" == m)
+ self.assertTrue(u"abcdef" != m)
# Unordered comparisons are unimplemented, and therefore give
# arbitrary results (they raise a TypeError in py3k)
diff --git a/pypy/doc/whatsnew-head.rst b/pypy/doc/whatsnew-head.rst
--- a/pypy/doc/whatsnew-head.rst
+++ b/pypy/doc/whatsnew-head.rst
@@ -9,3 +9,6 @@
Improve optimiziation of small allocation-heavy loops in the JIT
.. branch: reflex-support
+
+.. branch: refactor-buffer-api
+Properly implement old/new buffer API for objects and start work on replacing bufferstr usage
diff --git a/pypy/interpreter/baseobjspace.py b/pypy/interpreter/baseobjspace.py
--- a/pypy/interpreter/baseobjspace.py
+++ b/pypy/interpreter/baseobjspace.py
@@ -5,7 +5,7 @@
from rpython.rlib import jit, types
from rpython.rlib.debug import make_sure_not_resized
from rpython.rlib.objectmodel import (we_are_translated, newlist_hint,
- compute_unique_id)
+ compute_unique_id, specialize)
from rpython.rlib.signature import signature
from rpython.rlib.rarithmetic import r_uint, SHRT_MIN, SHRT_MAX, \
INT_MIN, INT_MAX, UINT_MAX
@@ -193,14 +193,37 @@
def immutable_unique_id(self, space):
return None
- def buffer_w(self, space):
+ def buffer_w(self, space, flags):
w_impl = space.lookup(self, '__buffer__')
if w_impl is not None:
w_result = space.get_and_call_function(w_impl, self)
if space.isinstance_w(w_result, space.w_memoryview):
- return w_result.buffer_w(space)
- raise oefmt(space.w_TypeError,
- "'%T' does not support the buffer interface", self)
+ return w_result.buffer_w(space, flags)
+ raise TypeError
+
+ def readbuf_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)
+ if space.isinstance_w(w_result, space.w_memoryview):
+ return w_result.readbuf_w(space)
+ raise TypeError
+
+ def writebuf_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)
+ if space.isinstance_w(w_result, space.w_memoryview):
+ return w_result.writebuf_w(space)
+ raise TypeError
+
+ def charbuf_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)
+ if space.isinstance_w(w_result, space.w_memoryview):
+ return w_result.charbuf_w(space)
+ raise TypeError
def bytes_w(self, space):
self._typed_unwrap_error(space, "bytes")
@@ -1332,24 +1355,109 @@
self.wrap('cannot convert negative integer '
'to unsigned int'))
- def buffer_w(self, w_obj):
- return w_obj.buffer_w(self)
+ BUF_SIMPLE = 0x0000
+ BUF_WRITABLE = 0x0001
+ BUF_FORMAT = 0x0004
+ BUF_ND = 0x0008
+ BUF_STRIDES = 0x0010 | BUF_ND
+ BUF_INDIRECT = 0x0100 | BUF_STRIDES
- def rwbuffer_w(self, w_obj):
- # returns a RWBuffer instance
- from pypy.interpreter.buffer import RWBuffer
- buffer = self.buffer_w(w_obj)
- if not isinstance(buffer, RWBuffer):
- raise OperationError(self.w_TypeError,
- self.wrap('read-write buffer expected'))
- return buffer
+ BUF_CONTIG_RO = BUF_ND
+ BUF_CONTIG = BUF_ND | BUF_WRITABLE
- def bufferstr_new_w(self, w_obj):
- # Implement the "new buffer interface" (new in Python 2.7)
- # returning an unwrapped string. It doesn't accept unicode
- # strings
- buffer = self.buffer_w(w_obj)
- return buffer.as_str()
+ BUF_FULL_RO = BUF_INDIRECT | BUF_FORMAT
+ BUF_FULL = BUF_INDIRECT | BUF_FORMAT | BUF_WRITABLE
+
+ def check_buf_flags(self, flags, readonly):
+ if readonly and flags & self.BUF_WRITABLE == self.BUF_WRITABLE:
+ raise oefmt(self.w_BufferError, "Object is not writable.")
+
+ def buffer_w(self, w_obj, flags):
+ # New buffer interface, returns a buffer based on flags (PyObject_GetBuffer)
+ try:
+ return w_obj.buffer_w(self, flags)
+ except TypeError:
+ raise oefmt(self.w_TypeError,
+ "'%T' does not have the buffer interface", w_obj)
+
+ def readbuf_w(self, w_obj):
+ # Old buffer interface, returns a readonly buffer (PyObject_AsReadBuffer)
+ try:
+ return w_obj.readbuf_w(self)
+ except TypeError:
+ raise oefmt(self.w_TypeError,
+ "expected a readable buffer object")
+
+ def writebuf_w(self, w_obj):
+ # Old buffer interface, returns a writeable buffer (PyObject_AsWriteBuffer)
+ try:
+ return w_obj.writebuf_w(self)
+ except TypeError:
+ raise oefmt(self.w_TypeError,
+ "expected a writeable buffer object")
+
+ def charbuf_w(self, w_obj):
+ # Old buffer interface, returns a character buffer (PyObject_AsCharBuffer)
+ try:
+ return w_obj.charbuf_w(self)
+ except TypeError:
+ raise oefmt(self.w_TypeError,
+ "expected a character buffer object")
+
+ def _getarg_error(self, expected, w_obj):
+ if self.is_none(w_obj):
+ name = "None"
+ else:
+ name = self.type(w_obj).get_module_type_name()
+ raise oefmt(self.w_TypeError, "must be %s, not %s", expected, name)
+
+ @specialize.arg(1)
+ def getarg_w(self, code, w_obj):
+ if code == 'z*':
+ if self.is_none(w_obj):
+ return None
+ code = 's*'
+ if code == 's*':
+ if self.isinstance_w(w_obj, self.w_str):
+ return w_obj.readbuf_w(self)
+ if self.isinstance_w(w_obj, self.w_unicode):
+ return self.str(w_obj).readbuf_w(self)
+ try:
+ return w_obj.buffer_w(self, 0)
+ except TypeError:
+ pass
+ try:
+ return w_obj.readbuf_w(self)
+ except TypeError:
+ self._getarg_error("string or buffer", w_obj)
+ elif code == 's#':
+ if self.isinstance_w(w_obj, self.w_str):
+ return w_obj.str_w(self)
+ if self.isinstance_w(w_obj, self.w_unicode):
+ return self.str(w_obj).str_w(self)
+ try:
+ return w_obj.readbuf_w(self).as_str()
+ except TypeError:
+ self._getarg_error("string or read-only buffer", w_obj)
+ elif code == 'w*':
+ try:
+ try:
+ return w_obj.buffer_w(self, self.BUF_WRITABLE)
+ except OperationError:
+ self._getarg_error("read-write buffer", w_obj)
+ except TypeError:
+ pass
+ try:
+ return w_obj.writebuf_w(self)
+ except TypeError:
+ self._getarg_error("read-write buffer", w_obj)
+ elif code == 't#':
+ try:
+ return w_obj.charbuf_w(self)
+ except TypeError:
+ self._getarg_error("string or read-only character buffer", w_obj)
+ else:
+ assert False
def bufferstr0_new_w(self, w_obj):
from rpython.rlib import rstring
@@ -1359,6 +1467,7 @@
'argument must be a string without NUL characters'))
return rstring.assert_str0(result)
+ # XXX rename/replace with code more like CPython getargs for buffers
def bufferstr_w(self, w_obj):
# Directly returns an interp-level str. Note that if w_obj is a
# unicode string, this is different from str_w(buffer(w_obj)):
@@ -1373,8 +1482,18 @@
except OperationError, e:
if not e.match(self, self.w_TypeError):
raise
- buffer = self.buffer_w(w_obj)
- return buffer.as_str()
+ try:
+ buf = w_obj.buffer_w(self, 0)
+ except TypeError:
+ pass
+ else:
+ return buf.as_str()
+ try:
+ buf = w_obj.readbuf_w(self)
+ except TypeError:
+ self._getarg_error("string or buffer", w_obj)
+ else:
+ return buf.as_str()
def bufferstr_or_u_w(self, w_obj):
"""Returns an interp-level str, directly if possible.
diff --git a/pypy/interpreter/buffer.py b/pypy/interpreter/buffer.py
deleted file mode 100644
--- a/pypy/interpreter/buffer.py
+++ /dev/null
@@ -1,118 +0,0 @@
-"""
-Buffer protocol support.
-"""
-from rpython.rlib.objectmodel import import_from_mixin
-
-
-class Buffer(object):
- """Abstract base class for buffers."""
- __slots__ = []
-
- def getlength(self):
- raise NotImplementedError
-
- 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 getitem(self, index):
- "Returns the index'th character in the buffer."
- raise NotImplementedError # Must be overriden. No bounds checks.
-
- 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 get_raw_address(self):
- raise ValueError("no raw buffer")
-
- def is_writable(self):
- return False
-
-
-class RWBuffer(Buffer):
- """Abstract base class for read-write buffers."""
- __slots__ = []
-
- def is_writable(self):
- return True
-
- def setitem(self, index, char):
- "Write a character into the buffer."
- raise NotImplementedError # Must be overriden. No bounds checks.
-
- def setslice(self, start, string):
- # May be overridden. No bounds checks.
- for i in range(len(string)):
- self.setitem(start + i, string[i])
-
-
-class StringBuffer(Buffer):
- __slots__ = ['value']
-
- def __init__(self, value):
- self.value = value
-
- def getlength(self):
- return len(self.value)
-
- def as_str(self):
- return self.value
-
- def getitem(self, index):
- return self.value[index]
-
- def getslice(self, start, stop, step, size):
- if size == 0:
- return ""
- if step == 1:
- assert 0 <= start <= stop
- return self.value[start:stop]
- return "".join([self.value[start + i*step] for i in xrange(size)])
-# ____________________________________________________________
-
-
-class SubBufferMixin(object):
- _attrs_ = ['buffer', 'offset', 'size']
-
- def __init__(self, buffer, offset, size):
- self.buffer = buffer
- self.offset = offset
- self.size = size
-
- def getlength(self):
- at_most = self.buffer.getlength() - self.offset
- if 0 <= self.size <= at_most:
- return self.size
- elif at_most >= 0:
- return at_most
- else:
- return 0
-
- def getitem(self, index):
- return self.buffer.getitem(self.offset + index)
-
- def getslice(self, start, stop, step, size):
- if start == stop:
- return '' # otherwise, adding self.offset might make them
- # out of bounds
- return self.buffer.getslice(self.offset + start, self.offset + stop,
- step, size)
-
-
-class SubBuffer(Buffer):
- import_from_mixin(SubBufferMixin)
-
-
-class RWSubBuffer(RWBuffer):
- import_from_mixin(SubBufferMixin)
-
- def setitem(self, index, char):
- self.buffer.setitem(self.offset + index, char)
-
- def setslice(self, start, string):
- if len(string) == 0:
- return # otherwise, adding self.offset might make 'start'
- # out of bounds
- self.buffer.setslice(self.offset + start, string)
diff --git a/pypy/interpreter/test/test_buffer.py b/pypy/interpreter/test/test_buffer.py
deleted file mode 100644
--- a/pypy/interpreter/test/test_buffer.py
+++ /dev/null
@@ -1,37 +0,0 @@
-import py
-from rpython.tool.udir import udir
-
-testdir = udir.ensure('test_buffer', dir=1)
-
-
-class TestBuffer:
- def test_buffer_w(self):
- space = self.space
- w_hello = space.wrapbytes('hello world')
- buf = space.buffer_w(w_hello)
- assert buf.getlength() == 11
- assert buf.as_str() == 'hello world'
- assert buf.getslice(1, 6, 1, 5) == 'ello '
- assert space.buffer_w(space.newbuffer(buf)) is buf
- assert space.bufferstr_w(w_hello) == 'hello world'
- assert space.bufferstr_w(space.newbuffer(space.buffer_w(w_hello))) == 'hello world'
- space.raises_w(space.w_TypeError, space.buffer_w, space.wrap(5))
- e = space.raises_w(space.w_TypeError, space.buffer_w, space.wrap(5))
- message = space.unwrap(e.value.get_w_value(space))
- assert "'int' does not support the buffer interface" == message
-
- def test_file_write(self):
- space = self.space
- w_buffer = space.newbuffer(space.buffer_w(space.wrapbytes('hello world')))
- filename = str(testdir.join('test_file_write'))
- space.appexec([w_buffer, space.wrap(filename)], """(buffer, filename):
- f = open(filename, 'wb')
- f.write(buffer)
- f.close()
- """)
- f = open(filename, 'rb')
- data = f.read()
- f.close()
- assert data == 'hello world'
-
-# Note: some app-level tests for buffer are in objspace/std/test/test_memoryview.py.
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,13 +2,16 @@
# A convenient read-write buffer. Located here for want of a better place.
#
-from pypy.interpreter.buffer import RWBuffer
+from rpython.rlib.buffer import Buffer
from pypy.interpreter.gateway import unwrap_spec
-class ByteBuffer(RWBuffer):
+class ByteBuffer(Buffer):
+ _immutable_ = True
+
def __init__(self, len):
self.data = ['\x00'] * len
+ self.readonly = False
def getlength(self):
return len(self.data)
diff --git a/pypy/module/__pypy__/test/test_bytebuffer.py b/pypy/module/__pypy__/test/test_bytebuffer.py
--- a/pypy/module/__pypy__/test/test_bytebuffer.py
+++ b/pypy/module/__pypy__/test/test_bytebuffer.py
@@ -12,3 +12,18 @@
assert b[-1] == b'*'
assert b[-2] == b'-'
assert b[-3] == b'+'
+ exc = raises(TypeError, "b[3] = b'abc'")
+ assert str(exc.value) == "right operand must be a single byte"
+ exc = raises(TypeError, "b[3:5] = b'abc'")
+ assert str(exc.value) == "right operand length must match slice length"
+ exc = raises(TypeError, "b[3:7:2] = b'abc'")
+ assert str(exc.value) == "right operand length must match slice length"
+
+ b = bytebuffer(10)
+ b[1:3] = b'xy'
+ assert bytes(b) == b"\x00xy" + b"\x00" * 7
+ b[4:8:2] = b'zw'
+ assert bytes(b) == b"\x00xy\x00z\x00w" + b"\x00" * 3
+ r = str(buffer(u'#'))
+ b[6:6+len(r)] = u'#'
+ assert str(b[:6+len(r)]) == "\x00xy\x00z\x00" + r
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
@@ -1,22 +1,23 @@
from pypy.interpreter.baseobjspace import W_Root
-from pypy.interpreter.buffer import RWBuffer
from pypy.interpreter.error import oefmt
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.objspace.std.memoryview import _buffer_setitem
+from rpython.rlib.buffer import Buffer
from rpython.rtyper.annlowlevel import llstr
from rpython.rtyper.lltypesystem import rffi
from rpython.rtyper.lltypesystem.rstr import copy_string_to_raw
-class LLBuffer(RWBuffer):
+class LLBuffer(Buffer):
_immutable_ = True
def __init__(self, raw_cdata, size):
self.raw_cdata = raw_cdata
self.size = size
+ self.readonly = False
def getlength(self):
return self.size
@@ -33,7 +34,7 @@
def getslice(self, start, stop, step, size):
if step == 1:
return rffi.charpsize2str(rffi.ptradd(self.raw_cdata, start), size)
- return RWBuffer.getslice(self, start, stop, step, size)
+ return Buffer.getslice(self, start, stop, step, size)
def setslice(self, start, string):
raw_cdata = rffi.ptradd(self.raw_cdata, start)
diff --git a/pypy/module/_codecs/__init__.py b/pypy/module/_codecs/__init__.py
--- a/pypy/module/_codecs/__init__.py
+++ b/pypy/module/_codecs/__init__.py
@@ -72,7 +72,7 @@
'utf_32_le_decode' : 'interp_codecs.utf_32_le_decode',
'utf_32_le_encode' : 'interp_codecs.utf_32_le_encode',
'utf_32_ex_decode' : 'interp_codecs.utf_32_ex_decode',
- 'readbuffer_encode': 'interp_codecs.buffer_encode',
+ 'readbuffer_encode': 'interp_codecs.readbuffer_encode',
'charmap_decode' : 'interp_codecs.charmap_decode',
'charmap_encode' : 'interp_codecs.charmap_encode',
'escape_encode' : 'interp_codecs.escape_encode',
diff --git a/pypy/module/_codecs/interp_codecs.py b/pypy/module/_codecs/interp_codecs.py
--- a/pypy/module/_codecs/interp_codecs.py
+++ b/pypy/module/_codecs/interp_codecs.py
@@ -423,8 +423,9 @@
w_res = space.call_function(w_encoder, w_obj, space.wrap(errors))
return space.getitem(w_res, space.wrap(0))
- at unwrap_spec(s='bufferstr_or_u', errors='str_or_None')
-def buffer_encode(space, s, errors='strict'):
+ at unwrap_spec(errors='str_or_None')
+def readbuffer_encode(space, w_data, errors='strict'):
+ s = space.getarg_w('s#', w_data)
return space.newtuple([space.wrapbytes(s), space.wrap(len(s))])
@unwrap_spec(errors=str)
diff --git a/pypy/module/_codecs/test/test_codecs.py b/pypy/module/_codecs/test/test_codecs.py
--- a/pypy/module/_codecs/test/test_codecs.py
+++ b/pypy/module/_codecs/test/test_codecs.py
@@ -428,14 +428,12 @@
for (i, line) in enumerate(reader):
assert line == s[i]
- def test_readbuffer_encode(self):
- import _codecs
- assert _codecs.readbuffer_encode("") == (b"", 0)
-
- def test_readbuffer_encode_array(self):
+ def test_buffer_encode(self):
import _codecs, array
assert (_codecs.readbuffer_encode(array.array('b', b'spam')) ==
(b'spam', 4))
+ assert _codecs.readbuffer_encode(u"test") == (b'test', 4)
+ assert _codecs.readbuffer_encode("") == (b"", 0)
def test_utf8sig(self):
import codecs
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 RWBuffer
+from rpython.rlib.buffer import Buffer
from rpython.rlib.rstring import StringBuilder
from rpython.rlib.rarithmetic import r_longlong, intmask
from rpython.rlib import rposix
@@ -81,7 +81,7 @@
self._unsupportedoperation(space, "detach")
def readinto_w(self, space, w_buffer):
- rwbuffer = space.rwbuffer_w(w_buffer)
+ rwbuffer = space.getarg_w('w*', w_buffer)
length = rwbuffer.getlength()
w_data = space.call_method(self, "read", space.wrap(length))
@@ -107,11 +107,14 @@
readinto = interp2app(W_BufferedIOBase.readinto_w),
)
-class RawBuffer(RWBuffer):
+class RawBuffer(Buffer):
+ _immutable_ = True
+
def __init__(self, buf, start, length):
self.buf = buf
self.start = start
self.length = length
+ self.readonly = False
def getlength(self):
return self.length
@@ -708,7 +711,7 @@
def write_w(self, space, w_data):
self._check_init(space)
self._check_closed(space, "write to closed file")
- data = space.bufferstr_w(w_data)
+ data = space.getarg_w('s*', w_data).as_str()
size = len(data)
with self.lock:
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
@@ -82,7 +82,7 @@
def readinto_w(self, space, w_buffer):
self._check_closed(space)
- rwbuffer = space.rwbuffer_w(w_buffer)
+ rwbuffer = space.getarg_w('w*', w_buffer)
size = rwbuffer.getlength()
output = self.read(size)
@@ -91,10 +91,7 @@
def write_w(self, space, w_data):
self._check_closed(space)
- if space.isinstance_w(w_data, space.w_unicode):
- raise OperationError(space.w_TypeError, space.wrap(
- "bytes string of buffer expected"))
- buf = space.bufferstr_w(w_data)
+ buf = space.buffer_w(w_data, space.BUF_CONTIG_RO).as_str()
length = len(buf)
if length <= 0:
return space.wrap(0)
diff --git a/pypy/module/_io/interp_fileio.py b/pypy/module/_io/interp_fileio.py
--- a/pypy/module/_io/interp_fileio.py
+++ b/pypy/module/_io/interp_fileio.py
@@ -340,7 +340,7 @@
def write_w(self, space, w_data):
self._check_closed(space)
self._check_writable(space)
- data = space.bufferstr_w(w_data)
+ data = space.getarg_w('s*', w_data).as_str()
try:
n = os.write(self.fd, data)
@@ -373,7 +373,7 @@
def readinto_w(self, space, w_buffer):
self._check_closed(space)
self._check_readable(space)
- rwbuffer = space.rwbuffer_w(w_buffer)
+ rwbuffer = space.getarg_w('w*', w_buffer)
length = rwbuffer.getlength()
try:
buf = os.read(self.fd, length)
diff --git a/pypy/module/_io/test/test_bufferedio.py b/pypy/module/_io/test/test_bufferedio.py
--- a/pypy/module/_io/test/test_bufferedio.py
+++ b/pypy/module/_io/test/test_bufferedio.py
@@ -139,6 +139,14 @@
raw = _io.FileIO(self.tmpfile)
f = _io.BufferedReader(raw)
assert f.readinto(a) == 5
+ exc = raises(TypeError, f.readinto, u"hello")
+ assert str(exc.value) == "cannot use unicode as modifiable buffer"
+ exc = raises(TypeError, f.readinto, buffer(b"hello"))
+ assert str(exc.value) == "must be read-write buffer, not buffer"
+ exc = raises(TypeError, f.readinto, buffer(bytearray("hello")))
+ assert str(exc.value) == "must be read-write buffer, not buffer"
+ exc = raises(TypeError, f.readinto, memoryview(b"hello"))
+ assert str(exc.value) == "must be read-write buffer, not memoryview"
f.close()
assert a == b'a\nb\ncxxxxx'
@@ -250,6 +258,7 @@
raw = _io.FileIO(self.tmpfile, 'w')
f = _io.BufferedWriter(raw)
f.write(b"abcd")
+ raises(TypeError, f.write, u"cd")
f.close()
assert self.readfile() == b"abcd"
diff --git a/pypy/module/_io/test/test_bytesio.py b/pypy/module/_io/test/test_bytesio.py
--- a/pypy/module/_io/test/test_bytesio.py
+++ b/pypy/module/_io/test/test_bytesio.py
@@ -43,6 +43,8 @@
f = _io.BytesIO()
assert f.write(b"") == 0
assert f.write(b"hello") == 5
+ exc = raises(TypeError, f.write, u"lo")
+ assert str(exc.value) == "'unicode' does not have the buffer interface"
import gc; gc.collect()
assert f.getvalue() == b"hello"
f.close()
@@ -102,6 +104,14 @@
a2 = bytearray(b'testing')
assert b.readinto(a1) == 1
assert b.readinto(a2) == 4
+ exc = raises(TypeError, b.readinto, u"hello")
+ assert str(exc.value) == "cannot use unicode as modifiable buffer"
+ exc = raises(TypeError, b.readinto, buffer(b"hello"))
+ assert str(exc.value) == "must be read-write buffer, not buffer"
+ exc = raises(TypeError, b.readinto, buffer(bytearray("hello")))
+ assert str(exc.value) == "must be read-write buffer, not buffer"
+ exc = raises(TypeError, b.readinto, memoryview(b"hello"))
+ assert str(exc.value) == "must be read-write buffer, not memoryview"
b.close()
assert a1 == b"h"
assert a2 == b"elloing"
diff --git a/pypy/module/_io/test/test_fileio.py b/pypy/module/_io/test/test_fileio.py
--- a/pypy/module/_io/test/test_fileio.py
+++ b/pypy/module/_io/test/test_fileio.py
@@ -135,6 +135,14 @@
a = bytearray(b'x' * 10)
f = _io.FileIO(self.tmpfile, 'r+')
assert f.readinto(a) == 10
+ exc = raises(TypeError, f.readinto, u"hello")
+ assert str(exc.value) == "cannot use unicode as modifiable buffer"
+ exc = raises(TypeError, f.readinto, buffer(b"hello"))
+ assert str(exc.value) == "must be read-write buffer, not buffer"
+ exc = raises(TypeError, f.readinto, buffer(bytearray("hello")))
+ assert str(exc.value) == "must be read-write buffer, not buffer"
+ exc = raises(TypeError, f.readinto, memoryview(b"hello"))
+ assert str(exc.value) == "must be read-write buffer, not memoryview"
f.close()
assert a == b'a\nb\nc\0\0\0\0\0'
#
diff --git a/pypy/module/_multiprocessing/interp_connection.py b/pypy/module/_multiprocessing/interp_connection.py
--- a/pypy/module/_multiprocessing/interp_connection.py
+++ b/pypy/module/_multiprocessing/interp_connection.py
@@ -81,8 +81,9 @@
raise OperationError(space.w_IOError,
space.wrap("connection is read-only"))
- @unwrap_spec(buf='bufferstr', offset='index', size='index')
- def send_bytes(self, space, buf, offset=0, size=PY_SSIZE_T_MIN):
+ @unwrap_spec(offset='index', size='index')
+ def send_bytes(self, space, w_buf, offset=0, size=PY_SSIZE_T_MIN):
+ buf = space.getarg_w('s*', w_buf).as_str()
length = len(buf)
self._check_writable(space)
if offset < 0:
@@ -123,7 +124,7 @@
@unwrap_spec(offset='index')
def recv_bytes_into(self, space, w_buffer, offset=0):
- rwbuffer = space.rwbuffer_w(w_buffer)
+ rwbuffer = space.writebuf_w(w_buffer)
length = rwbuffer.getlength()
res, newbuf = self.do_recv_string(
@@ -150,7 +151,7 @@
w_pickled = space.call_method(
w_picklemodule, "dumps", w_obj, w_protocol)
- buf = space.bufferstr_w(w_pickled)
+ buf = space.str_w(w_pickled)
self.do_send_string(space, buf, 0, len(buf))
def recv(self, space):
diff --git a/pypy/module/_rawffi/buffer.py b/pypy/module/_rawffi/buffer.py
--- a/pypy/module/_rawffi/buffer.py
+++ b/pypy/module/_rawffi/buffer.py
@@ -1,12 +1,14 @@
-from pypy.interpreter.buffer import RWBuffer
+from rpython.rlib.buffer import Buffer
# XXX not the most efficient implementation
-class RawFFIBuffer(RWBuffer):
+class RawFFIBuffer(Buffer):
+ _immutable_ = True
def __init__(self, datainstance):
self.datainstance = datainstance
+ self.readonly = False
def getlength(self):
return self.datainstance.getrawsize()
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
@@ -18,6 +18,7 @@
from rpython.tool.sourcetools import func_with_new_name
from rpython.rlib.rarithmetic import intmask, r_uint
+from pypy.module._rawffi.buffer import RawFFIBuffer
from pypy.module._rawffi.tracker import tracker
TYPEMAP = {
@@ -359,8 +360,13 @@
lltype.free(self.ll_buffer, flavor='raw')
self.ll_buffer = lltype.nullptr(rffi.VOIDP.TO)
- def buffer_w(self, space):
- from pypy.module._rawffi.buffer import RawFFIBuffer
+ def buffer_w(self, space, flags):
+ return RawFFIBuffer(self)
+
+ def readbuf_w(self, space):
+ return RawFFIBuffer(self)
+
+ def writebuf_w(self, space):
return RawFFIBuffer(self)
def getrawsize(self):
diff --git a/pypy/module/_rawffi/test/test__rawffi.py b/pypy/module/_rawffi/test/test__rawffi.py
--- a/pypy/module/_rawffi/test/test__rawffi.py
+++ b/pypy/module/_rawffi/test/test__rawffi.py
@@ -1093,6 +1093,12 @@
assert a[3] == b'z'
assert a[4] == b't'
+ b = memoryview(a)
+ assert len(b) == 10
+ assert b[3] == 'z'
+ b[3] = 'x'
+ assert b[3] == 'x'
+
def test_union(self):
import _rawffi
longsize = _rawffi.sizeof('l')
diff --git a/pypy/module/_socket/interp_socket.py b/pypy/module/_socket/interp_socket.py
--- a/pypy/module/_socket/interp_socket.py
+++ b/pypy/module/_socket/interp_socket.py
@@ -457,7 +457,7 @@
@unwrap_spec(nbytes=int, flags=int)
def recv_into_w(self, space, w_buffer, nbytes=0, flags=0):
- rwbuffer = space.rwbuffer_w(w_buffer)
+ rwbuffer = space.getarg_w('w*', w_buffer)
lgt = rwbuffer.getlength()
if nbytes == 0 or nbytes > lgt:
nbytes = lgt
@@ -468,7 +468,7 @@
@unwrap_spec(nbytes=int, flags=int)
def recvfrom_into_w(self, space, w_buffer, nbytes=0, flags=0):
- rwbuffer = space.rwbuffer_w(w_buffer)
+ rwbuffer = space.getarg_w('w*', w_buffer)
lgt = rwbuffer.getlength()
if nbytes == 0 or nbytes > lgt:
nbytes = lgt
diff --git a/pypy/module/_socket/test/test_sock_app.py b/pypy/module/_socket/test/test_sock_app.py
--- a/pypy/module/_socket/test/test_sock_app.py
+++ b/pypy/module/_socket/test/test_sock_app.py
@@ -534,6 +534,8 @@
s.connect(("www.python.org", 80))
except _socket.gaierror as ex:
skip("GAIError - probably no connection: %s" % str(ex.args))
+ exc = raises(TypeError, s.send, None)
+ assert str(exc.value) == "must be string or buffer, not None"
assert s.send(memoryview(b'')) == 0
assert s.sendall(memoryview(b'')) is None
exc = raises(TypeError, s.send, '')
@@ -694,6 +696,13 @@
msg = buf.tobytes()[:len(MSG)]
assert msg == MSG
+ conn.send(MSG)
+ buf = bytearray(1024)
+ nbytes = cli.recv_into(memoryview(buf))
+ assert nbytes == len(MSG)
+ msg = buf[:len(MSG)]
+ assert msg == MSG
+
def test_recvfrom_into(self):
import socket
import array
@@ -710,6 +719,13 @@
msg = buf.tobytes()[:len(MSG)]
assert msg == MSG
+ conn.send(MSG)
+ buf = bytearray(1024)
+ nbytes, addr = cli.recvfrom_into(memoryview(buf))
+ assert nbytes == len(MSG)
+ msg = buf[:len(MSG)]
+ assert msg == MSG
+
def test_family(self):
import socket
cli = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
diff --git a/pypy/module/_sre/interp_sre.py b/pypy/module/_sre/interp_sre.py
--- a/pypy/module/_sre/interp_sre.py
+++ b/pypy/module/_sre/interp_sre.py
@@ -118,7 +118,7 @@
return rsre_core.UnicodeMatchContext(self.code, unicodestr,
pos, endpos, self.flags)
else:
- buf = space.buffer_w(w_string)
+ buf = space.readbuf_w(w_string)
if (not space.is_none(self.w_pattern) and
space.isinstance_w(self.w_pattern, space.w_unicode)):
raise OperationError(space.w_TypeError, space.wrap(
diff --git a/pypy/module/_winreg/interp_winreg.py b/pypy/module/_winreg/interp_winreg.py
--- a/pypy/module/_winreg/interp_winreg.py
+++ b/pypy/module/_winreg/interp_winreg.py
@@ -2,7 +2,7 @@
from pypy.interpreter.baseobjspace import W_Root
from pypy.interpreter.gateway import interp2app, unwrap_spec
from pypy.interpreter.typedef import TypeDef, GetSetProperty
-from pypy.interpreter.error import OperationError, wrap_windowserror
+from pypy.interpreter.error import OperationError, wrap_windowserror, oefmt
from rpython.rtyper.lltypesystem import rffi, lltype
from rpython.rlib import rwinreg, rwin32
from rpython.rlib.rarithmetic import r_uint, intmask
@@ -327,7 +327,14 @@
buf = lltype.malloc(rffi.CCHARP.TO, 1, flavor='raw')
buf[0] = '\0'
else:
- value = space.bufferstr_w(w_value)
+ try:
+ value = w_value.readbuf_w(space)
+ except TypeError:
+ raise oefmt(space.w_TypeError,
+ "Objects of type '%T' can not be used as binary "
+ "registry values", w_value)
+ else:
+ value = value.as_str()
buflen = len(value)
buf = rffi.str2charp(value)
diff --git a/pypy/module/_winreg/test/test_winreg.py b/pypy/module/_winreg/test/test_winreg.py
--- a/pypy/module/_winreg/test/test_winreg.py
+++ b/pypy/module/_winreg/test/test_winreg.py
@@ -140,11 +140,15 @@
assert 0, "Did not raise"
def test_SetValueEx(self):
- from winreg import CreateKey, SetValueEx
+ from winreg import CreateKey, SetValueEx, REG_BINARY
key = CreateKey(self.root_key, self.test_key_name)
sub_key = CreateKey(key, "sub_key")
for name, value, type in self.test_data:
SetValueEx(sub_key, name, 0, type, value)
+ exc = raises(TypeError, SetValueEx, sub_key, 'test_name', None,
+ REG_BINARY, memoryview('abc'))
+ assert str(exc.value) == ("Objects of type 'memoryview' can not "
+ "be used as binary registry values")
def test_readValues(self):
from winreg import OpenKey, EnumValue, QueryValueEx, EnumKey
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
@@ -1,6 +1,7 @@
from __future__ import with_statement
from rpython.rlib import jit
+from rpython.rlib.buffer import Buffer
from rpython.rlib.objectmodel import keepalive_until_here
from rpython.rlib.rarithmetic import ovfcheck, widen
from rpython.rlib.unroll import unrolling_iterable
@@ -9,7 +10,6 @@
from rpython.rtyper.lltypesystem.rstr import copy_string_to_raw
from pypy.interpreter.baseobjspace import W_Root
-from pypy.interpreter.buffer import RWBuffer
from pypy.interpreter.error import OperationError, oefmt
from pypy.interpreter.gateway import (
interp2app, interpindirect2app, unwrap_spec)
@@ -138,8 +138,11 @@
self.len = 0
self.allocated = 0
- def buffer_w(self, space):
- return ArrayBuffer(self)
+ def readbuf_w(self, space):
+ return ArrayBuffer(self, True)
+
+ def writebuf_w(self, space):
+ return ArrayBuffer(self, False)
def descr_append(self, space, w_x):
""" append(x)
@@ -247,9 +250,8 @@
self._charbuf_stop()
return self.space.wrapbytes(s)
- @unwrap_spec(s='bufferstr_or_u')
- def descr_fromstring(self, space, s):
- """fromstring(string)
+ def descr_fromstring(self, space, w_s):
+ """ fromstring(string)
Appends items from the string, interpreting it as an array of
machine values, as if it had been read from a file using the
@@ -257,6 +259,7 @@
This method is deprecated. Use frombytes instead.
"""
+ s = space.getarg_w('s#', w_s)
msg = "fromstring() is deprecated. Use frombytes() instead."
space.warn(space.wrap(msg), self.space.w_DeprecationWarning)
self.descr_frombytes(space, s)
@@ -303,7 +306,7 @@
self.descr_frombytes(space, item)
msg = "not enough items in file"
raise OperationError(space.w_EOFError, space.wrap(msg))
- self.descr_fromstring(space, item)
+ self.descr_fromstring(space, w_item)
def descr_tofile(self, space, w_f):
""" tofile(f)
@@ -628,9 +631,12 @@
v.typecode = k
unroll_typecodes = unrolling_iterable(types.keys())
-class ArrayBuffer(RWBuffer):
- def __init__(self, array):
+class ArrayBuffer(Buffer):
+ _immutable_ = True
+
+ def __init__(self, array, readonly):
self.array = array
+ self.readonly = readonly
def getlength(self):
return self.array.len * self.array.itemsize
diff --git a/pypy/module/array/test/test_array.py b/pypy/module/array/test/test_array.py
--- a/pypy/module/array/test/test_array.py
+++ b/pypy/module/array/test/test_array.py
@@ -131,7 +131,14 @@
raises(OverflowError, a.append, 2 ** (8 * b))
def test_fromstring(self):
- a = self.array('l')
+ a = self.array('b')
+ a.fromstring('Hi!')
+ assert a[0] == b'H' and a[1] == b'i' and a[2] == b'!' and len(a) == 3
+ a = self.array('b')
+ exc = raises(TypeError, a.fromstring, memoryview(b'xyz'))
+ assert str(exc.value) == "must be string or read-only buffer, not memoryview"
+ assert a[0] == b'x' and a[1] == b'y' and a[2] == b'z' and len(a) == 3
+ a = self.array('b')
a.fromstring('')
assert not len(a)
@@ -404,7 +411,6 @@
def test_buffer_write(self):
a = self.array('b', b'hello')
buf = memoryview(a)
- print(repr(buf))
try:
buf[3] = b'L'
except TypeError:
diff --git a/pypy/module/cppyy/converter.py b/pypy/module/cppyy/converter.py
--- a/pypy/module/cppyy/converter.py
+++ b/pypy/module/cppyy/converter.py
@@ -63,7 +63,7 @@
def get_rawbuffer(space, w_obj):
# raw buffer
try:
- buf = space.buffer_w(w_obj)
+ buf = space.buffer_w(w_obj, space.BUF_SIMPLE)
return rffi.cast(rffi.VOIDP, buf.get_raw_address())
except Exception:
pass
@@ -163,7 +163,7 @@
def to_memory(self, space, w_obj, w_value, offset):
# copy the full array (uses byte copy for now)
address = rffi.cast(rffi.CCHARP, self._get_raw_address(space, w_obj, offset))
- buf = space.buffer_w(w_value)
+ buf = space.buffer_w(w_value, space.BUF_SIMPLE)
# TODO: report if too many items given?
for i in range(min(self.size*self.typesize, buf.getlength())):
address[i] = buf.getitem(i)
@@ -204,7 +204,7 @@
# copy only the pointer value
rawobject = get_rawobject_nonnull(space, w_obj)
byteptr = rffi.cast(rffi.CCHARPP, capi.direct_ptradd(rawobject, offset))
- buf = space.buffer_w(w_value)
+ buf = space.buffer_w(w_value, space.BUF_SIMPLE)
try:
byteptr[0] = buf.get_raw_address()
except ValueError:
diff --git a/pypy/module/cpyext/api.py b/pypy/module/cpyext/api.py
--- a/pypy/module/cpyext/api.py
+++ b/pypy/module/cpyext/api.py
@@ -22,7 +22,6 @@
from pypy.interpreter.nestedscope import Cell
from pypy.interpreter.module import Module
from pypy.interpreter.function import StaticMethod
-from pypy.objspace.std.memoryview import W_MemoryView
from pypy.objspace.std.sliceobject import W_SliceObject
from pypy.module.__builtin__.descriptor import W_Property
from pypy.module.micronumpy.base import W_NDimArray
@@ -475,7 +474,7 @@
"PyLong_Type": "space.w_int",
"PyComplex_Type": "space.w_complex",
"PyByteArray_Type": "space.w_bytearray",
- "PyMemoryView_Type": "space.gettypeobject(W_MemoryView.typedef)",
+ "PyMemoryView_Type": "space.w_memoryview",
"PyArray_Type": "space.gettypeobject(W_NDimArray.typedef)",
"PyBaseObject_Type": "space.w_object",
'PyNone_Type': 'space.type(space.w_None)',
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
@@ -15,8 +15,8 @@
from pypy.module.cpyext.pyerrors import PyErr_Occurred
from pypy.module.cpyext.state import State
from pypy.interpreter.error import OperationError, oefmt
-from pypy.interpreter.buffer import Buffer
from pypy.interpreter.argument import Arguments
+from rpython.rlib.buffer import Buffer
from rpython.rlib.unroll import unrolling_iterable
from rpython.rlib.objectmodel import specialize
from rpython.tool.sourcetools import func_renamer
@@ -230,11 +230,13 @@
class CPyBuffer(Buffer):
# Similar to Py_buffer
+ _immutable_ = True
def __init__(self, ptr, size, w_obj):
self.ptr = ptr
self.size = size
self.w_obj = w_obj # kept alive
+ self.readonly = True
def getlength(self):
return self.size
diff --git a/pypy/module/cpyext/test/test_arraymodule.py b/pypy/module/cpyext/test/test_arraymodule.py
--- a/pypy/module/cpyext/test/test_arraymodule.py
+++ b/pypy/module/cpyext/test/test_arraymodule.py
@@ -54,7 +54,7 @@
module = self.import_module(name='array')
arr = module.array('i', [1,2,3,4])
# XXX big-endian
- assert memoryview(arr).tobytes() == (b'\x01\0\0\0'
- b'\x02\0\0\0'
- b'\x03\0\0\0'
- b'\x04\0\0\0')
+ assert bytes(arr) == (b'\x01\0\0\0'
+ b'\x02\0\0\0'
+ b'\x03\0\0\0'
+ b'\x04\0\0\0')
diff --git a/pypy/module/fcntl/interp_fcntl.py b/pypy/module/fcntl/interp_fcntl.py
--- a/pypy/module/fcntl/interp_fcntl.py
+++ b/pypy/module/fcntl/interp_fcntl.py
@@ -1,6 +1,6 @@
from rpython.rtyper.tool import rffi_platform as platform
from rpython.rtyper.lltypesystem import rffi, lltype
-from pypy.interpreter.error import OperationError, wrap_oserror
+from pypy.interpreter.error import OperationError, wrap_oserror, oefmt
from pypy.interpreter.gateway import unwrap_spec, WrappedDefault
from rpython.rlib import rposix
from rpython.translator.tool.cbuild import ExternalCompilationInfo
@@ -92,38 +92,27 @@
op = rffi.cast(rffi.INT, op) # C long => C int
try:
- intarg = space.int_w(w_arg)
+ arg = space.getarg_w('s#', w_arg)
except OperationError, e:
if not e.match(space, space.w_TypeError):
raise
else:
- intarg = rffi.cast(rffi.INT, intarg) # C long => C int
- rv = fcntl_int(fd, op, intarg)
- if rv < 0:
- raise _get_error(space, "fcntl")
- return space.wrap(rv)
+ ll_arg = rffi.str2charp(arg)
+ try:
+ rv = fcntl_str(fd, op, ll_arg)
+ if rv < 0:
+ raise _get_error(space, "fcntl")
+ arg = rffi.charpsize2str(ll_arg, len(arg))
+ return space.wrap(arg)
+ finally:
+ lltype.free(ll_arg, flavor='raw')
- try:
- arg = space.bufferstr_w(w_arg)
- except OperationError, e:
- if not e.match(space, space.w_TypeError):
- raise
- try:
- arg = space.str_w(w_arg)
- except OperationError, e:
- if not e.match(space, space.w_TypeError):
- raise
- raise OperationError(space.w_TypeError, space.wrap(
- "int or string or buffer required"))
-
- ll_arg = rffi.str2charp(arg)
- rv = fcntl_str(fd, op, ll_arg)
- arg = rffi.charpsize2str(ll_arg, len(arg))
- lltype.free(ll_arg, flavor='raw')
+ intarg = space.int_w(w_arg)
+ intarg = rffi.cast(rffi.INT, intarg) # C long => C int
+ rv = fcntl_int(fd, op, intarg)
if rv < 0:
raise _get_error(space, "fcntl")
- return space.wrapbytes(arg)
-
+ return space.wrapbytes(rv)
@unwrap_spec(op=int)
def flock(space, w_fd, op):
@@ -212,55 +201,50 @@
fd = space.c_filedescriptor_w(w_fd)
op = rffi.cast(rffi.INT, op) # C long => C int
- if mutate_flag != 0:
- try:
- rwbuffer = space.rwbuffer_w(w_arg)
- except OperationError, e:
- if not e.match(space, space.w_TypeError):
- raise
- if mutate_flag > 0:
- raise
- else:
- arg = rwbuffer.as_str()
- ll_arg = rffi.str2charp(arg)
- rv = ioctl_str(fd, op, ll_arg)
- arg = rffi.charpsize2str(ll_arg, len(arg))
- lltype.free(ll_arg, flavor='raw')
- if rv < 0:
- raise _get_error(space, "ioctl")
- rwbuffer.setslice(0, arg)
- return space.wrap(rv)
-
try:
- intarg = space.int_w(w_arg)
+ rwbuffer = space.writebuf_w(w_arg)
except OperationError, e:
if not e.match(space, space.w_TypeError):
raise
else:
- intarg = rffi.cast(rffi.INT, intarg) # C long => C int
- rv = ioctl_int(fd, op, intarg)
- if rv < 0:
- raise _get_error(space, "ioctl")
- return space.wrap(rv)
+ arg = rwbuffer.as_str()
+ ll_arg = rffi.str2charp(arg)
+ try:
+ rv = ioctl_str(fd, op, ll_arg)
+ if rv < 0:
+ raise _get_error(space, "ioctl")
+ arg = rffi.charpsize2str(ll_arg, len(arg))
+ if mutate_flag != 0:
+ rwbuffer.setslice(0, arg)
+ return space.wrap(rv)
+ return space.wrap(arg)
+ finally:
+ lltype.free(ll_arg, flavor='raw')
+
+ if mutate_flag != -1:
+ raise OperationError(space.w_TypeError, space.wrap(
+ "ioctl requires a file or file descriptor, an integer "
+ "and optionally an integer or buffer argument"))
try:
- arg = space.bufferstr_w(w_arg)
+ arg = space.getarg_w('s#', w_arg)
except OperationError, e:
if not e.match(space, space.w_TypeError):
raise
+ else:
+ ll_arg = rffi.str2charp(arg)
try:
- arg = space.str_w(w_arg)
- except OperationError, e:
- if not e.match(space, space.w_TypeError):
- raise
- raise OperationError(
- space.w_TypeError,
- space.wrap("int or string or buffer required"))
+ rv = ioctl_str(fd, op, ll_arg)
+ if rv < 0:
+ raise _get_error(space, "ioctl")
+ arg = rffi.charpsize2str(ll_arg, len(arg))
+ return space.wrap(arg)
+ finally:
+ lltype.free(ll_arg, flavor='raw')
- ll_arg = rffi.str2charp(arg)
- rv = ioctl_str(fd, op, ll_arg)
- arg = rffi.charpsize2str(ll_arg, len(arg))
- lltype.free(ll_arg, flavor='raw')
+ intarg = space.int_w(w_arg)
+ intarg = rffi.cast(rffi.INT, intarg) # C long => C int
+ rv = ioctl_int(fd, op, intarg)
if rv < 0:
raise _get_error(space, "ioctl")
- return space.wrapbytes(arg)
+ return space.wrapbytes(rv)
diff --git a/pypy/module/fcntl/test/test_fcntl.py b/pypy/module/fcntl/test/test_fcntl.py
--- a/pypy/module/fcntl/test/test_fcntl.py
+++ b/pypy/module/fcntl/test/test_fcntl.py
@@ -47,6 +47,8 @@
assert fcntl.fcntl(f, 1, 0) == 0
assert fcntl.fcntl(f, 2, "foo") == b"foo"
assert fcntl.fcntl(f, 2, memoryview(b"foo")) == b"foo"
+ exc = raises(TypeError, fcntl.fcntl, f, 2, memoryview(b"foo"))
+ assert 'integer' in str(exc.value)
try:
os.O_LARGEFILE
@@ -222,6 +224,16 @@
assert res == 0
assert buf.tostring() == expected
+ buf = array.array('i', [0])
+ res = fcntl.ioctl(mfd, TIOCGPGRP, buffer(buf))
+ assert res == expected
+ assert buf.tostring() == b'\x00' * 4
+
+ exc = raises(TypeError, fcntl.ioctl, mfd, TIOCGPGRP, memoryview(b'abc'))
+ assert 'integer' in str(exc.value)
+ exc = raises(TypeError, fcntl.ioctl, mfd, TIOCGPGRP, memoryview(b'abc'), False)
+ assert str(exc.value) == "ioctl requires a file or file descriptor, an integer and optionally an integer or buffer argument"
+
res = fcntl.ioctl(mfd, TIOCGPGRP, buf, False)
assert res == expected
diff --git a/pypy/module/marshal/interp_marshal.py b/pypy/module/marshal/interp_marshal.py
--- a/pypy/module/marshal/interp_marshal.py
+++ b/pypy/module/marshal/interp_marshal.py
@@ -223,7 +223,7 @@
space = self.space
if space.type(w_obj).is_heaptype():
try:
- buf = space.buffer_w(w_obj)
+ buf = space.readbuf_w(w_obj)
except OperationError as e:
if not e.match(space, space.w_TypeError):
raise
@@ -466,13 +466,7 @@
# Unmarshaller with inlined buffer string
def __init__(self, space, w_str):
Unmarshaller.__init__(self, space, None)
- try:
- self.bufstr = space.bufferstr_w(w_str)
- except OperationError, e:
- if not e.match(space, space.w_TypeError):
- raise
- raise OperationError(space.w_TypeError, space.wrap(
- 'marshal.loads() arg must be string or buffer'))
+ self.bufstr = space.getarg_w('s#', w_str)
self.bufpos = 0
self.limit = len(self.bufstr)
diff --git a/pypy/module/marshal/test/test_marshal.py b/pypy/module/marshal/test/test_marshal.py
--- a/pypy/module/marshal/test/test_marshal.py
+++ b/pypy/module/marshal/test/test_marshal.py
@@ -16,6 +16,9 @@
x = marshal.loads(s)
assert x == case and type(x) is type(case)
+ exc = raises(TypeError, marshal.loads, memoryview(s))
+ assert str(exc.value) == "must be string or read-only buffer, not memoryview"
+
import sys
if '__pypy__' in sys.builtin_module_names:
f = StringIO.StringIO()
diff --git a/pypy/module/marshal/test/test_marshalimpl.py b/pypy/module/marshal/test/test_marshalimpl.py
--- a/pypy/module/marshal/test/test_marshalimpl.py
+++ b/pypy/module/marshal/test/test_marshalimpl.py
@@ -25,6 +25,8 @@
s = marshal.dumps(array.array('b', b'asd'))
t = marshal.loads(s)
assert type(t) is bytes and t == b'asd'
+ exc = raises(ValueError, marshal.dumps, memoryview(b'asd'))
+ assert str(exc.value) == "unmarshallable object"
def test_unmarshal_evil_long(self):
import marshal
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
@@ -337,8 +337,14 @@
def descr_copy(self, space):
return self.convert_to(space, self.get_dtype(space))
- def buffer_w(self, space):
- return self.descr_ravel(space).buffer_w(space)
+ def buffer_w(self, space, flags):
+ return self.descr_ravel(space).buffer_w(space, flags)
+
+ def readbuf_w(self, space):
+ return self.descr_ravel(space).readbuf_w(space)
+
+ def charbuf_w(self, space):
+ return self.descr_ravel(space).charbuf_w(space)
def descr_byteswap(self, space):
return self.get_dtype(space).itemtype.byteswap(self)
diff --git a/pypy/module/micronumpy/concrete.py b/pypy/module/micronumpy/concrete.py
--- a/pypy/module/micronumpy/concrete.py
+++ b/pypy/module/micronumpy/concrete.py
@@ -1,6 +1,6 @@
-from pypy.interpreter.buffer import RWBuffer
from pypy.interpreter.error import OperationError, oefmt
from rpython.rlib import jit
+from rpython.rlib.buffer import Buffer
from rpython.rlib.debug import make_sure_not_resized
from rpython.rlib.rawstorage import alloc_raw_storage, free_raw_storage, \
raw_storage_getitem, raw_storage_setitem, RAW_STORAGE
@@ -316,8 +316,8 @@
def get_storage(self):
return self.storage
- def get_buffer(self, space):
- return ArrayBuffer(self)
+ def get_buffer(self, space, readonly):
+ return ArrayBuffer(self, readonly)
def astype(self, space, dtype):
strides, backstrides = calc_strides(self.get_shape(), dtype,
@@ -471,9 +471,12 @@
free_raw_storage(self.storage)
-class ArrayBuffer(RWBuffer):
- def __init__(self, impl):
+class ArrayBuffer(Buffer):
+ _immutable_ = True
+
+ def __init__(self, impl, readonly):
self.impl = impl
+ self.readonly = readonly
def getitem(self, item):
return raw_storage_getitem(lltype.Char, self.impl.storage, item)
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
@@ -610,11 +610,20 @@
raise OperationError(space.w_NotImplementedError, space.wrap(
"ctypes not implemented yet"))
- def buffer_w(self, space):
- return self.implementation.get_buffer(space)
+ def buffer_w(self, space, flags):
+ return self.implementation.get_buffer(space, True)
+
+ def readbuf_w(self, space):
+ return self.implementation.get_buffer(space, True)
+
+ def writebuf_w(self, space):
+ return self.implementation.get_buffer(space, False)
+
+ def charbuf_w(self, space):
+ return self.implementation.get_buffer(space, True).as_str()
def descr_get_data(self, space):
- return space.newbuffer(self.buffer_w(space))
+ return space.newbuffer(self.implementation.get_buffer(space, False))
@unwrap_spec(offset=int, axis1=int, axis2=int)
def descr_diagonal(self, space, offset=0, axis1=0, axis2=1):
@@ -1178,7 +1187,10 @@
raise OperationError(space.w_NotImplementedError,
space.wrap("unsupported param"))
- buf = space.buffer_w(w_buffer)
+ try:
+ buf = space.writebuf_w(w_buffer)
+ except OperationError:
+ buf = space.readbuf_w(w_buffer)
try:
raw_ptr = buf.get_raw_address()
except ValueError:
@@ -1196,7 +1208,7 @@
return W_NDimArray.from_shape_and_storage(space, shape, storage, dtype,
w_subtype=w_subtype,
w_base=w_buffer,
- writable=buf.is_writable())
+ writable=not buf.readonly)
order = order_converter(space, w_order, NPY.CORDER)
if order == NPY.CORDER:
diff --git a/pypy/module/micronumpy/test/test_ndarray.py b/pypy/module/micronumpy/test/test_ndarray.py
--- a/pypy/module/micronumpy/test/test_ndarray.py
+++ b/pypy/module/micronumpy/test/test_ndarray.py
@@ -347,6 +347,9 @@
a = np.array([1,2,3])
b = buffer(a)
assert type(b) is buffer
+ assert 'read-only buffer' in repr(b)
+ exc = raises(TypeError, "b[0] = '0'")
+ assert str(exc.value) == 'buffer is read-only'
def test_type(self):
from numpypy import array
@@ -2242,6 +2245,7 @@
a.data[4] = '\xff'
assert a[1] == 0xff
assert len(a.data) == 16
+ assert type(a.data) is buffer
def test_explicit_dtype_conversion(self):
from numpypy import array
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
@@ -2,8 +2,8 @@
from pypy.interpreter.baseobjspace import W_Root
from pypy.interpreter.typedef import TypeDef, GetSetProperty
from pypy.interpreter.gateway import interp2app, unwrap_spec
-from pypy.interpreter.buffer import RWBuffer
from rpython.rlib import rmmap, rarithmetic
+from rpython.rlib.buffer import Buffer
from rpython.rlib.rmmap import RValueError, RTypeError, RMMapError
if rmmap.HAVE_LARGEFILE_SUPPORT:
@@ -17,9 +17,9 @@
self.space = space
self.mmap = mmap_obj
- def buffer_w(self, space):
+ def readbuf_w(self, space):
self.check_valid()
- return MMapBuffer(self.space, self.mmap)
+ return MMapBuffer(self.space, self.mmap, True)
def close(self):
self.mmap.close()
@@ -304,10 +304,13 @@
mmap_error._dont_inline_ = True
-class MMapBuffer(RWBuffer):
- def __init__(self, space, mmap):
+class MMapBuffer(Buffer):
+ _immutable_ = True
+
+ def __init__(self, space, mmap, readonly):
self.space = space
self.mmap = mmap
+ self.readonly = readonly
def getlength(self):
return self.mmap.size
@@ -321,7 +324,7 @@
if step == 1:
return self.mmap.getslice(start, size)
else:
- return RWBuffer.getslice(self, start, stop, step, size)
+ return Buffer.getslice(self, start, stop, step, size)
def setitem(self, index, char):
self.check_valid_writeable()
@@ -331,14 +334,6 @@
self.check_valid_writeable()
self.mmap.setslice(start, string)
- def is_writable(self):
- try:
- self.mmap.check_writeable()
- except RMMapError:
- return False
- else:
- return True
-
def get_raw_address(self):
self.check_valid()
return self.mmap.data
diff --git a/pypy/module/mmap/test/test_mmap.py b/pypy/module/mmap/test/test_mmap.py
--- a/pypy/module/mmap/test/test_mmap.py
+++ b/pypy/module/mmap/test/test_mmap.py
@@ -542,20 +542,16 @@
m.close()
f.close()
- def test_buffer_write(self):
+ def test_memoryview(self):
from mmap import mmap
- f = open(self.tmpname + "y", "wb+")
- f.write(b"foobar")
+ f = open(self.tmpname + "y", "w+")
+ f.write("foobar")
f.flush()
m = mmap(f.fileno(), 6)
- m[5] = ord('?')
- b = memoryview(m)
- b[:3] = b"FOO"
- del b # For CPython: "cannot close exported pointers exist"
+ m[5] = '?'
+ exc = raises(TypeError, memoryview, m)
+ assert 'buffer interface' in str(exc.value)
m.close()
- f.seek(0)
- got = f.read()
- assert got == b"FOOba?"
f.close()
def test_offset(self):
diff --git a/pypy/module/struct/__init__.py b/pypy/module/struct/__init__.py
--- a/pypy/module/struct/__init__.py
+++ b/pypy/module/struct/__init__.py
@@ -50,7 +50,9 @@
interpleveldefs = {
'calcsize': 'interp_struct.calcsize',
'pack': 'interp_struct.pack',
+ 'pack_into': 'interp_struct.pack_into',
'unpack': 'interp_struct.unpack',
+ 'unpack_from': 'interp_struct.unpack_from',
'_clearcache': 'interp_struct.clearcache',
'Struct': 'interp_struct.W_Struct',
@@ -58,6 +60,4 @@
appleveldefs = {
'error': 'app_struct.error',
- 'pack_into': 'app_struct.pack_into',
- 'unpack_from': 'app_struct.unpack_from',
}
diff --git a/pypy/module/struct/app_struct.py b/pypy/module/struct/app_struct.py
--- a/pypy/module/struct/app_struct.py
+++ b/pypy/module/struct/app_struct.py
@@ -2,23 +2,8 @@
"""
Application-level definitions for the struct module.
"""
-import _struct as struct
class error(Exception):
"""Exception raised on various occasions; argument is a string
describing what is wrong."""
-
-# XXX inefficient
-def pack_into(fmt, buf, offset, *args):
- data = struct.pack(fmt, *args)
- memoryview(buf)[offset:offset+len(data)] = data
-
-# XXX inefficient
-def unpack_from(fmt, buf, offset=0):
- size = struct.calcsize(fmt)
- data = memoryview(buf)[offset:offset+size]
- if len(data) != size:
- raise error("unpack_from requires a buffer of at least %d bytes"
- % (size,))
- return struct.unpack(fmt, data)
diff --git a/pypy/module/struct/interp_struct.py b/pypy/module/struct/interp_struct.py
--- a/pypy/module/struct/interp_struct.py
+++ b/pypy/module/struct/interp_struct.py
@@ -5,7 +5,7 @@
from pypy.interpreter.baseobjspace import W_Root
from pypy.interpreter.gateway import interp2app, unwrap_spec
-from pypy.interpreter.error import OperationError
+from pypy.interpreter.error import OperationError, oefmt
from pypy.interpreter.typedef import TypeDef, interp_attrproperty
from pypy.module.struct.formatiterator import (
PackFormatIterator, UnpackFormatIterator
@@ -29,6 +29,7 @@
raise OperationError(w_error, space.wrap(e.msg))
return fmtiter.totalsize
+
@unwrap_spec(format=str)
def pack(space, format, args_w):
if jit.isconstant(format):
@@ -47,6 +48,23 @@
return space.wrapbytes(fmtiter.result.build())
+# XXX inefficient
+ at unwrap_spec(format=str, offset=int)
+def pack_into(space, format, w_buf, offset, args_w):
+ res = pack(space, format, args_w).str_w(space)
+ buf = space.writebuf_w(w_buf)
+ if offset < 0:
+ offset += buf.getlength()
+ size = len(res)
+ if offset < 0 or (buf.getlength() - offset) < size:
+ w_module = space.getbuiltinmodule('struct')
+ w_error = space.getattr(w_module, space.wrap('error'))
+ raise oefmt(w_error,
+ "pack_into requires a buffer of at least %d bytes",
+ size)
+ buf.setslice(offset, res)
+
+
@unwrap_spec(format=str, input='bufferstr')
def unpack(space, format, input):
fmtiter = UnpackFormatIterator(space, input)
@@ -65,6 +83,27 @@
# No cache in this implementation
+# XXX inefficient
+ at unwrap_spec(format=str, offset=int)
+def unpack_from(space, format, w_buf, offset=0):
+ size = _calcsize(space, format)
+ buf = space.getarg_w('z*', w_buf)
+ if buf is None:
+ w_module = space.getbuiltinmodule('struct')
+ w_error = space.getattr(w_module, space.wrap('error'))
+ raise oefmt(w_error, "unpack_from requires a buffer argument")
+ if offset < 0:
+ offset += buf.getlength()
+ if offset < 0 or (buf.getlength() - offset) < size:
+ w_module = space.getbuiltinmodule('struct')
+ w_error = space.getattr(w_module, space.wrap('error'))
+ raise oefmt(w_error,
+ "unpack_from requires a buffer of at least %d bytes",
+ size)
+ data = buf.getslice(offset, offset + size, 1, size)
+ return unpack(space, format, data)
+
+
class W_Struct(W_Root):
_immutable_fields_ = ["format", "size"]
diff --git a/pypy/module/struct/test/test_struct.py b/pypy/module/struct/test/test_struct.py
--- a/pypy/module/struct/test/test_struct.py
+++ b/pypy/module/struct/test/test_struct.py
@@ -2,7 +2,6 @@
Tests for the struct module implemented at interp-level in pypy/module/struct.
"""
-import py
from rpython.rlib.rstruct.nativefmttable import native_is_bigendian
@@ -26,7 +25,6 @@
"""
assert issubclass(self.struct.error, Exception)
-
def test_calcsize_standard(self):
"""
Check the standard size of the various format characters.
@@ -52,14 +50,12 @@
# test with some repetitions and multiple format characters
assert calcsize('=bQ3i') == 1 + 8 + 3*4
-
def test_index(self):
class X(object):
def __index__(self):
return 3
assert self.struct.unpack("i", self.struct.pack("i", X()))[0] == 3
-
def test_pack_standard_little(self):
"""
Check packing with the '<' format specifier.
@@ -73,7 +69,6 @@
assert pack("<q", -0x41B2B3B4B5B6B7B8) == b'HHIJKLM\xbe'
assert pack("<Q", 0x8142434445464748) == b'HGFEDCB\x81'
-
def test_unpack_standard_little(self):
"""
Check unpacking with the '<' format specifier.
@@ -87,7 +82,6 @@
assert unpack("<q", b'HHIJKLM\xbe') == (-0x41B2B3B4B5B6B7B8,)
assert unpack("<Q", b'HGFEDCB\x81') == (0x8142434445464748,)
-
def test_pack_standard_big(self):
"""
Check packing with the '>' format specifier.
@@ -101,7 +95,6 @@
assert pack(">q", -0x41B2B3B4B5B6B7B8) == b'\xbeMLKJIHH'
assert pack(">Q", 0x8142434445464748) == b'\x81BCDEFGH'
-
def test_unpack_standard_big(self):
"""
Check unpacking with the '>' format specifier.
@@ -115,7 +108,6 @@
assert unpack(">q", b'\xbeMLKJIHH') == (-0x41B2B3B4B5B6B7B8,)
assert unpack(">Q", b'\x81BCDEFGH') == (0x8142434445464748,)
-
def test_calcsize_native(self):
"""
Check that the size of the various format characters is reasonable.
@@ -145,7 +137,6 @@
assert calcsize('ibb') == calcsize('i') + 2 * calcsize('b')
assert calcsize('ih') == calcsize('i') + calcsize('h')
-
def test_pack_native(self):
"""
Check packing with the native format.
@@ -163,7 +154,6 @@
assert res[sizeofi:] == b'\x05' + b'\x00' * (sizeofi-1)
assert pack("q", -1) == b'\xff' * calcsize("q")
-
def test_unpack_native(self):
"""
Check unpacking with the native format.
@@ -174,7 +164,6 @@
assert unpack("bi", pack("bi", -2, 5)) == (-2, 5)
assert unpack("q", b'\xff' * calcsize("q")) == (-1,)
-
def test_string_format(self):
"""
Check the 's' format character.
@@ -189,7 +178,6 @@
assert unpack("5s3s", b"worldspa") == (b"world", b"spa")
assert unpack("0s", b"") == (b"",)
-
def test_pascal_format(self):
"""
Check the 'p' format character.
@@ -209,7 +197,6 @@
assert unpack("1p", b"\x03") == (b"",)
assert unpack("300p", longpacked300) == (longstring[:255],)
-
def test_char_format(self):
"""
Check the 'c' format character.
@@ -221,7 +208,6 @@
assert unpack("c", b"?") == (b"?",)
assert unpack("5c", b"a\xc0\x00\n-") == (b"a", b"\xc0", b"\x00", b"\n", b"-")
-
def test_pad_format(self):
"""
Check the 'x' format character.
@@ -233,7 +219,6 @@
assert unpack("x", b"?") == ()
assert unpack("5x", b"hello") == ()
-
def test_native_floats(self):
"""
Check the 'd' and 'f' format characters on native packing.
@@ -250,7 +235,6 @@
assert res != 12.34 # precision lost
assert abs(res - 12.34) < 1E-6
-
def test_standard_floats(self):
"""
Check the 'd' and 'f' format characters on standard packing.
@@ -269,7 +253,6 @@
def test_bool(self):
pack = self.struct.pack
- unpack = self.struct.unpack
assert pack("!?", True) == b'\x01'
assert pack(">?", True) == b'\x01'
assert pack("!?", False) == b'\x00'
@@ -332,15 +315,12 @@
raises(error, pack, "b", 150) # argument out of range
# XXX the accepted ranges still differs between PyPy and CPython
-
def test_overflow_error(self):
"""
Check OverflowError cases.
"""
import sys
calcsize = self.struct.calcsize
- pack = self.struct.pack
- unpack = self.struct.unpack
someerror = (OverflowError, self.struct.error)
raises(someerror, calcsize, "%dc" % (sys.maxsize+1,))
raises(someerror, calcsize, "999999999999999999999999999c")
@@ -349,7 +329,6 @@
raises(someerror, calcsize, "c%dc" % (sys.maxsize,))
raises(someerror, calcsize, "%dci" % (sys.maxsize,))
-
def test_unicode(self):
"""
A PyPy extension: accepts the 'u' format character in native mode,
@@ -365,7 +344,6 @@
assert data == b'X\x00\x00\x00Y\x00\x00\x00Z\x00\x00\x00'
assert self.struct.unpack("uuu", data) == ('X', 'Y', 'Z')
-
def test_unpack_memoryview(self):
"""
memoryview objects can be passed to struct.unpack().
@@ -374,6 +352,36 @@
assert self.struct.unpack("ii", b) == (62, 12)
raises(self.struct.error, self.struct.unpack, "i", b)
+ def test_pack_unpack_buffer(self):
+ import array
+ b = array.array('c', '\x00' * 19)
+ sz = self.struct.calcsize("ii")
+ for offset in [2, -17]:
+ self.struct.pack_into("ii", b, offset, 17, 42)
+ assert str(buffer(b)) == ('\x00' * 2 +
+ self.struct.pack("ii", 17, 42) +
+ '\x00' * (19-sz-2))
+ exc = raises(TypeError, self.struct.pack_into, "ii", buffer(b), 0, 17, 42)
+ assert str(exc.value) == "buffer is read-only"
+ exc = raises(TypeError, self.struct.pack_into, "ii", 'test', 0, 17, 42)
+ assert str(exc.value) == "Cannot use string as modifiable buffer"
+ exc = raises(self.struct.error, self.struct.pack_into, "ii", b[0:1], 0, 17, 42)
+ assert str(exc.value) == "pack_into requires a buffer of at least 8 bytes"
+
+ assert self.struct.unpack_from("ii", b, 2) == (17, 42)
+ assert self.struct.unpack_from("ii", b, -17) == (17, 42)
+ assert self.struct.unpack_from("ii", buffer(b, 2)) == (17, 42)
+ assert self.struct.unpack_from("ii", buffer(b), 2) == (17, 42)
+ assert self.struct.unpack_from("ii", memoryview(buffer(b)), 2) == (17, 42)
+ exc = raises(TypeError, self.struct.unpack_from, "ii", 123)
+ assert 'must be string or buffer, not int' in str(exc.value)
+ exc = raises(self.struct.error, self.struct.unpack_from, "ii", None)
+ assert str(exc.value) == "unpack_from requires a buffer argument"
+ exc = raises(self.struct.error, self.struct.unpack_from, "ii", '')
+ assert str(exc.value) == "unpack_from requires a buffer of at least 8 bytes"
+ exc = raises(self.struct.error, self.struct.unpack_from, "ii", memoryview(''))
+ assert str(exc.value) == "unpack_from requires a buffer of at least 8 bytes"
+
def test___float__(self):
class MyFloat(object):
def __init__(self, x):
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
@@ -4,6 +4,7 @@
from pypy.interpreter.typedef import TypeDef, GetSetProperty
from pypy.objspace.std.stdtypedef import StdTypeDef
from pypy.objspace.std.sliceobject import W_SliceObject
+from rpython.rlib.buffer import StringBuffer
from rpython.rlib.objectmodel import instantiate, we_are_translated, specialize
from rpython.rlib.nonconst import NonConstant
from rpython.rlib.rarithmetic import r_uint, r_singlefloat
@@ -39,6 +40,9 @@
def setclass(self, space, w_subtype):
is_root(w_subtype)
+ def buffer_w(self, space, flags):
+ return StringBuffer("foobar")
+
def str_w(self, space):
return NonConstant("foobar")
identifier_w = bytes_w = str_w
@@ -70,6 +74,9 @@
def get_module(self):
return w_some_obj()
+ def get_module_type_name(self):
+ return self.name
+
def w_some_obj():
if NonConstant(False):
return W_Root()
@@ -305,11 +312,6 @@
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/bufferobject.py b/pypy/objspace/std/bufferobject.py
new file mode 100644
--- /dev/null
+++ b/pypy/objspace/std/bufferobject.py
@@ -0,0 +1,159 @@
+"""
+Implementation of the 'buffer' and 'memoryview' types.
+"""
+import operator
+
+from rpython.rlib.buffer import Buffer, StringBuffer, SubBuffer
+from pypy.interpreter.baseobjspace import W_Root
More information about the pypy-commit
mailing list