[pypy-commit] pypy py3k: hg merge py3k-memoryview
mjacob
noreply at buildbot.pypy.org
Wed Feb 25 17:06:41 CET 2015
Author: Manuel Jacob <me at manueljacob.de>
Branch: py3k
Changeset: r76139:1091e0c8103b
Date: 2015-02-25 16:52 +0100
http://bitbucket.org/pypy/pypy/changeset/1091e0c8103b/
Log: hg merge py3k-memoryview
This fixes issue #1542.
diff --git a/lib-python/3/test/test_memoryview.py b/lib-python/3/test/test_memoryview.py
--- a/lib-python/3/test/test_memoryview.py
+++ b/lib-python/3/test/test_memoryview.py
@@ -50,7 +50,6 @@
m = None
self.assertEqual(getrefcount(b), oldrefcount)
- @unittest.skip('XXX: https://bugs.pypy.org/issue1542')
def test_getitem(self):
for tp in self._types:
self.check_getitem_with_type(tp)
@@ -75,7 +74,6 @@
m = None
self.assertEqual(getrefcount(b), oldrefcount)
- @unittest.skip('XXX: https://bugs.pypy.org/issue1542')
def test_setitem_writable(self):
if not self.rw_type:
return
@@ -128,7 +126,6 @@
with self.assertRaises(TypeError):
del m[1:4]
- @unittest.skip('XXX: https://bugs.pypy.org/issue1542')
def test_tobytes(self):
for tp in self._types:
m = self._view(tp(self._source))
@@ -145,7 +142,6 @@
l = m.tolist()
self.assertEqual(l, list(b"abcdef"))
- @unittest.skip('XXX: https://bugs.pypy.org/issue1542')
def test_compare(self):
# memoryviews can compare for equality with other objects
# having the buffer interface.
@@ -193,7 +189,6 @@
m = self.check_attributes_with_type(self.ro_type)
self.assertEqual(m.readonly, True)
- @unittest.skip('XXX: https://bugs.pypy.org/issue1542')
def test_attributes_writable(self):
if not self.rw_type:
return
diff --git a/pypy/interpreter/baseobjspace.py b/pypy/interpreter/baseobjspace.py
--- a/pypy/interpreter/baseobjspace.py
+++ b/pypy/interpreter/baseobjspace.py
@@ -25,6 +25,29 @@
reds=['items', 'w_iterator'])
+# It seems there's no way to do it without top-level-functions.
+
+ at specialize.memo()
+def _does_override_buffer_w(type):
+ return type.buffer_w != W_Root.buffer_w
+
+ at specialize.memo()
+def _does_override_buffer_w_ex(type):
+ return type.buffer_w_ex != W_Root.buffer_w_ex
+
+ at specialize.argtype(0)
+def W_Root_buffer_w(self, space, flags):
+ if _does_override_buffer_w_ex(self.__class__):
+ return self.buffer_w_ex(space, flags)[0]
+ return self._buffer(space, flags).buffer_w(space, flags)
+
+ at specialize.argtype(0)
+def W_Root_buffer_w_ex(self, space, flags):
+ if _does_override_buffer_w(self.__class__):
+ return self.buffer_w(space, flags), 'B', 1
+ return self._buffer(space, flags).buffer_w_ex(space, flags)
+
+
class W_Root(object):
"""This is the abstract root class of all wrapped objects that live
in a 'normal' object space like StdObjSpace."""
@@ -195,11 +218,17 @@
return None
def buffer_w(self, space, flags):
+ return W_Root_buffer_w(self, space, flags)
+
+ def buffer_w_ex(self, space, flags):
+ return W_Root_buffer_w_ex(self, space, flags)
+
+ def _buffer(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, flags)
+ return w_result
raise TypeError
def bytes_w(self, space):
@@ -1368,6 +1397,15 @@
raise oefmt(self.w_TypeError,
"'%T' does not support the buffer interface", w_obj)
+ def buffer_w_ex(self, w_obj, flags):
+ # New buffer interface, returns a buffer based on flags (PyObject_GetBuffer)
+ # Returns extra information: (buffer, typecode, itemsize)
+ try:
+ return w_obj.buffer_w_ex(self, flags)
+ except TypeError:
+ raise oefmt(self.w_TypeError,
+ "'%T' does not support the buffer interface", w_obj)
+
def readbuf_w(self, w_obj):
# Old buffer interface, returns a readonly buffer (PyObject_AsReadBuffer)
try:
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
@@ -3,7 +3,6 @@
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.memoryobject import _buffer_setitem
from rpython.rlib.buffer import Buffer
from rpython.rtyper.annlowlevel import llstr
@@ -41,8 +40,6 @@
copy_string_to_raw(llstr(string), raw_cdata, 0, len(string))
-# Override the typedef to narrow down the interface that's exposed to app-level
-
class MiniBuffer(W_Root):
def __init__(self, buffer, keepalive=None):
self.buffer = buffer
@@ -63,7 +60,18 @@
return space.wrapbytes(res)
def descr_setitem(self, space, w_index, w_newstring):
- _buffer_setitem(space, self.buffer, w_index, w_newstring)
+ start, stop, step, size = space.decode_index4(w_index,
+ self.buffer.getlength())
+ if step not in (0, 1):
+ raise oefmt(space.w_NotImplementedError, "")
+ value = space.buffer_w(w_newstring, space.BUF_CONTIG_RO)
+ if value.getlength() != size:
+ raise oefmt(space.w_ValueError,
+ "cannot modify size of memoryview object")
+ if step == 0: # index only
+ self.buffer.setitem(start, value.getitem(0))
+ elif step == 1:
+ self.buffer.setslice(start, value.as_str())
MiniBuffer.typedef = TypeDef(
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
@@ -59,10 +59,12 @@
def descr_itemsize(space, self):
+ assert isinstance(self, W_ArrayBase)
return space.wrap(self.itemsize)
def descr_typecode(space, self):
+ assert isinstance(self, W_ArrayBase)
return space.wrap(self.typecode)
arr_eq_driver = jit.JitDriver(name='array_eq_driver', greens=['comp_func'],
@@ -135,8 +137,8 @@
self.len = 0
self.allocated = 0
- def buffer_w(self, space, flags):
- return ArrayBuffer(self, False)
+ def buffer_w_ex(self, space, flags):
+ return ArrayBuffer(self, False), self.typecode, self.itemsize
def descr_append(self, space, w_x):
""" append(x)
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
@@ -411,7 +411,16 @@
def test_buffer(self):
a = self.array('h', b'Hi')
buf = memoryview(a)
- assert buf[1] == b'i'
+ assert buf[0] == b'Hi'
+ raises(IndexError, 'buf[1]')
+ assert buf.tobytes() == b'Hi'
+ #assert buf.tolist() == [26952]
+ assert buf.format == 'h'
+ assert buf.itemsize == 2
+ assert buf.shape == (1,)
+ assert buf.ndim == 1
+ assert buf.strides == (2,)
+ assert not buf.readonly
def test_buffer_write(self):
a = self.array('b', b'hello')
@@ -431,6 +440,11 @@
a.fromstring(b'some extra text')
assert buf[:] == b'foobarbazsome extra text'
+ def test_memview_multi_tobytes(self):
+ a = self.array('i', list(b"abcdef"))
+ m = memoryview(a)
+ assert m.tobytes() == a.tobytes()
+
def test_list_methods(self):
assert repr(self.array('i')) == "array('i')"
assert repr(self.array('i', [1, 2, 3])) == "array('i', [1, 2, 3])"
diff --git a/pypy/module/cpyext/bytesobject.py b/pypy/module/cpyext/bytesobject.py
--- a/pypy/module/cpyext/bytesobject.py
+++ b/pypy/module/cpyext/bytesobject.py
@@ -255,5 +255,3 @@
return w_obj
buffer = space.buffer_w(w_obj, space.BUF_FULL_RO)
return space.wrapbytes(buffer.as_str())
-
-
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
@@ -633,6 +633,7 @@
"ctypes not implemented yet"))
def buffer_w(self, space, flags):
+ # XXX format isn't always 'B' probably
return self.implementation.get_buffer(space, True)
def descr_get_data(self, space):
diff --git a/pypy/objspace/std/memoryobject.py b/pypy/objspace/std/memoryobject.py
--- a/pypy/objspace/std/memoryobject.py
+++ b/pypy/objspace/std/memoryobject.py
@@ -10,39 +10,25 @@
from pypy.interpreter.typedef import TypeDef, GetSetProperty
-def _buffer_setitem(space, buf, w_index, w_obj):
- if buf.readonly:
- raise oefmt(space.w_TypeError, "cannot modify read-only memory")
- start, stop, step, size = space.decode_index4(w_index, buf.getlength())
- if step not in (0, 1):
- raise oefmt(space.w_NotImplementedError, "")
- value = space.buffer_w(w_obj, space.BUF_CONTIG_RO)
- if value.getlength() != size:
- raise oefmt(space.w_ValueError,
- "cannot modify size of memoryview object")
- if step == 0: # index only
- buf.setitem(start, value.getitem(0))
- elif step == 1:
- buf.setslice(start, value.as_str())
-
-
class W_MemoryView(W_Root):
"""Implement the built-in 'memoryview' type as a wrapper around
an interp-level buffer.
"""
- def __init__(self, buf):
+ def __init__(self, buf, format='B', itemsize=1):
assert isinstance(buf, Buffer)
self.buf = buf
+ self.format = format
+ self.itemsize = itemsize
- def buffer_w(self, space, flags):
+ def buffer_w_ex(self, space, flags):
self._check_released(space)
space.check_buf_flags(flags, self.buf.readonly)
- return self.buf
+ return self.buf, self.format, self.itemsize
@staticmethod
def descr_new_memoryview(space, w_subtype, w_object):
- return W_MemoryView(space.buffer_w(w_object, space.BUF_FULL_RO))
+ return W_MemoryView(*space.buffer_w_ex(w_object, space.BUF_FULL_RO))
def _make_descr__cmp(name):
def descr__cmp(self, space, w_other):
@@ -71,10 +57,12 @@
descr_ne = _make_descr__cmp('ne')
def as_str(self):
- return self.buf.as_str()
+ buf = self.buf
+ n_bytes = buf.getlength()
+ return buf.getslice(0, n_bytes, 1, n_bytes)
def getlength(self):
- return self.buf.getlength()
+ return self.buf.getlength() // self.itemsize
def descr_tobytes(self, space):
self._check_released(space)
@@ -83,9 +71,12 @@
def descr_tolist(self, space):
self._check_released(space)
buf = self.buf
+ if self.format != 'B':
+ raise oefmt(space.w_NotImplementedError,
+ "tolist() only supports byte views")
result = []
for i in range(buf.getlength()):
- result.append(space.wrap(ord(buf.getitem(i))))
+ result.append(space.wrap(ord(buf.getitem(i)[0])))
return space.newlist(result)
def descr_getitem(self, space, w_index):
@@ -94,26 +85,39 @@
if step not in (0, 1):
raise oefmt(space.w_NotImplementedError, "")
if step == 0: # index only
- return space.wrapbytes(self.buf.getitem(start))
+ a = start * self.itemsize
+ b = a + self.itemsize
+ return space.wrapbytes(
+ ''.join([self.buf.getitem(i) for i in range(a, b)]))
else:
- buf = SubBuffer(self.buf, start, size)
- return W_MemoryView(buf)
+ buf = SubBuffer(self.buf, start * self.itemsize,
+ size * self.itemsize)
+ return W_MemoryView(buf, self.format, self.itemsize)
def descr_setitem(self, space, w_index, w_obj):
self._check_released(space)
- _buffer_setitem(space, self.buf, w_index, w_obj)
+ if self.buf.readonly:
+ raise oefmt(space.w_TypeError, "cannot modify read-only memory")
+ start, stop, step, size = space.decode_index4(w_index, self.getlength())
+ if step not in (0, 1):
+ raise oefmt(space.w_NotImplementedError, "")
+ value = space.buffer_w(w_obj, space.BUF_CONTIG_RO)
+ if value.getlength() != size * self.itemsize:
+ raise oefmt(space.w_ValueError,
+ "cannot modify size of memoryview object")
+ self.buf.setslice(start * self.itemsize, value.as_str())
def descr_len(self, space):
self._check_released(space)
- return space.wrap(self.buf.getlength())
+ return space.wrap(self.getlength())
def w_get_format(self, space):
self._check_released(space)
- return space.wrap("B")
+ return space.wrap(self.format)
def w_get_itemsize(self, space):
self._check_released(space)
- return space.wrap(1)
+ return space.wrap(self.itemsize)
def w_get_ndim(self, space):
self._check_released(space)
@@ -129,7 +133,7 @@
def w_get_strides(self, space):
self._check_released(space)
- return space.newtuple([space.wrap(1)])
+ return space.newtuple([space.wrap(self.itemsize)])
def w_get_suboffsets(self, space):
self._check_released(space)
@@ -147,8 +151,8 @@
def _check_released(self, space):
if self.buf is None:
- raise OperationError(space.w_ValueError, space.wrap(
- "operation forbidden on released memoryview object"))
+ raise oefmt(space.w_ValueError,
+ "operation forbidden on released memoryview object")
def descr_enter(self, space):
self._check_released(space)
diff --git a/pypy/objspace/std/test/test_memoryobject.py b/pypy/objspace/std/test/test_memoryobject.py
--- a/pypy/objspace/std/test/test_memoryobject.py
+++ b/pypy/objspace/std/test/test_memoryobject.py
@@ -128,8 +128,31 @@
raises(ValueError, bytes, v)
assert "released memory" in repr(v)
+ def test_int_array_buffer(self):
+ import array
+ m = memoryview(array.array('i', list(range(10))))
+ assert m.format == 'i'
+ assert m.itemsize == 4
+ assert len(m) == 10
+ assert len(m.tobytes()) == 40
+ assert m[0] == b'\x00\x00\x00\x00'
+ m[0] = b'\x00\x00\x00\x01'
+ assert m[0] == b'\x00\x00\x00\x01'
+
+ def test_int_array_slice(self):
+ import array
+ m = memoryview(array.array('i', list(range(10))))
+ slice = m[2:8]
+ assert slice.format == 'i'
+ assert slice.itemsize == 4
+ assert len(slice) == 6
+ assert len(slice.tobytes()) == 24
+ assert slice[0] in (b'\x00\x00\x00\x02', b'\x02\x00\x00\x00')
+ slice[0] = b'\x00\x00\x00\x01'
+ assert slice[0] == b'\x00\x00\x00\x01'
+ assert m[2] == b'\x00\x00\x00\x01'
+
def test_pypy_raw_address_base(self):
raises(ValueError, memoryview(b"foobar")._pypy_raw_address)
e = raises(ValueError, memoryview(bytearray(b"foobar"))._pypy_raw_address)
assert 'BytearrayBuffer' in str(e.value)
-
More information about the pypy-commit
mailing list