Author: Armin Rigo <[email protected]>
Branch: py3k
Changeset: r86590:fbf9c57aa038
Date: 2016-08-27 09:46 +0200
http://bitbucket.org/pypy/pypy/changeset/fbf9c57aa038/
Log: Backport memoryview.cast(), fix getitem
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
@@ -17,6 +17,7 @@
"""Implement the built-in 'memoryview' type as a wrapper around
an interp-level buffer.
"""
+ _immutable_fields_ = ['format', 'itemsize']
def __init__(self, buf, format='B', itemsize=1):
assert isinstance(buf, Buffer)
@@ -62,8 +63,7 @@
def as_str(self):
buf = self.buf
- n_bytes = buf.getlength()
- return buf.getslice(0, n_bytes, 1, n_bytes)
+ return buf.as_str()
def getlength(self):
return self.buf.getlength() // self.itemsize
@@ -82,27 +82,24 @@
def descr_getitem(self, space, w_index):
self._check_released(space)
start, stop, step, size = space.decode_index4(w_index,
self.getlength())
- itemsize = self.buf.getitemsize()
- if itemsize > 1:
- start *= itemsize
- size *= itemsize
- stop = start + size
- if step == 0:
- step = 1
- if stop > self.getlength():
- raise oefmt(space.w_IndexError, 'index out of range')
+ # ^^^ for a non-slice index, this returns (index, 0, 0, 1)
+ itemsize = self.itemsize
if step == 0: # index only
- # TODO: this probably isn't very fast
- buf = SubBuffer(self.buf, start, self.itemsize)
- fmtiter = UnpackFormatIterator(space, buf)
- fmtiter.interpret(self.format)
- return fmtiter.result_w[0]
+ if itemsize == 1:
+ ch = self.buf.getitem(start)
+ return space.newint(ord(ch))
+ else:
+ # TODO: this probably isn't very fast
+ buf = SubBuffer(self.buf, start * itemsize, itemsize)
+ fmtiter = UnpackFormatIterator(space, buf)
+ fmtiter.interpret(self.format)
+ return fmtiter.result_w[0]
elif step == 1:
- buf = SubBuffer(self.buf, start, size)
- return W_MemoryView(buf, self.format, self.itemsize)
+ buf = SubBuffer(self.buf, start * itemsize, size * itemsize)
+ return W_MemoryView(buf, self.format, itemsize)
else:
- buf = SubBuffer(self.buf, start, size)
- return W_MemoryView(buf)
+ raise oefmt(space.w_NotImplementedError,
+ "XXX extended slicing")
def descr_setitem(self, space, w_index, w_obj):
self._check_released(space)
@@ -141,7 +138,7 @@
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)
@@ -214,6 +211,44 @@
raise OperationError(space.w_ValueError, space.wrap(msg))
return space.wrap(rffi.cast(lltype.Signed, ptr))
+ def get_native_fmtchar(self, fmt):
+ from rpython.rtyper.lltypesystem import rffi
+ size = -1
+ if fmt[0] == '@':
+ f = fmt[1]
+ else:
+ f = fmt[0]
+ if f == 'c' or f == 'b' or f == 'B':
+ size = rffi.sizeof(rffi.CHAR)
+ elif f == 'h' or f == 'H':
+ size = rffi.sizeof(rffi.SHORT)
+ elif f == 'i' or f == 'I':
+ size = rffi.sizeof(rffi.INT)
+ elif f == 'l' or f == 'L':
+ size = rffi.sizeof(rffi.LONG)
+ elif f == 'q' or f == 'Q':
+ size = rffi.sizeof(rffi.LONGLONG)
+ elif f == 'n' or f == 'N':
+ size = rffi.sizeof(rffi.SIZE_T)
+ elif f == 'f':
+ size = rffi.sizeof(rffi.FLOAT)
+ elif f == 'd':
+ size = rffi.sizeof(rffi.DOUBLE)
+ elif f == '?':
+ size = rffi.sizeof(rffi.CHAR)
+ elif f == 'P':
+ size = rffi.sizeof(rffi.VOIDP)
+ return size
+
+ def descr_cast(self, space, w_format, w_shape=None):
+ self._check_released(space)
+ if not space.is_none(w_shape):
+ raise oefmt(space.w_NotImplementedError,
+ "XXX cast() with a shape")
+ fmt = space.str_w(w_format)
+ newitemsize = self.get_native_fmtchar(fmt)
+ return W_MemoryView(self.buf, fmt, newitemsize)
+
W_MemoryView.typedef = TypeDef(
"memoryview",
__doc__ = """\
@@ -230,6 +265,7 @@
__enter__ = interp2app(W_MemoryView.descr_enter),
__exit__ = interp2app(W_MemoryView.descr_exit),
__weakref__ = make_weakref_descr(W_MemoryView),
+ cast = interp2app(W_MemoryView.descr_cast),
tobytes = interp2app(W_MemoryView.descr_tobytes),
tolist = interp2app(W_MemoryView.descr_tolist),
release = interp2app(W_MemoryView.descr_release),
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
@@ -16,8 +16,6 @@
w = v[1:234]
assert isinstance(w, memoryview)
assert len(w) == 2
- exc = raises(NotImplementedError, "v[0:2:2]")
- assert str(exc.value) == ""
def test_rw(self):
data = bytearray(b'abcefg')
@@ -31,8 +29,15 @@
assert data == bytearray(eval("b'23f3fg'"))
exc = raises(ValueError, "v[2:3] = b'spam'")
assert str(exc.value) == "cannot modify size of memoryview object"
- exc = raises(NotImplementedError, "v[0:2:2] = b'spam'")
- assert str(exc.value) == ""
+
+ def test_extended_slice(self):
+ data = bytearray(b'abcefg')
+ v = memoryview(data)
+ w = v[0:2:2] # failing for now: NotImplementedError
+ assert len(w) == 1
+ assert list(w) == [97]
+ v[::2] = b'ABC'
+ assert data == bytearray(b'AbBeCg')
def test_memoryview_attrs(self):
v = memoryview(b"a"*100)
@@ -161,3 +166,33 @@
raises(ValueError, memoryview(b"foobar")._pypy_raw_address)
a = memoryview(bytearray(b"foobar"))._pypy_raw_address()
assert a != 0
+
+ def test_memoryview_cast(self):
+ m1 = memoryview(b'abcdefgh')
+ m2 = m1.cast('I')
+ m3 = m1.cast('h')
+ assert list(m1) == [97, 98, 99, 100, 101, 102, 103, 104]
+ assert list(m2) == [1684234849, 1751606885]
+ assert list(m3) == [25185, 25699, 26213, 26727]
+ assert m1[1] == 98
+ assert m2[1] == 1751606885
+ assert m3[1] == 25699
+ assert list(m3[1:3]) == [25699, 26213]
+ assert m3[1:3].tobytes() == b'cdef'
+ assert len(m2) == 2
+ assert len(m3) == 4
+ assert (m2[-2], m2[-1]) == (1684234849, 1751606885)
+ raises(IndexError, "m2[2]")
+ raises(IndexError, "m2[-3]")
+ assert list(m3[-99:3]) == [25185, 25699, 26213]
+ assert list(m3[1:99]) == [25699, 26213, 26727]
+ raises(IndexError, "m1[8]")
+ raises(IndexError, "m1[-9]")
+ assert m1[-8] == 97
+
+ def test_memoryview_cast_extended_slicing(self):
+ m1 = memoryview(b'abcdefgh')
+ m3 = m1.cast('h')
+ assert m3[1::2].tobytes() == b'cdgh'
+ assert m3[::2].tobytes() == b'abef'
+ assert m3[:2:2].tobytes() == b'ab'
diff --git a/rpython/rlib/buffer.py b/rpython/rlib/buffer.py
--- a/rpython/rlib/buffer.py
+++ b/rpython/rlib/buffer.py
@@ -10,6 +10,7 @@
_immutable_ = True
def getlength(self):
+ """Returns the size in bytes (even if getitemsize() > 1)."""
raise NotImplementedError
def __len__(self):
_______________________________________________
pypy-commit mailing list
[email protected]
https://mail.python.org/mailman/listinfo/pypy-commit