Blame SOURCES/0010-Add-nbdkit.parse_size-Python-function.patch

3cdd4c
From 52ee1dab95436128b44c37cc495022ff90108b2e Mon Sep 17 00:00:00 2001
3cdd4c
From: Nikolaus Rath <Nikolaus@rath.org>
3cdd4c
Date: Mon, 9 May 2022 10:04:30 +0100
3cdd4c
Subject: [PATCH] Add nbdkit.parse_size() Python function.
3cdd4c
3cdd4c
This enables Python plugins to parse sizes the same way as C plugins.
3cdd4c
3cdd4c
I'm not sure about the best way to test this - input is appreciated.
3cdd4c
3cdd4c
I'm not too happy with the way this code is tested. It workes, but putting the tests into
3cdd4c
test-python-plugin.py feels misplaced: this file is intended to support the unit tests in
3cdd4c
test_python.py, not run its own unit tests.
3cdd4c
3cdd4c
(cherry picked from commit 1b7d72542be68e254c1ef86ecb1a82b05c78ff63)
3cdd4c
---
3cdd4c
 plugins/python/modfunctions.c           | 21 +++++++++++++++++++++
3cdd4c
 plugins/python/nbdkit-python-plugin.pod |  5 +++++
3cdd4c
 tests/test-python-plugin.py             | 19 +++++++++++++++++++
3cdd4c
 3 files changed, 45 insertions(+)
3cdd4c
3cdd4c
diff --git a/plugins/python/modfunctions.c b/plugins/python/modfunctions.c
3cdd4c
index fffbaab2..46b0c904 100644
3cdd4c
--- a/plugins/python/modfunctions.c
3cdd4c
+++ b/plugins/python/modfunctions.c
3cdd4c
@@ -93,11 +93,32 @@ do_shutdown (PyObject *self, PyObject *args)
3cdd4c
   Py_RETURN_NONE;
3cdd4c
 }
3cdd4c
 
3cdd4c
+/* nbdkit.parse_size */
3cdd4c
+static PyObject *
3cdd4c
+parse_size (PyObject *self, PyObject *args)
3cdd4c
+{
3cdd4c
+  const char *s;
3cdd4c
+  if (!PyArg_ParseTuple (args, "s", &s)) {
3cdd4c
+    PyErr_SetString (PyExc_TypeError, "Expected string, got something else");
3cdd4c
+    return NULL;
3cdd4c
+  }
3cdd4c
+
3cdd4c
+  int64_t size = nbdkit_parse_size(s);
3cdd4c
+  if (size == -1) {
3cdd4c
+    PyErr_SetString (PyExc_ValueError, "Unable to parse string as size");
3cdd4c
+    return NULL;
3cdd4c
+  }
3cdd4c
+
3cdd4c
+  return PyLong_FromSize_t((size_t)size);
3cdd4c
+}
3cdd4c
+
3cdd4c
 static PyMethodDef NbdkitMethods[] = {
3cdd4c
   { "debug", debug, METH_VARARGS,
3cdd4c
     "Print a debug message" },
3cdd4c
   { "export_name", export_name, METH_VARARGS,
3cdd4c
     "Return the optional export name negotiated with the client" },
3cdd4c
+  { "parse_size", parse_size, METH_VARARGS,
3cdd4c
+    "Parse human-readable size strings into bytes" },
3cdd4c
   { "set_error", set_error, METH_VARARGS,
3cdd4c
     "Store an errno value prior to throwing an exception" },
3cdd4c
   { "shutdown", do_shutdown, METH_VARARGS,
3cdd4c
diff --git a/plugins/python/nbdkit-python-plugin.pod b/plugins/python/nbdkit-python-plugin.pod
3cdd4c
index 051b0237..ccc9406f 100644
3cdd4c
--- a/plugins/python/nbdkit-python-plugin.pod
3cdd4c
+++ b/plugins/python/nbdkit-python-plugin.pod
3cdd4c
@@ -131,6 +131,11 @@ Record C<err> as the reason you are about to throw an exception. C<err>
3cdd4c
 should correspond to usual errno values, where it may help to
3cdd4c
 C<import errno>.
3cdd4c
 
3cdd4c
+=head3 C<nbdkit.parse_size(str)>
3cdd4c
+
3cdd4c
+Parse a string (such as "100M") into a size in bytes. Wraps the
3cdd4c
+C<nbdkit_parse_size()> C function.
3cdd4c
+
3cdd4c
 =head3 C<nbdkit.shutdown()>
3cdd4c
 
3cdd4c
 Request asynchronous server shutdown.
3cdd4c
diff --git a/tests/test-python-plugin.py b/tests/test-python-plugin.py
3cdd4c
index 0b34d532..d4f379fc 100644
3cdd4c
--- a/tests/test-python-plugin.py
3cdd4c
+++ b/tests/test-python-plugin.py
3cdd4c
@@ -34,12 +34,31 @@
3cdd4c
 import nbdkit
3cdd4c
 import pickle
3cdd4c
 import base64
3cdd4c
+import unittest
3cdd4c
 
3cdd4c
 API_VERSION = 2
3cdd4c
 
3cdd4c
 cfg = {}
3cdd4c
 
3cdd4c
 
3cdd4c
+# Not nice, but there doesn't seem to be a better way of putting this
3cdd4c
+class TestAPI(unittest.TestCase):
3cdd4c
+
3cdd4c
+    def test_parse_size(self):
3cdd4c
+        self.assertEqual(nbdkit.parse_size('511'), 511)
3cdd4c
+        self.assertEqual(nbdkit.parse_size('7k'), 7*1024)
3cdd4c
+        self.assertEqual(nbdkit.parse_size('17M'), 17*1024*1024)
3cdd4c
+
3cdd4c
+        with self.assertRaises(TypeError):
3cdd4c
+            nbdkit.parse_size(17)
3cdd4c
+
3cdd4c
+        with self.assertRaises(ValueError):
3cdd4c
+            nbdkit.parse_size('foo')
3cdd4c
+
3cdd4c
+
3cdd4c
+TestAPI().test_parse_size()
3cdd4c
+
3cdd4c
+
3cdd4c
 def config(k, v):
3cdd4c
     global cfg
3cdd4c
     if k == "cfg":
3cdd4c
-- 
3cdd4c
2.31.1
3cdd4c