From: Michael Tremer Date: Tue, 19 Jan 2021 17:12:28 +0000 (+0000) Subject: libpakfire: execute: Allow passing the logging callback from Python X-Git-Tag: 0.9.28~1285^2~845 X-Git-Url: http://git.ipfire.org/?a=commitdiff_plain;h=d5bb29968cf6b48354f5ac2436f343ab83811a84;p=pakfire.git libpakfire: execute: Allow passing the logging callback from Python Signed-off-by: Michael Tremer --- diff --git a/src/_pakfire/pakfire.c b/src/_pakfire/pakfire.c index 56d3c2a7a..e5fae08ef 100644 --- a/src/_pakfire/pakfire.c +++ b/src/_pakfire/pakfire.c @@ -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++) diff --git a/tests/python/execute.py b/tests/python/execute.py index 25f60f112..3567adfac 100755 --- a/tests/python/execute.py +++ b/tests/python/execute.py @@ -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"])