1 /*#############################################################################
3 # Pakfire - The IPFire package management system #
4 # Copyright (C) 2011 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 #############################################################################*/
25 #include <pakfire/arch.h>
26 #include <pakfire/dependencies.h>
27 #include <pakfire/key.h>
30 #include "archive_file.h"
31 #include "buildservice.h"
42 PyMODINIT_FUNC
PyInit__pakfire(void);
44 PyObject
* PyExc_BadSignatureError
;
45 PyObject
* PyExc_CommandExecutionError
;
46 PyObject
* PyExc_DependencyError
;
48 PyObject
* PyExc_CheckError
;
49 PyObject
* PyExc_CheckFileVerificationError
;
51 struct pakfire_ctx
* pakfire_ctx
= NULL
;
53 static PyObject
* setup_logger(void) {
54 PyObject
* logging
= NULL
;
55 PyObject
* logger
= NULL
;
58 logging
= PyImport_ImportModule("logging");
62 // logging.getLogger("pakfire")
63 logger
= PyObject_CallMethod(logging
, "getLogger", "s", "pakfire");
73 static void __pakfire_log_callback(void* data
, int level
, const char* file
, int line
,
74 const char* fn
, const char* format
, va_list args
) {
75 PyObject
* logger
= (PyObject
*)data
;
76 PyObject
* result
= NULL
;
80 PyObject
* exception
= NULL
;
81 PyObject
* type
= NULL
;
82 PyObject
* value
= NULL
;
83 PyObject
* traceback
= NULL
;
85 // Do nothing if the logger does not exist
89 // Translate priority to Python logging priorities
103 // Drop messages of an unknown level
108 PyGILState_STATE state
= PyGILState_Ensure();
110 // Format the log line
111 r
= vasprintf(&buffer
, format
, args
);
116 result
= PyObject_CallMethod(logger
, "log", "is", level
, buffer
);
122 We cannot really catch any Python errors here, since we cannot send
123 any error codes up the chain.
125 So, in order to debug the problem, We will check if an exception has
126 occurred and if so, print it to the console.
128 exception
= PyErr_Occurred();
132 // Fetch the exception and destroy it
133 PyErr_Fetch(&type
, &value
, &traceback
);
137 Py_XDECREF(traceback
);
145 PyGILState_Release(state
);
148 static int initialize_context(void) {
149 PyObject
* logger
= NULL
;
152 // Create a new context
153 r
= pakfire_ctx_create(&pakfire_ctx
, NULL
);
155 PyErr_SetFromErrno(PyExc_OSError
);
159 // Setup the python logger
160 logger
= setup_logger();
164 // Pass all log messages to Python
165 pakfire_ctx_set_log_callback(pakfire_ctx
, __pakfire_log_callback
, logger
);
168 // Set the log level to DEBUG
169 pakfire_ctx_set_log_level(pakfire_ctx
, LOG_DEBUG
);
175 pakfire_ctx_unref(pakfire_ctx
);
183 static PyObject
* _pakfire_native_arch(void) {
184 const char* arch
= pakfire_arch_native();
188 return PyUnicode_FromString(arch
);
191 static PyObject
* _pakfire_set_log_level(PyObject
* self
, PyObject
* args
) {
194 if (!PyArg_ParseTuple(args
, "i", &level
))
198 pakfire_ctx_set_log_level(pakfire_ctx
, level
);
203 static PyObject
* _pakfire_supported_arches(void) {
206 // Fetch all architectures
207 const char** arches
= pakfire_supported_arches();
209 PyErr_SetFromErrno(PyExc_OSError
);
214 PyObject
* list
= PyList_New(0);
218 // Append all architectures
219 for (const char** arch
= arches
; *arch
; arch
++) {
220 PyObject
* object
= PyUnicode_FromString(*arch
);
225 r
= PyList_Append(list
, object
);
241 static PyObject
* _pakfire_version_compare(PyObject
* self
, PyObject
* args
) {
242 const char* evr1
= NULL
;
243 const char* evr2
= NULL
;
246 if (!PyArg_ParseTuple(args
, "ss", &evr1
, &evr2
))
250 r
= pakfire_static_version_compare(evr1
, evr2
);
252 // Return the return code
253 return PyLong_FromLong(r
);
256 static PyMethodDef pakfireModuleMethods
[] = {
257 {"native_arch", (PyCFunction
)_pakfire_native_arch
, METH_NOARGS
, NULL
},
260 (PyCFunction
)_pakfire_set_log_level
,
264 {"supported_arches", (PyCFunction
)_pakfire_supported_arches
, METH_NOARGS
, NULL
},
267 (PyCFunction
)_pakfire_version_compare
,
271 { NULL
, NULL
, 0, NULL
}
274 static struct PyModuleDef moduledef
= {
275 .m_base
= PyModuleDef_HEAD_INIT
,
276 .m_name
= "_pakfire",
278 .m_methods
= pakfireModuleMethods
,
281 PyMODINIT_FUNC
PyInit__pakfire(void) {
284 /* Initialize locale */
285 setlocale(LC_ALL
, "");
286 bindtextdomain(PACKAGE_TARNAME
, "/usr/share/locale");
287 textdomain(PACKAGE_TARNAME
);
290 PyObject
* module
= PyModule_Create(&moduledef
);
294 PyExc_BadSignatureError
= PyErr_NewException("_pakfire.BadSignatureError", NULL
, NULL
);
295 Py_INCREF(PyExc_BadSignatureError
);
296 PyModule_AddObject(module
, "BadSignatureError", PyExc_BadSignatureError
);
298 PyExc_CommandExecutionError
= PyErr_NewException("_pakfire.CommandExecutionError", NULL
, NULL
);
299 Py_INCREF(PyExc_CommandExecutionError
);
300 PyModule_AddObject(module
, "CommandExecutionError", PyExc_CommandExecutionError
);
302 PyExc_DependencyError
= PyErr_NewException("_pakfire.DependencyError", NULL
, NULL
);
303 Py_INCREF(PyExc_DependencyError
);
304 PyModule_AddObject(module
, "DependencyError", PyExc_DependencyError
);
309 PyExc_CheckError
= PyErr_NewException("_pakfire.CheckError", NULL
, NULL
);
310 Py_INCREF(PyExc_CheckError
);
311 if (PyModule_AddObject(module
, "CheckError", PyExc_CheckError
) < 0) {
312 Py_XDECREF(PyExc_CheckError
);
313 Py_CLEAR(PyExc_CheckError
);
317 // CheckFileVerificationError based on CheckError
318 PyExc_CheckFileVerificationError
= PyErr_NewExceptionWithDoc(
319 "_pakfire.CheckFileVerificationError",
320 "The file verification process failed",
324 Py_INCREF(PyExc_CheckFileVerificationError
);
325 if (PyModule_AddObject(module
, "CheckFileVerificationError", PyExc_CheckFileVerificationError
) < 0) {
326 Py_XDECREF(PyExc_CheckFileVerificationError
);
327 Py_CLEAR(PyExc_CheckFileVerificationError
);
332 if (PyType_Ready(&PakfireType
) < 0)
335 Py_INCREF(&PakfireType
);
336 PyModule_AddObject(module
, "Pakfire", (PyObject
*)&PakfireType
);
339 if (PyType_Ready(&ArchiveType
) < 0)
342 Py_INCREF(&ArchiveType
);
343 PyModule_AddObject(module
, "Archive", (PyObject
*)&ArchiveType
);
346 if (PyType_Ready(&ArchiveFileType
) < 0)
349 Py_INCREF(&ArchiveFileType
);
350 PyModule_AddObject(module
, "ArchiveFile", (PyObject
*)&ArchiveFileType
);
353 if (PyType_Ready(&BuildServiceType
) < 0)
356 Py_INCREF(&BuildServiceType
);
357 PyModule_AddObject(module
, "BuildService", (PyObject
*)&BuildServiceType
);
360 if (PyType_Ready(&FileType
) < 0)
363 Py_INCREF(&FileType
);
364 PyModule_AddObject(module
, "File", (PyObject
*)&FileType
);
367 if (PyType_Ready(&KeyType
) < 0)
371 PyModule_AddObject(module
, "Key", (PyObject
*)&KeyType
);
374 if (PyType_Ready(&PackageType
) < 0)
377 Py_INCREF(&PackageType
);
378 PyModule_AddObject(module
, "Package", (PyObject
*)&PackageType
);
381 if (PyType_Ready(&ProblemType
) < 0)
383 Py_INCREF(&ProblemType
);
384 PyModule_AddObject(module
, "Problem", (PyObject
*)&ProblemType
);
387 if (PyType_Ready(&RepoType
) < 0)
390 Py_INCREF(&RepoType
);
391 PyModule_AddObject(module
, "Repo", (PyObject
*)&RepoType
);
394 if (PyType_Ready(&SolutionType
) < 0)
397 Py_INCREF(&SolutionType
);
398 PyModule_AddObject(module
, "Solution", (PyObject
*)&SolutionType
);
401 if (PyModule_AddIntMacro(module
, PAKFIRE_KEY_ALGO_NULL
) < 0)
403 if (PyModule_AddIntMacro(module
, PAKFIRE_KEY_ALGO_ED25519
) < 0)
406 // Initialize the context
407 r
= initialize_context();