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_INCREF(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
);
153 static int Ctx_init(CtxObject
* self
, PyObject
* args
, PyObject
* kwargs
) {
154 char* kwlist
[] = { (char*)"path", NULL
};
155 const char* path
= NULL
;
159 if (!PyArg_ParseTupleAndKeywords(args
, kwargs
, "|s", kwlist
, &path
))
163 r
= pakfire_ctx_create(&self
->ctx
, path
);
167 PyErr_SetFromErrno(PyExc_OSError
);
171 // Set the log level to DEBUG
172 pakfire_ctx_set_log_level(self
->ctx
, LOG_DEBUG
);
177 static void Ctx_dealloc(CtxObject
* self
) {
179 pakfire_ctx_unref(self
->ctx
);
181 Py_XDECREF(self
->logger
);
183 Py_TYPE(self
)->tp_free((PyObject
*)self
);
188 static PyObject
* Ctx_set_logger(CtxObject
* self
, PyObject
* args
) {
189 PyObject
* logger
= NULL
;
191 if (!PyArg_ParseTuple(args
, "O", &logger
))
194 // XXX Check if we have a log method
197 Ctx___set_logger(self
, logger
);
202 static PyObject
* Ctx_set_cache_path(CtxObject
* self
, PyObject
* value
) {
203 const char* path
= NULL
;
207 path
= PyUnicode_AsUTF8(value
);
211 // Set the cache path
212 r
= pakfire_ctx_set_cache_path(self
->ctx
, path
);
215 PyErr_SetFromErrno(PyExc_OSError
);
223 static struct PyMethodDef Ctx_methods
[] = {
226 (PyCFunction
)Ctx_set_logger
,
233 static struct PyGetSetDef Ctx_getsetters
[] = {
237 (setter
)Ctx_set_cache_path
,
244 PyTypeObject CtxType
= {
245 PyVarObject_HEAD_INIT(NULL
, 0)
246 tp_name
: "_pakfire.Ctx",
247 tp_basicsize
: sizeof(CtxObject
),
248 tp_flags
: Py_TPFLAGS_DEFAULT
|Py_TPFLAGS_BASETYPE
,
250 tp_dealloc
: (destructor
)Ctx_dealloc
,
251 tp_init
: (initproc
)Ctx_init
,
252 tp_doc
: "Ctx Object",
253 tp_methods
: Ctx_methods
,
254 tp_getset
: Ctx_getsetters
,