Repository: ninia/jep (language: python)

Issue:
Exception while trying to invoke a python function which returns a bytestring-jep.JepException: <class 'BufferError'>: Object is not writable.
**Problem**
I am trying to invoke a python function which returns a bytestring and I keep getting an exception.
Same code did run without any issues using Jep 3.9.1.

Sample code/over simplified :
**Python**
  ```
    def get_binary(arg_1, arg_2):
          return b'binary'
```
**Java**
```
import jep.Interpreter;
Interpreter interpreter;
byte[] myBinary;
myBinary = (byte[]) interpreter.invoke("get_binary", ["a1","a2"]);

```
**Exception**
```
    jep.JepException: <class 'BufferError'>: Object is not writable.
        at jep.Jep.invoke(Native Method)
        at jep.Jep.invoke(Jep.java:257)
```

**Environment (please complete the following information):**
- Oracle Linux Server 7.3"
- Python 3.6.13
- java (TM) version 1.8.0_261
- Jep Version: 4.0.1
- Python packages:
numpy                     1.19.5 
pandas                    1.1.5
scipy                     1.5.4


Discussion / hints:

Fix patch:
diff --git a/src/main/c/Jep/convert_p2j.c b/src/main/c/Jep/convert_p2j.c
index a00650f0..cc6efb51 100644
--- a/src/main/c/Jep/convert_p2j.c
+++ b/src/main/c/Jep/convert_p2j.c
@@ -799,7 +799,7 @@ static jshortArray pybuffer_as_jshortarray(JNIEnv *env, PyObject *pybuffer)
     jshortArray jarr = NULL;
     Py_buffer view;
 
-    if (PyObject_GetBuffer(pybuffer, &view, PyBUF_FULL) < 0) {
+    if (PyObject_GetBuffer(pybuffer, &view, PyBUF_FULL_RO) < 0) {
         return NULL;
     }
     if ( pybufferview_check_jshortarray(view) ) {
@@ -846,7 +846,7 @@ static jintArray pybuffer_as_jintarray(JNIEnv *env, PyObject *pybuffer)
     jintArray jarr = NULL;
     Py_buffer view;
 
-    if (PyObject_GetBuffer(pybuffer, &view, PyBUF_FULL) < 0) {
+    if (PyObject_GetBuffer(pybuffer, &view, PyBUF_FULL_RO) < 0) {
         return NULL;
     }
     if (pybufferview_check_jintarray(view)) {
@@ -892,7 +892,7 @@ static jlongArray pybuffer_as_jlongarray(JNIEnv *env, PyObject *pybuffer)
     jlongArray jarr = NULL;
     Py_buffer view;
 
-    if (PyObject_GetBuffer(pybuffer, &view, PyBUF_FULL) < 0) {
+    if (PyObject_GetBuffer(pybuffer, &view, PyBUF_FULL_RO) < 0) {
         return NULL;
     }
     if ( pybufferview_check_jlongarray(view) ) {
@@ -938,7 +938,7 @@ static jfloatArray pybuffer_as_jfloatarray(JNIEnv *env, PyObject *pybuffer)
     jfloatArray jarr = NULL;
     Py_buffer view;
 
-    if (PyObject_GetBuffer(pybuffer, &view, PyBUF_FULL) < 0) {
+    if (PyObject_GetBuffer(pybuffer, &view, PyBUF_FULL_RO) < 0) {
         return NULL;
     }
     if (pybufferview_check_jfloatarray(view)) {
@@ -983,7 +983,7 @@ static jdoubleArray pybuffer_as_jdoublearray(JNIEnv *env, PyObject *pybuffer)
     jdoubleArray jarr = NULL;
     Py_buffer view;
 
-    if (PyObject_GetBuffer(pybuffer, &view, PyBUF_FULL) < 0) {
+    if (PyObject_GetBuffer(pybuffer, &view, PyBUF_FULL_RO) < 0) {
         return NULL;
     }
     if ( pybufferview_check_jdoublearray(view) ) {
@@ -1010,11 +1010,11 @@ static jobject pybuffer_as_jobject(JNIEnv *env, PyObject *pybuffer,
          */
         Py_buffer view;
         jobject result = NULL;
-        if (PyObject_GetBuffer(pybuffer, &view, PyBUF_FULL) < 0) {
+        if (PyObject_GetBuffer(pybuffer, &view, PyBUF_FULL_RO) < 0) {
             return NULL;
         }
-        if (pybufferview_check_jintarray(view)) {
-            result = (jobject) pybufferview_as_jintarray(env, view);
+        if (pybufferview_check_jbytearray(view)) {
+            result = (jobject) pybufferview_as_jbytearray(env, view);
         } else if (pybufferview_check_jshortarray(view)) {
             result = (jobject) pybufferview_as_jshortarray(env, view);
         } else if (pybufferview_check_jintarray(view)) {


Test patch:
diff --git a/src/test/python/test_types.py b/src/test/python/test_types.py
index dd9d1f61..86c881eb 100644
--- a/src/test/python/test_types.py
+++ b/src/test/python/test_types.py
@@ -785,6 +785,8 @@ def test_int_array(self):
         v = memoryview(a)
         v = v[::2]
         examples.append(v)
+        if sys.version_info.major > 3 or sys.version_info.minor > 7:
+            examples.append(v.toreadonly())
         for l in examples:
             self.assertSequenceEqual(l, self.methods.intArray(l))
             self.assertSequenceEqual(l, self.staticMethods.intArray(l))
@@ -827,8 +829,12 @@ def test_byte_array(self):
         v = v[::2]
         bb = ByteBuffer.wrap(v)
         self.assertSequenceEqual(bb.array(), v)
+        if sys.version_info.major > 3 or sys.version_info.minor > 7:
+            bb = ByteBuffer.wrap(v.toreadonly())
+            self.assertSequenceEqual(bb.array(), v)
         with self.assertRaises(TypeError):
             ByteBuffer.wrap(array.array('f', [1,2,3,4]))
+        self.assertSequenceEqual(self.methods.object(b'binary'), b'binary')
                 
     def test_float_array(self):
         from java.nio import FloatBuffer
@@ -841,6 +847,9 @@ def test_float_array(self):
         v = v[::2]
         fb = FloatBuffer.wrap(v)
         self.assertSequenceEqual(fb.array(), v)
+        if sys.version_info.major > 3 or sys.version_info.minor > 7:
+            fb = FloatBuffer.wrap(v.toreadonly())
+            self.assertSequenceEqual(fb.array(), v)
         with self.assertRaises(TypeError):
             FloatBuffer.wrap(array.array('i', [1,2,3,4]))
 
@@ -855,6 +864,9 @@ def test_long_array(self):
         v = v[::2]
         lb = LongBuffer.wrap(v)
         self.assertSequenceEqual(lb.array(), v)
+        if sys.version_info.major > 3 or sys.version_info.minor > 7:
+            lb = LongBuffer.wrap(v.toreadonly())
+            self.assertSequenceEqual(lb.array(), v)
         with self.assertRaises(TypeError):
             LongBuffer.wrap(array.array('f', [1,2,3,4]))