Repository: numba/numba

Issue:
Need to respect the ndarray.flags.writeable flag
Numba allows writes to arrays that have the writeable flag set to False.  This code:

``` python
@numba.jit(nopython=True)
def write_test(x):
    x[1] = 20

a = np.arange(5)
a.flags.writeable = False
write_test(a)
print(a)
```

prints this:

```
[ 0 20  2  3  4]
```

This should raise a compilation error, if possible.  (Presumably, this means that we need a read only array type.)



Discussion:

Resolving patch:
diff --git a/numba/typing/builtins.py b/numba/typing/builtins.py
--- a/numba/typing/builtins.py
+++ b/numba/typing/builtins.py
@@ -501,7 +501,7 @@ def generic(self, args, kws):
         ary, idx, val = args
         if isinstance(ary, types.Buffer):
             if not ary.mutable:
-                raise TypeError("Immutable array")
+                raise TypeError("Cannot modify value of type %s" %(ary,))
             return signature(types.none, ary, normalize_index(idx), ary.dtype)
 
 
diff --git a/numba/typing/context.py b/numba/typing/context.py
--- a/numba/typing/context.py
+++ b/numba/typing/context.py
@@ -177,7 +177,8 @@ def resolve_data_type(self, val):
             except NotImplementedError:
                 return
             layout = numpy_support.map_layout(ary)
-            return types.Array(dtype, ary.ndim, layout)
+            readonly = not ary.flags.writeable
+            return types.Array(dtype, ary.ndim, layout, readonly=readonly)
 
         elif sys.version_info >= (2, 7) and not isinstance(val, numpy.generic):
             try:


Test patch:
diff --git a/numba/tests/test_indexing.py b/numba/tests/test_indexing.py
--- a/numba/tests/test_indexing.py
+++ b/numba/tests/test_indexing.py
@@ -4,7 +4,7 @@
 
 import numba.unittest_support as unittest
 from numba.compiler import compile_isolated, Flags
-from numba import types, utils, njit
+from numba import types, utils, njit, errors
 from numba.tests import usecases
 from .support import TestCase
 
@@ -112,6 +112,10 @@ def empty_tuple_usecase(a):
     return a[()]
 
 
+@njit
+def setitem_usecase(a, index, value):
+    a[index] = value
+
 def slicing_1d_usecase_set(a, b, start, stop, step):
     a[start:stop:step] = b
     return a
@@ -694,7 +698,19 @@ def test_2d_slicing_set_npm(self):
         with self.assertTypingError():
             self.test_2d_slicing_set(flags=Noflags)
 
+    def test_setitem(self):
+        arr = np.arange(5)
+        setitem_usecase(arr, 1, 42)
+        self.assertEqual(list(arr), [0, 42, 2, 3, 4])
+
+    def test_setitem_readonly(self):
+        arr = np.arange(5)
+        arr.flags.writeable = False
+        with self.assertRaises((TypeError, errors.TypingError)) as raises:
+            setitem_usecase(arr, 1, 42)
+        self.assertIn("Cannot modify value of type readonly array(int64, 1d, C)",
+                      str(raises.exception))
+
 
 if __name__ == '__main__':
     unittest.main()
-
diff --git a/numba/tests/test_special.py b/numba/tests/test_special.py
--- a/numba/tests/test_special.py
+++ b/numba/tests/test_special.py
@@ -36,21 +36,24 @@ def test_array_values(self):
         """
         Test special.typeof() with ndarray values.
         """
-        def check(arr, ndim, layout):
+        def check(arr, ndim, layout, mutable):
             ty = special.typeof(arr)
             self.assertIsInstance(ty, types.Array)
             self.assertEqual(ty.ndim, ndim)
             self.assertEqual(ty.layout, layout)
+            self.assertEqual(ty.mutable, mutable)
 
         a1 = np.arange(10)
-        check(a1, 1, 'C')
+        check(a1, 1, 'C', True)
         a2 = np.arange(10).reshape(2, 5)
-        check(a2, 2, 'C')
-        check(a2.T, 2, 'F')
+        check(a2, 2, 'C', True)
+        check(a2.T, 2, 'F', True)
         a3 = (np.arange(60))[::2].reshape((2, 5, 3))
-        check(a3, 3, 'A')
+        check(a3, 3, 'A', True)
         a4 = np.arange(1).reshape(())
-        check(a4, 0, 'C')
+        check(a4, 0, 'C', True)
+        a4.flags.writeable = False
+        check(a4, 0, 'C', False)
 
 
 if __name__ == '__main__':