pread() can return now any object supporting the buffer protocol[1] such
as bytearray, bytes, or memoryview.
[1]
https://docs.python.org/3/c-api/buffer.html
---
When the new python tests will be in master we can add some automated tests.
For now I tested this manually using the example plugin as is and with
these changes:
def pread(h, count, offset):
global disk
return bytes(disk[offset:offset+count])
def pread(h, count, offset):
global disk
return memoryview(disk)[offset:offset+count]
plugins/python/python.c | 31 +++++++++++++++++++------------
1 file changed, 19 insertions(+), 12 deletions(-)
diff --git a/plugins/python/python.c b/plugins/python/python.c
index 148097f..ed299ff 100644
--- a/plugins/python/python.c
+++ b/plugins/python/python.c
@@ -445,10 +445,12 @@ py_pread (void *handle, void *buf,
PyObject *obj = handle;
PyObject *fn;
PyObject *r;
+ Py_buffer view = {0};
+ int ret = -1;
if (!callback_defined ("pread", &fn)) {
nbdkit_error ("%s: missing callback: %s", script, "pread");
- return -1;
+ return ret;
}
PyErr_Clear ();
@@ -456,25 +458,30 @@ py_pread (void *handle, void *buf,
r = PyObject_CallFunction (fn, "OiL", obj, count, offset, NULL);
Py_DECREF (fn);
if (check_python_failure ("pread") == -1)
- return -1;
+ return ret;
- if (!PyByteArray_Check (r)) {
- nbdkit_error ("%s: value returned from pread method is not a byte array",
+ if (PyObject_GetBuffer (r, &view, PyBUF_SIMPLE) == -1) {
+ nbdkit_error ("%s: value returned from pread does not support the "
+ "buffer protocol",
script);
- Py_DECREF (r);
- return -1;
+ goto out;
}
- if (PyByteArray_Size (r) < count) {
- nbdkit_error ("%s: byte array returned from pread is too small", script);
- Py_DECREF (r);
- return -1;
+ if (view.len < count) {
+ nbdkit_error ("%s: buffer returned from pread is too small", script);
+ goto out;
}
- memcpy (buf, PyByteArray_AsString (r), count);
+ memcpy (buf, view.buf, count);
+ ret = 0;
+
+out:
+ if (view.obj)
+ PyBuffer_Release (&view);
+
Py_DECREF (r);
- return 0;
+ return ret;
}
static int
--
2.21.0