[pypy-commit] pypy ndarray-buffer: raise ValueError if we try to write to a mmapped array which is ready-only
antocuni
noreply at buildbot.pypy.org
Mon Dec 2 16:43:48 CET 2013
Author: Antonio Cuni <anto.cuni at gmail.com>
Branch: ndarray-buffer
Changeset: r68356:9c8634e4593f
Date: 2013-12-02 16:42 +0100
http://bitbucket.org/pypy/pypy/changeset/9c8634e4593f/
Log: raise ValueError if we try to write to a mmapped array which is
ready-only
diff --git a/pypy/interpreter/buffer.py b/pypy/interpreter/buffer.py
--- a/pypy/interpreter/buffer.py
+++ b/pypy/interpreter/buffer.py
@@ -47,6 +47,9 @@
def get_raw_address(self):
raise ValueError("no raw buffer")
+ def is_writable(self):
+ return False
+
# __________ app-level support __________
def descr_len(self, space):
@@ -135,6 +138,9 @@
__slots__ = () # no extra slot here
+ 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.
diff --git a/pypy/module/micronumpy/arrayimpl/concrete.py b/pypy/module/micronumpy/arrayimpl/concrete.py
--- a/pypy/module/micronumpy/arrayimpl/concrete.py
+++ b/pypy/module/micronumpy/arrayimpl/concrete.py
@@ -400,7 +400,14 @@
def base(self):
return self.orig_base
-
+
+
+class ConcreteNonWritableArrayWithBase(ConcreteArrayWithBase):
+ def descr_setitem(self, space, orig_array, w_index, w_value):
+ raise OperationError(space.w_ValueError, space.wrap(
+ "assignment destination is read-only"))
+
+
class NonWritableArray(ConcreteArray):
def descr_setitem(self, space, orig_array, w_index, w_value):
raise OperationError(space.w_ValueError, space.wrap(
diff --git a/pypy/module/micronumpy/base.py b/pypy/module/micronumpy/base.py
--- a/pypy/module/micronumpy/base.py
+++ b/pypy/module/micronumpy/base.py
@@ -50,7 +50,7 @@
@staticmethod
def from_shape_and_storage(space, shape, storage, dtype, order='C', owning=False,
- w_subtype=None, w_base=None):
+ w_subtype=None, w_base=None, writable=True):
from pypy.module.micronumpy.arrayimpl import concrete
assert shape
strides, backstrides = calc_strides(shape, dtype, order)
@@ -58,8 +58,14 @@
if owning:
raise OperationError(space.w_ValueError,
space.wrap("Cannot have owning=True when specifying a buffer"))
- impl = concrete.ConcreteArrayWithBase(shape, dtype, order, strides,
- backstrides, storage, w_base)
+ if writable:
+ impl = concrete.ConcreteArrayWithBase(shape, dtype, order, strides,
+ backstrides, storage, w_base)
+ else:
+ impl = concrete.ConcreteNonWritableArrayWithBase(shape, dtype, order,
+ strides, backstrides,
+ storage, w_base)
+
elif owning:
# Will free storage when GCd
impl = concrete.ConcreteArray(shape, dtype, order, strides,
diff --git a/pypy/module/micronumpy/interp_numarray.py b/pypy/module/micronumpy/interp_numarray.py
--- a/pypy/module/micronumpy/interp_numarray.py
+++ b/pypy/module/micronumpy/interp_numarray.py
@@ -1096,7 +1096,8 @@
storage = rffi.ptradd(storage, offset)
return W_NDimArray.from_shape_and_storage(space, shape, storage, dtype,
w_subtype=w_subtype,
- w_base=w_buffer)
+ w_base=w_buffer,
+ writable=buf.is_writable())
if not shape:
return W_NDimArray.new_scalar(space, dtype)
diff --git a/pypy/module/micronumpy/test/test_numarray.py b/pypy/module/micronumpy/test/test_numarray.py
--- a/pypy/module/micronumpy/test/test_numarray.py
+++ b/pypy/module/micronumpy/test/test_numarray.py
@@ -218,7 +218,8 @@
assert get(1, 1) == 3
class AppTestNumArray(BaseNumpyAppTest):
- spaceconfig = dict(usemodules=["micronumpy", "struct", "binascii", "array"])
+ spaceconfig = dict(usemodules=["micronumpy", "struct", "binascii"])
+
def w_CustomIndexObject(self, index):
class CustomIndexObject(object):
def __init__(self, index):
@@ -2087,6 +2088,15 @@
a = np.ndarray([1], dtype=bool)
assert a[0] == True
+
+class AppTestNumArrayFromBuffer(BaseNumpyAppTest):
+ spaceconfig = dict(usemodules=["micronumpy", "array", "mmap"])
+
+ def setup_class(cls):
+ from rpython.tool.udir import udir
+ BaseNumpyAppTest.setup_class.im_func(cls)
+ cls.w_tmpname = cls.space.wrap(str(udir.join('mmap-')))
+
def test_ndarray_from_buffer(self):
import numpypy as np
import array
@@ -2126,7 +2136,19 @@
assert str(info.value).startswith('buffer is too small')
info = raises(TypeError, "np.ndarray((5,), buffer=buf, offset=15, dtype='i2')")
assert str(info.value).startswith('buffer is too small')
-
+
+ def test_ndarray_from_readonly_buffer(self):
+ import numpypy as np
+ from mmap import mmap, ACCESS_READ
+ f = open(self.tmpname, "w+")
+ f.write("hello")
+ f.flush()
+ buf = mmap(f.fileno(), 5, access=ACCESS_READ)
+ a = np.ndarray((5,), buffer=buf, dtype='c')
+ raises(ValueError, "a[0] = 'X'")
+ buf.close()
+ f.close()
+
class AppTestMultiDim(BaseNumpyAppTest):
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
@@ -314,6 +314,14 @@
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
More information about the pypy-commit
mailing list