]> git.ipfire.org Git - pakfire.git/commitdiff
python: Allow passing a confirm callback from Python
authorMichael Tremer <michael.tremer@ipfire.org>
Fri, 14 Mar 2025 15:20:47 +0000 (15:20 +0000)
committerMichael Tremer <michael.tremer@ipfire.org>
Fri, 14 Mar 2025 15:20:47 +0000 (15:20 +0000)
Signed-off-by: Michael Tremer <michael.tremer@ipfire.org>
src/python/ctx.c
src/python/ctx.h
tests/python/ctx.py

index 122fd647c18e76c76773d4ebdfeec06842d020e0..375f7308dc4033bc7a52eca198cdb737381a2e25 100644 (file)
@@ -197,6 +197,7 @@ static void Ctx_dealloc(CtxObject* self) {
                pakfire_ctx_unref(self->ctx);
        }
 
+       Py_XDECREF(self->callbacks.confirm);
        Py_XDECREF(self->logger);
 
        Py_TYPE(self)->tp_free((PyObject *)self);
@@ -216,6 +217,54 @@ static PyObject* Ctx_set_logger(CtxObject* self, PyObject* args) {
        Py_RETURN_NONE;
 }
 
+// Confirm Callback
+
+static int Ctx_confirm_callback(struct pakfire_ctx* ctx, struct pakfire* pakfire,
+               void* data, const char* message, const char* question) {
+       PyObject* callback = data;
+       PyObject* ret = NULL;
+       int r = 0;
+
+       // Call the callback function
+       ret = PyObject_CallFunction(callback, "ss", message, question);
+       if (!ret)
+               return -1;
+
+       // Return if the result is True
+       if (PyObject_IsTrue(ret))
+               r = 1;
+
+       // Cleanup
+       Py_DECREF(ret);
+
+       return r;
+}
+
+static PyObject* Ctx_set_confirm_callback(CtxObject* self, PyObject* args) {
+       PyObject* callback = NULL;
+
+       // Parse arguments
+       if (!PyArg_ParseTuple(args, "O", &callback))
+               return NULL;
+
+       // Check if the callback is actually callable
+       if (!PyCallable_Check(callback)) {
+               PyErr_SetString(PyExc_ValueError, "Callback is not callable");
+               return NULL;
+       }
+
+       // Store a reference to the callback
+       self->callbacks.confirm = callback;
+       Py_INCREF(self->callbacks.confirm);
+
+       // Set the confirm callback of the context
+       pakfire_ctx_set_confirm_callback(self->ctx, Ctx_confirm_callback, self->callbacks.confirm);
+
+       Py_RETURN_NONE;
+}
+
+// Cache Path
+
 static PyObject* Ctx_get_cache_path(CtxObject* self) {
        const char* path = NULL;
 
@@ -251,6 +300,12 @@ static int Ctx_set_cache_path(CtxObject* self, PyObject* value) {
 }
 
 static struct PyMethodDef Ctx_methods[] = {
+       {
+               "set_confirm_callback",
+               (PyCFunction)Ctx_set_confirm_callback,
+               METH_VARARGS,
+               NULL,
+       },
        {
                "set_logger",
                (PyCFunction)Ctx_set_logger,
index 7ff1b0dcac4dbf6893d20c8230593688599de869..81d12ad987dd79080dba26f6df012ad3b7aa7933 100644 (file)
@@ -30,6 +30,11 @@ typedef struct {
        struct pakfire_ctx* ctx;
 
        PyObject* logger;
+
+       // Callbacks
+       struct {
+               PyObject* confirm;
+       } callbacks;
 } CtxObject;
 
 extern PyTypeObject CtxType;
index ab2b77db2ab647d0a0dcbab671add0fb72145374..80ce2d9e28c7620b2d43dea4ae67eb248b30273f 100755 (executable)
@@ -87,6 +87,31 @@ class CtxTests(tests.TestCase):
                # Check if we have received anything
                self.assertTrue(logger.buffer)
 
+       # Callbacks
+
+       def test_set_callbacks(self):
+               """
+                       Tries to set some callbacks.
+
+                       I am not sure how we should call these to test them...
+               """
+               # Create a new context
+               ctx = self.setup_ctx()
+
+               # Try setting something that we cannot call
+               with self.assertRaises(ValueError):
+                       ctx.set_confirm_callback(None)
+
+               # Create a simple callback function
+               def confirm_callback(message, question):
+                       print(message)
+                       print(question)
+
+                       return True
+
+               # Set the confirm callback
+               ctx.set_confirm_callback(confirm_callback)
+
 
 if __name__ == "__main__":
        tests.main()