1 /*#############################################################################
3 # Pakfire - The IPFire package management system #
4 # Copyright (C) 2023 Pakfire development team #
6 # This program is free software: you can redistribute it and/or modify #
7 # it under the terms of the GNU General Public License as published by #
8 # the Free Software Foundation, either version 3 of the License, or #
9 # (at your option) any later version. #
11 # This program is distributed in the hope that it will be useful, #
12 # but WITHOUT ANY WARRANTY; without even the implied warranty of #
13 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the #
14 # GNU General Public License for more details. #
16 # You should have received a copy of the GNU General Public License #
17 # along with this program. If not, see <http://www.gnu.org/licenses/>. #
19 #############################################################################*/
21 #define PY_SSIZE_T_CLEAN
25 #include <pakfire/ctx.h>
29 static PyObject
* Ctx_new(PyTypeObject
* type
, PyObject
* args
, PyObject
* kwds
) {
30 CtxObject
* self
= (CtxObject
*)type
->tp_alloc(type
, 0);
34 return (PyObject
*)self
;
37 static void Ctx_log_callback(void* data
, int level
, const char* file
, int line
,
38 const char* fn
, const char* format
, va_list args
) {
39 PyObject
* logger
= (PyObject
*)data
;
40 PyObject
* result
= NULL
;
44 PyObject
* exception
= NULL
;
45 PyObject
* type
= NULL
;
46 PyObject
* value
= NULL
;
47 PyObject
* traceback
= NULL
;
49 // Do nothing if the logger does not exist
53 // Translate priority to Python logging priorities
67 // Drop messages of an unknown level
72 PyGILState_STATE state
= PyGILState_Ensure();
74 // Format the log line
75 r
= vasprintf(&buffer
, format
, args
);
79 // Remove trailing newline
80 if (buffer
[r
- 1] == '\n')
84 result
= PyObject_CallMethod(logger
, "log", "is#", level
, buffer
, r
);
90 We cannot really catch any Python errors here, since we cannot send
91 any error codes up the chain.
93 So, in order to debug the problem, We will check if an exception has
94 occurred and if so, print it to the console.
96 exception
= PyErr_Occurred();
100 // Fetch the exception and destroy it
101 PyErr_Fetch(&type
, &value
, &traceback
);
105 Py_XDECREF(traceback
);
113 PyGILState_Release(state
);
116 static void Ctx___set_logger(CtxObject
* self
, PyObject
* logger
) {
117 // Dereference the old logger
118 Py_XDECREF(self
->logger
);
120 // Store the new logger
121 self
->logger
= logger
;
122 Py_XINCREF(self
->logger
);
125 pakfire_ctx_set_log_callback(self
->ctx
, Ctx_log_callback
, self
->logger
);
128 static int Ctx_setup_logging(CtxObject
* self
) {
129 PyObject
* logging
= NULL
;
130 PyObject
* logger
= NULL
;
134 logging
= PyImport_ImportModule("logging");
138 // logging.getLogger("pakfire")
139 logger
= PyObject_CallMethod(logging
, "getLogger", "s", "pakfire");
143 // Set default logger
144 Ctx___set_logger(self
, logger
);
156 static int Ctx_init(CtxObject
* self
, PyObject
* args
, PyObject
* kwargs
) {
157 char* kwlist
[] = { (char*)"path", NULL
};
158 const char* path
= NULL
;
162 if (!PyArg_ParseTupleAndKeywords(args
, kwargs
, "|s", kwlist
, &path
))
166 r
= pakfire_ctx_create(&self
->ctx
, path
);
170 PyErr_SetFromErrno(PyExc_OSError
);
174 // Set the log level to DEBUG
175 pakfire_ctx_set_log_level(self
->ctx
, LOG_DEBUG
);
177 // Setup the default logger
178 r
= Ctx_setup_logging(self
);
185 static void Ctx_dealloc(CtxObject
* self
) {
188 pakfire_ctx_set_log_callback(self
->ctx
, NULL
, NULL
);
190 pakfire_ctx_unref(self
->ctx
);
193 Py_XDECREF(self
->logger
);
195 Py_TYPE(self
)->tp_free((PyObject
*)self
);
200 static PyObject
* Ctx_set_logger(CtxObject
* self
, PyObject
* args
) {
201 PyObject
* logger
= NULL
;
203 if (!PyArg_ParseTuple(args
, "O", &logger
))
207 Ctx___set_logger(self
, logger
);
212 static PyObject
* Ctx_set_cache_path(CtxObject
* self
, PyObject
* value
) {
213 const char* path
= NULL
;
217 path
= PyUnicode_AsUTF8(value
);
221 // Set the cache path
222 r
= pakfire_ctx_set_cache_path(self
->ctx
, path
);
225 PyErr_SetFromErrno(PyExc_OSError
);
233 static struct PyMethodDef Ctx_methods
[] = {
236 (PyCFunction
)Ctx_set_logger
,
243 static struct PyGetSetDef Ctx_getsetters
[] = {
247 (setter
)Ctx_set_cache_path
,
254 PyTypeObject CtxType
= {
255 PyVarObject_HEAD_INIT(NULL
, 0)
256 tp_name
: "_pakfire.Ctx",
257 tp_basicsize
: sizeof(CtxObject
),
258 tp_flags
: Py_TPFLAGS_DEFAULT
|Py_TPFLAGS_BASETYPE
,
260 tp_dealloc
: (destructor
)Ctx_dealloc
,
261 tp_init
: (initproc
)Ctx_init
,
262 tp_doc
: "Ctx Object",
263 tp_methods
: Ctx_methods
,
264 tp_getset
: Ctx_getsetters
,