]> git.ipfire.org Git - pakfire.git/commitdiff
python: Pass logger to Pakfire instance
authorMichael Tremer <michael.tremer@ipfire.org>
Tue, 15 Jun 2021 15:13:22 +0000 (15:13 +0000)
committerMichael Tremer <michael.tremer@ipfire.org>
Tue, 15 Jun 2021 15:13:22 +0000 (15:13 +0000)
Signed-off-by: Michael Tremer <michael.tremer@ipfire.org>
src/_pakfire/pakfire.c
src/_pakfire/pakfire.h
src/pakfire/logger.py
src/scripts/pakfire-builder.in

index a01c65b9f012839f701e1ec5980b50f0dd41a12f..5152208042450c353f19e5fd82149efdad69696c 100644 (file)
@@ -44,13 +44,57 @@ static PyObject* Pakfire_new(PyTypeObject* type, PyObject* args, PyObject* kwds)
        PakfireObject* self = (PakfireObject *)type->tp_alloc(type, 0);
        if (self) {
                self->pakfire = NULL;
+               self->logger = NULL;
        }
 
        return (PyObject *)self;
 }
 
+static void Pakfire_logging_callback(void* data, int priority, const char* file, int line,
+               const char* fn, const char* format, va_list args) {
+       PyObject* callback = (PyObject*)data;
+
+       // Do nothing if callback isn't set
+       if (!callback)
+               return;
+
+       // Translate priority to Python logging priorities
+       switch (priority) {
+               case LOG_INFO:
+                       priority = 20;
+                       break;
+
+               case LOG_ERR:
+                       priority = 40;
+                       break;
+       }
+
+       PyObject* tuple = NULL;
+       PyObject* result = NULL;
+       char* buffer = NULL;
+
+       // Make line
+       int r = vasprintf(&buffer, format, args);
+       if (r < 0)
+               goto ERROR;
+
+       // Build a tuple with the priority and the log message
+       tuple = Py_BuildValue("(is)", priority, buffer);
+       if (!tuple)
+               goto ERROR;
+
+       // Call the callback
+       result = PyObject_CallObject(callback, tuple);
+
+ERROR:
+       if (buffer)
+               free(buffer);
+       Py_XDECREF(tuple);
+       Py_XDECREF(result);
+}
+
 static int Pakfire_init(PakfireObject* self, PyObject* args, PyObject* kwds) {
-       char* kwlist[] = { "path", "arch", "offline", "conf", "build",
+       char* kwlist[] = { "path", "arch", "logger", "offline", "conf", "build",
                "enable_ccache", "enable_snapshot", NULL };
        const char* path = NULL;
        const char* arch = NULL;
@@ -60,10 +104,17 @@ static int Pakfire_init(PakfireObject* self, PyObject* args, PyObject* kwds) {
        int enable_ccache = 1;
        int enable_snapshot = 1;
 
-       if (!PyArg_ParseTupleAndKeywords(args, kwds, "|zzpzppp", kwlist,
-                       &path, &arch, &offline, &conf, &build, &enable_ccache, &enable_snapshot))
+       if (!PyArg_ParseTupleAndKeywords(args, kwds, "|zzOpzppp", kwlist,
+                       &path, &arch, &self->logger, &offline, &conf, &build,
+                       &enable_ccache, &enable_snapshot))
                return -1;
 
+       // Check if logger is callable
+       if (self->logger && !PyCallable_Check(self->logger)) {
+               PyErr_SetString(PyExc_TypeError, "logger must be callable\n");
+               return -1;
+       }
+
        int flags = 0;
 
        // Enable offline mode
@@ -82,7 +133,8 @@ static int Pakfire_init(PakfireObject* self, PyObject* args, PyObject* kwds) {
        }
 
        // Create a new Pakfire instance
-       int r = pakfire_create(&self->pakfire, path, arch, conf, flags, NULL, NULL);
+       int r = pakfire_create(&self->pakfire, path, arch, conf, flags,
+                       (self->logger) ? Pakfire_logging_callback : NULL, self->logger);
        if (r) {
                switch (errno) {
                        // Invalid architecture or path
@@ -98,6 +150,8 @@ static int Pakfire_init(PakfireObject* self, PyObject* args, PyObject* kwds) {
                return -1;
     }
 
+       Py_XINCREF(self->logger);
+
        return 0;
 }
 
@@ -105,6 +159,9 @@ static void Pakfire_dealloc(PakfireObject* self) {
        if (self->pakfire)
                pakfire_unref(self->pakfire);
 
+       if (self->logger)
+               Py_DECREF(self->logger);
+
        Py_TYPE(self)->tp_free((PyObject *)self);
 }
 
index c8f001875670136008cb585fd66585d0bf20274a..208ad4d94600723df62a9387d77d670e019a9987 100644 (file)
@@ -28,6 +28,7 @@
 typedef struct {
        PyObject_HEAD
     Pakfire pakfire;
+    PyObject* logger;
 } PakfireObject;
 
 extern PyTypeObject PakfireType;
index 6c3b698defc73397b2efbfb94228956d60063d64..ecc7988744383645913876a6161f3b61e2576d59 100644 (file)
@@ -95,7 +95,7 @@ class ConsoleHandler(logging.Handler):
                                fd = sys.stdout
 
                        # Write the output
-                       fd.write("%s\n" % msg)
+                       fd.write(msg)
 
                        # Immediately flush
                        self.flush()
index 6814edbdcdb3dc425b52016b15b780db8d38b102..b3a27a871b6254262ec1d0d74f6bf98231275fdb 100644 (file)
 ###############################################################################
 
 import argparse
+import logging
 import os.path
 import sys
 
 import pakfire
+import pakfire.logger
 from pakfire.constants import CONFIG_DISTRO_DIR
 from pakfire.i18n import _
 
 class Cli(object):
+       @property
+       def logger(self):
+               log = logging.getLogger("pakfire.builder.cli")
+               log.setLevel(logging.DEBUG)
+
+               # Do not propagate anything
+               log.propagate = False
+
+               # Enable console output
+               handler = pakfire.logger.ConsoleHandler()
+               log.addHandler(handler)
+
+               return log
+
        def parse_cli(self):
                parser = argparse.ArgumentParser(
                        description = _("Pakfire builder command line interface"),
@@ -126,9 +142,13 @@ class Cli(object):
                        conf=conf,
                        arch=ns.arch,
 
+                       # Set up logging
+                       logger=self.logger.log,
+
                        # Enable build mode
                        build=build,
-                       enable_snapshot=not ns.disable_snapshot
+                       enable_snapshot=not ns.disable_snapshot,
+
                )
 
        def __call__(self):