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

Reply via email to