* Copyright (C) 2011-2021 Gary Kramlich <grim@reaperworld.com> * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2 of the License, or (at your option) any later version. * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, see <https://www.gnu.org/licenses/>. #include "gplugin-python3-loader.h" #include <glib/gi18n-lib.h> #include "gplugin-python3-plugin.h" #include "gplugin-python3-utils.h" struct _GPluginPython3Loader { /****************************************************************************** * GPluginLoader Implementation *****************************************************************************/ gplugin_python3_loader_supported_extensions(G_GNUC_UNUSED GPluginLoader *l) return g_slist_append(NULL, "py"); gplugin_python3_loader_query( G_GNUC_UNUSED GError **error) GPluginPlugin *plugin = NULL; PyObject *pyinfo = NULL, *args = NULL; PyObject *module = NULL, *package_list = NULL, *module_dict = NULL; PyObject *query = NULL, *load = NULL, *unload = NULL; gchar *module_name = NULL, *dir_name = NULL; state = pyg_gil_state_ensure(); /* create package_list as a tuple to handle 'import foo.bar' */ package_list = PyTuple_New(0); /* now figure out the module name from the filename */ module_name = gplugin_python3_filename_to_module(filename); /* grab the dirname since we need it on sys.path to import the module */ dir_name = g_path_get_dirname(filename); gplugin_python3_add_module_path(dir_name); module = PyImport_ImportModuleEx(module_name, NULL, NULL, package_list); g_warning(_("Failed to query %s"), filename); *error = gplugin_python3_exception_to_gerror(); /* clean some stuff up */ pyg_gil_state_release(state); /* clean some stuff up */ /* at this point we have the module, lets find the query, load, and unload module_dict = PyModule_GetDict(module); query = PyDict_GetItemString(module_dict, "gplugin_query"); _("Failed to find the gplugin_query function in %s"), pyg_gil_state_release(state); if(!PyCallable_Check(query)) { _("Found gplugin_query in %s but it is not a " pyg_gil_state_release(state); load = PyDict_GetItemString(module_dict, "gplugin_load"); _("Failed to find the gplugin_load function in %s"), pyg_gil_state_release(state); if(!PyCallable_Check(load)) { _("Found gplugin_load in %s but it is not a " pyg_gil_state_release(state); unload = PyDict_GetItemString(module_dict, "gplugin_unload"); _("Failed to find the gplugin_unload function in %s"), pyg_gil_state_release(state); if(!PyCallable_Check(unload)) { _("Found gplugin_unload in %s but it is not a " pyg_gil_state_release(state); /* now that we have everything, call the query method and get the plugin's pyinfo = PyObject_Call(query, args, NULL); info = pygobject_get(pyinfo); /* now that we have everything, create the plugin */ GPLUGIN_PYTHON3_TYPE_PLUGIN, pyg_gil_state_release(state); gplugin_python3_loader_load( G_GNUC_UNUSED GPluginLoader *loader, PyObject *load = NULL, *pyplugin = NULL, *result = NULL; g_object_get(G_OBJECT(plugin), "load-func", &load, NULL); pyplugin = pygobject_new(G_OBJECT(plugin)); result = PyObject_CallFunctionObjArgs(load, pyplugin, NULL); *error = gplugin_python3_exception_to_gerror(); ret = PyObject_IsTrue(result); _("Failed to load plugin")); gplugin_python3_loader_unload( G_GNUC_UNUSED GPluginLoader *loader, PyObject *unload = NULL, *result = NULL; PyObject *pyplugin = NULL, *pyshutdown = NULL; g_object_get(G_OBJECT(plugin), "unload-func", &unload, NULL); pyplugin = pygobject_new(G_OBJECT(plugin)); pyshutdown = PyBool_FromLong(shutdown); result = PyObject_CallFunctionObjArgs(unload, pyplugin, pyshutdown, NULL); *error = gplugin_python3_exception_to_gerror(); ret = PyObject_IsTrue(result); _("Failed to unload plugin")); /****************************************************************************** *****************************************************************************/ gplugin_python3_loader_init_pygobject(void) PyObject *type = NULL, *value = NULL, *tb = NULL, *obj = NULL; PyErr_Fetch(&type, &value, &tb); obj = PyUnicode_AsUTF8String(value); g_warning("Failed to initialize PyGObject : %s", PyBytes_AsString(obj)); /* disable g_log redirections */ pyg_disable_warning_redirections(); gplugin_python3_loader_init_gettext(void) PyObject *module_dict = NULL, *install = NULL; PyObject *gettext = NULL, *result = NULL; gettext = PyImport_ImportModule("gettext"); g_warning("Failed to import gettext"); module_dict = PyModule_GetDict(gettext); install = PyDict_GetItemString(module_dict, "install"); result = PyObject_CallFunction(install, "ss", GETTEXT_PACKAGE, LOCALEDIR); gplugin_python3_loader_init_python(void) wchar_t *argv[] = {NULL, NULL}; /* Initializes Python3 */ argv[0] = Py_DecodeLocale(g_get_prgname(), NULL); g_warning("Could not convert program name to wchar_t string."); /* setup sys.path according to * https://docs.python.org/3/c-api/init.html#PySys_SetArgvEx PySys_SetArgvEx(1, argv, 0); /* initialize pygobject */ if(gplugin_python3_loader_init_pygobject()) { if(gplugin_python3_loader_init_gettext()) { /****************************************************************************** *****************************************************************************/ gplugin_python3_loader_init(G_GNUC_UNUSED GPluginPython3Loader *loader) gplugin_python3_loader_class_finalize( G_GNUC_UNUSED GPluginPython3LoaderClass *klass) gplugin_python3_loader_class_init(GPluginPython3LoaderClass *klass) GPluginLoaderClass *loader_class = GPLUGIN_LOADER_CLASS(klass); loader_class->supported_extensions = gplugin_python3_loader_supported_extensions; loader_class->query = gplugin_python3_loader_query; loader_class->load = gplugin_python3_loader_load; loader_class->unload = gplugin_python3_loader_unload; /****************************************************************************** *****************************************************************************/ gplugin_python3_loader_register(GTypeModule *module) gplugin_python3_loader_register_type(module); gplugin_python3_loader_init_python(); gplugin_python3_loader_new(void) return GPLUGIN_LOADER(g_object_new( GPLUGIN_PYTHON3_TYPE_LOADER,