]> git.ipfire.org Git - pakfire.git/commitdiff
libpakfire: execute: Allow passing the logging callback from Python
authorMichael Tremer <michael.tremer@ipfire.org>
Tue, 19 Jan 2021 17:12:28 +0000 (17:12 +0000)
committerMichael Tremer <michael.tremer@ipfire.org>
Tue, 19 Jan 2021 17:12:28 +0000 (17:12 +0000)
Signed-off-by: Michael Tremer <michael.tremer@ipfire.org>
src/_pakfire/pakfire.c
tests/python/execute.py

index 56d3c2a7ad62a382861b44b8226e43733c19e139..e5fae08efaeed20c686c9da47ee7acabcd178737 100644 (file)
@@ -350,16 +350,43 @@ static Py_ssize_t Pakfire_len(PakfireObject* self) {
        return pakfire_count_packages(self->pakfire);
 }
 
+static PyObject* Pakfire_execute_logging_callback = NULL;
+
+static int __Pakfire_execute_logging_callback(Pakfire pakfire, int priority, const char* data) {
+       int r = 0;
+
+       // Do nothing if callback isn't set
+       if (!Pakfire_execute_logging_callback)
+               return 0;
+
+       // Create tuple with arguments for the callback function
+       PyObject* args = Py_BuildValue("(is)", priority, data);
+       if (!args)
+               return 1;
+
+       PyObject* result = PyEval_CallObject(Pakfire_execute_logging_callback, args);
+    if (result && PyLong_Check(result)) {
+        r = PyLong_AsLong(result);
+    }
+
+       Py_XDECREF(args);
+       Py_DECREF(result);
+
+       return r;
+}
+
 static PyObject* Pakfire_execute(PakfireObject* self, PyObject* args, PyObject* kwds) {
-       char* kwlist[] = {"command", "environ", "enable_network", "interactive", NULL};
+       char* kwlist[] = {"command", "environ", "enable_network", "interactive",
+               "logging_callback", NULL};
 
        PyObject* command = NULL;
        PyObject* environ = NULL;
        int enable_network = 0;
        int interactive = 0;
+       PyObject* logging_callback = NULL;
 
-       if (!PyArg_ParseTupleAndKeywords(args, kwds, "O|Opp", kwlist, &command, &environ,
-                       &enable_network, &interactive))
+       if (!PyArg_ParseTupleAndKeywords(args, kwds, "O|OppO", kwlist, &command, &environ,
+                       &enable_network, &interactive, &logging_callback))
                return NULL;
 
        // Check if command is a list
@@ -386,6 +413,12 @@ static PyObject* Pakfire_execute(PakfireObject* self, PyObject* args, PyObject*
                }
        }
 
+       // Check if logging_callback is
+       if (logging_callback && !PyCallable_Check(logging_callback)) {
+               PyErr_SetString(PyExc_TypeError, "logging_callback must be callable\n");
+               return NULL;
+       }
+
        ssize_t environ_length = 0;
        PyObject* key;
        PyObject* value;
@@ -453,8 +486,12 @@ static PyObject* Pakfire_execute(PakfireObject* self, PyObject* args, PyObject*
        if (interactive)
                flags |= PAKFIRE_EXECUTE_INTERACTIVE;
 
+       // Set logging callback
+       Pakfire_execute_logging_callback = logging_callback;
+
        // Execute command
-       int r = pakfire_execute(self->pakfire, argv, envp, flags, NULL);
+       int r = pakfire_execute(self->pakfire, argv, envp, flags,
+               (logging_callback) ? __Pakfire_execute_logging_callback : NULL);
 
        // Cleanup
        for (unsigned int i = 0; envp[i]; i++)
index 25f60f112bc7ea8451a2fbaa7fd3091307fd0fd7..3567adfacc0bcb265a771b9242ba5731c6c67ee2 100755 (executable)
@@ -70,6 +70,12 @@ class Test(unittest.TestCase):
                # Multiple newlines in one read
                self.pakfire.execute(["/usr/bin/printf", "1\n2\n3\n"])
 
+       def test_execute_logger(self):
+               def log(priority, message):
+                       print("LOG (%s): %s" % (priority, message.rstrip()))
+
+               self.pakfire.execute(["/bin/bash", "--help"], logging_callback=log)
+
        # This is an interactive test which cannot be performed automatically
        #def test_shell(self):
        #       self.pakfire.execute(["/bin/bash", "-i"])