Author: Manuel Jacob
Branch: py3k
Changeset: r61895:11b581d8503f
Date: 2013-03-01 12:54 +0100
http://bitbucket.org/pypy/pypy/changeset/11b581d8503f/
Log: Implement release() and context manager protocol on memoryview.
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
@@ -20,6 +20,8 @@
def _make_descr__cmp(name):
def descr__cmp(self, space, w_other):
other = space.interpclass_w(w_other)
+ if self.buf is None:
+ return space.wrap(getattr(operator, name)(self, other))
if isinstance(other, W_MemoryView):
# xxx not the most efficient implementation
str1 = self.as_str()
@@ -66,12 +68,15 @@
not in CPython; but CPython supports passing memoryview() to most
built-in functions that accept buffers, with the notable exception
of the buffer() built-in."""
+ self._check_released(space)
return space.wrap(self.buf)
def descr_tobytes(self, space):
+ self._check_released(space)
return space.wrapbytes(self.as_str())
def descr_tolist(self, space):
+ self._check_released(space)
buf = self.buf
result = []
for i in range(buf.getlength()):
@@ -79,6 +84,7 @@
return space.newlist(result)
def descr_getitem(self, space, w_index):
+ self._check_released(space)
start, stop, step = space.decode_index(w_index, self.getlength())
if step == 0: # index only
return space.wrapbytes(self.buf.getitem(start))
@@ -92,6 +98,7 @@
@unwrap_spec(newstring='bufferstr')
def descr_setitem(self, space, w_index, newstring):
+ self._check_released(space)
buf = self.buf
if isinstance(buf, buffer.RWBuffer):
buf.descr_setitem(space, w_index, newstring)
@@ -100,26 +107,53 @@
space.wrap("cannot modify read-only memory"))
def descr_len(self, space):
+ self._check_released(space)
return self.buf.descr_len(space)
def w_get_format(self, space):
+ self._check_released(space)
return space.wrap("B")
def w_get_itemsize(self, space):
+ self._check_released(space)
return space.wrap(1)
def w_get_ndim(self, space):
+ self._check_released(space)
return space.wrap(1)
def w_is_readonly(self, space):
+ self._check_released(space)
return space.wrap(not isinstance(self.buf, buffer.RWBuffer))
def w_get_shape(self, space):
+ self._check_released(space)
return space.newtuple([space.wrap(self.getlength())])
def w_get_strides(self, space):
+ self._check_released(space)
return space.newtuple([space.wrap(1)])
def w_get_suboffsets(self, space):
+ self._check_released(space)
# I've never seen anyone filling this field
return space.w_None
def descr_repr(self, space):
- return self.getrepr(space, 'memory')
+ if self.buf is None:
+ return self.getrepr(space, 'released memory')
+ else:
+ return self.getrepr(space, 'memory')
+
+ def descr_release(self, space):
+ self.buf = None
+
+ def _check_released(self, space):
+ if self.buf is None:
+ raise OperationError(space.w_ValueError, space.wrap(
+ "operation forbidden on released memoryview object"))
+
+ def descr_enter(self, space):
+ self._check_released(space)
+ return self
+
+ def descr_exit(self, space, __args__):
+ self.buf = None
+ return space.w_None
def descr_new(space, w_subtype, w_object):
@@ -139,8 +173,11 @@
__ne__ = interp2app(W_MemoryView.descr_ne),
__setitem__ = interp2app(W_MemoryView.descr_setitem),
__repr__ = interp2app(W_MemoryView.descr_repr),
+ __enter__ = interp2app(W_MemoryView.descr_enter),
+ __exit__ = interp2app(W_MemoryView.descr_exit),
tobytes = interp2app(W_MemoryView.descr_tobytes),
tolist = interp2app(W_MemoryView.descr_tolist),
+ release = interp2app(W_MemoryView.descr_release),
format = GetSetProperty(W_MemoryView.w_get_format),
itemsize = GetSetProperty(W_MemoryView.w_get_itemsize),
ndim = GetSetProperty(W_MemoryView.w_get_ndim),
diff --git a/pypy/module/__builtin__/test/test_buffer.py
b/pypy/module/__builtin__/test/test_buffer.py
--- a/pypy/module/__builtin__/test/test_buffer.py
+++ b/pypy/module/__builtin__/test/test_buffer.py
@@ -80,3 +80,31 @@
def test_suboffsets(self):
v = memoryview(b"a"*100)
assert v.suboffsets == None
+
+ def test_release(self):
+ v = memoryview(b"a"*100)
+ v.release()
+ raises(ValueError, len, v)
+ raises(ValueError, v.tolist)
+ raises(ValueError, v.tobytes)
+ raises(ValueError, "v[0]")
+ raises(ValueError, "v[0] = b'a'")
+ raises(ValueError, "v.format")
+ raises(ValueError, "v.itemsize")
+ raises(ValueError, "v.ndim")
+ raises(ValueError, "v.readonly")
+ raises(ValueError, "v.shape")
+ raises(ValueError, "v.strides")
+ raises(ValueError, "v.suboffsets")
+ raises(ValueError, "with v as cm: pass")
+ raises(ValueError, "memoryview(v)")
+ assert v == v
+ assert v != memoryview(b"a"*100)
+ assert v != b"a"*100
+ assert "released memory" in repr(v)
+
+ def test_context_manager(self):
+ v = memoryview(b"a"*100)
+ with v as cm:
+ assert cm is v
+ assert "released memory" in repr(v)
_______________________________________________
pypy-commit mailing list
[email protected]
http://mail.python.org/mailman/listinfo/pypy-commit