{
Py_ssize_t size, iEl;
FolderItem *folderitem;
-
+
*list = NULL;
folderitem = clawsmail_folder_get_item(folder);
PyErr_SetString(PyExc_TypeError, "Argument must be a list of MessageInfo objects.");
return FALSE;
}
-
+
msginfo = clawsmail_messageinfo_get_msginfo(element);
if(!msginfo) {
PyErr_SetString(PyExc_LookupError, "Broken MessageInfo object.");
return FALSE;
}
-
+
procmsg_msginfo_set_to_folder(msginfo, folderitem);
*list = g_slist_prepend(*list, msginfo);
}
-
+
return TRUE;
}
PyObject *folder;
int retval;
GSList *list = NULL;
-
+
retval = PyArg_ParseTuple(args, "O!O!",
&PyList_Type, &messagelist,
clawsmail_folder_get_type_object(), &folder);
if(!retval )
- return NULL;
+ return NULL;
folder_item_update_freeze();
-
+
if(!get_message_list_for_move_or_copy(messagelist, folder, &list))
goto err;
-
- if(move)
+
+ if(move)
procmsg_move_messages(list);
else
procmsg_copy_messages(list);
-
+
folder_item_update_thaw();
g_slist_free(list);
Py_RETURN_NONE;
"\n"
"Returns the gtk.ActionGroup for the main window."},
- {"get_mainwindow_ui_manager", get_mainwindow_ui_manager, METH_NOARGS,
+ {"get_mainwindow_ui_manager", get_mainwindow_ui_manager, METH_NOARGS,
"get_mainwindow_ui_manager() - get ui manager of main window\n"
"\n"
"Returns the gtk.UIManager for the main window."},
{NULL, NULL, 0, NULL}
};
-static void initmiscstuff(PyObject *module)
+static gboolean add_miscstuff(PyObject *module)
{
+ gboolean retval;
PyObject *dict;
PyObject *res;
const char *cmd =
"\n";
dict = PyModule_GetDict(module);
res = PyRun_String(cmd, Py_file_input, dict, dict);
+ retval = (res != NULL);
Py_XDECREF(res);
+ return retval;
}
-void claws_mail_python_init(void)
+PyMODINIT_FUNC initclawsmail(void)
{
- if (!Py_IsInitialized())
- Py_Initialize();
+ gboolean ok = TRUE;
/* create module */
cm_module = Py_InitModule3("clawsmail", ClawsMailMethods,
"The interface to Claws Mail in this module is extended on a 'as-needed' basis.\n"
"If you're missing something specific, try contacting the author.");
+ /* add module member "compose_window" set to None */
+ Py_INCREF(Py_None);
+ PyModule_AddObject(cm_module, "compose window", Py_None);
+
/* initialize classes */
- initnode(cm_module);
- initcomposewindow(cm_module);
- initfolder(cm_module);
- initmessageinfo(cm_module);
+ ok = ok && cmpy_add_node(cm_module);
+ ok = ok && cmpy_add_composewindow(cm_module);
+ ok = ok && cmpy_add_folder(cm_module);
+ ok = ok && cmpy_add_messageinfo(cm_module);
/* initialize misc things */
- initmiscstuff(cm_module);
-
- PyRun_SimpleString("import clawsmail\n");
- PyRun_SimpleString("clawsmail.compose_window = None\n");
+ if(ok)
+ add_miscstuff(cm_module);
}
#include "compose.h"
+#ifndef PyMODINIT_FUNC
+# define PyMODINIT_FUNC void
+#endif
-void claws_mail_python_init(void);
+PyMODINIT_FUNC initclawsmail(void);
PyObject* get_gobj_from_address(gpointer addr);
void put_composewindow_into_module(Compose *compose);
0, /* tp_new */
};
-PyMODINIT_FUNC initcomposewindow(PyObject *module)
+gboolean cmpy_add_composewindow(PyObject *module)
{
- clawsmail_ComposeWindowType.tp_new = PyType_GenericNew;
- if(PyType_Ready(&clawsmail_ComposeWindowType) < 0)
- return;
+ clawsmail_ComposeWindowType.tp_new = PyType_GenericNew;
+ if(PyType_Ready(&clawsmail_ComposeWindowType) < 0)
+ return FALSE;
- Py_INCREF(&clawsmail_ComposeWindowType);
- PyModule_AddObject(module, "ComposeWindow", (PyObject*)&clawsmail_ComposeWindowType);
+ Py_INCREF(&clawsmail_ComposeWindowType);
+ return (PyModule_AddObject(module, "ComposeWindow", (PyObject*)&clawsmail_ComposeWindowType) == 0);
}
PyObject* clawsmail_compose_new(PyObject *module, Compose *compose)
#ifndef COMPOSEWINDOWTYPE_H
#define COMPOSEWINDOWTYPE_H
+#include <glib.h>
#include <Python.h>
#include "compose.h"
-#ifndef PyMODINIT_FUNC /* declarations for DLL import/export */
-#define PyMODINIT_FUNC void
-#endif
-PyMODINIT_FUNC initcomposewindow(PyObject *module);
+gboolean cmpy_add_composewindow(PyObject *module);
PyObject* clawsmail_compose_new(PyObject *module, Compose *compose);
#include "claws-features.h"
#endif
-#include <glib.h>
#include <glib/gi18n.h>
#include "foldertype.h"
/* optional constructor argument: folderitem id string */
if(!PyArg_ParseTuple(args, "|sb", &ss, &create))
return -1;
-
+
Py_INCREF(Py_None);
self->name = Py_None;
-
+
Py_INCREF(Py_None);
self->path = Py_None;
Py_INCREF(Py_None);
return Py_None;
}
-
+
for(pos = 0, walk = msglist; walk; walk = walk->next, ++pos) {
PyObject *msg;
msg = clawsmail_messageinfo_new(walk->data);
PyTuple_SET_ITEM(retval, pos, msg);
}
procmsg_msg_list_free(msglist);
-
+
return retval;
}
static PyMemberDef Folder_members[] = {
{"name", T_OBJECT_EX, offsetof(clawsmail_FolderObject, name), 0,
"name - name of folder"},
-
+
{"path", T_OBJECT_EX, offsetof(clawsmail_FolderObject, path), 0,
"path - path of folder"},
-
+
{"mailbox_name", T_OBJECT_EX, offsetof(clawsmail_FolderObject, mailbox_name), 0,
"mailbox_name - name of the corresponding mailbox"},
0, /* tp_new */
};
-PyMODINIT_FUNC initfolder(PyObject *module)
+gboolean cmpy_add_folder(PyObject *module)
{
- clawsmail_FolderType.tp_new = PyType_GenericNew;
- if(PyType_Ready(&clawsmail_FolderType) < 0)
- return;
+ clawsmail_FolderType.tp_new = PyType_GenericNew;
+ if(PyType_Ready(&clawsmail_FolderType) < 0)
+ return FALSE;
- Py_INCREF(&clawsmail_FolderType);
- PyModule_AddObject(module, "Folder", (PyObject*)&clawsmail_FolderType);
+ Py_INCREF(&clawsmail_FolderType);
+ return (PyModule_AddObject(module, "Folder", (PyObject*)&clawsmail_FolderType) == 0);
}
PyObject* clawsmail_folder_new(FolderItem *folderitem)
#ifndef FOLDERTYPE_H
#define FOLDERTYPE_H
+#include <glib.h>
#include <Python.h>
#include "folder.h"
-#ifndef PyMODINIT_FUNC /* declarations for DLL import/export */
-#define PyMODINIT_FUNC void
-#endif
-PyMODINIT_FUNC initfolder(PyObject *module);
+
+gboolean cmpy_add_folder(PyObject *module);
PyObject* clawsmail_folder_new(FolderItem *folderitem);
FolderItem* clawsmail_folder_get_item(PyObject *self);
#include "claws-features.h"
#endif
-#include <glib.h>
#include <glib/gi18n.h>
#include "messageinfotype.h"
0, /* tp_new */
};
-PyMODINIT_FUNC initmessageinfo(PyObject *module)
+gboolean cmpy_add_messageinfo(PyObject *module)
{
- clawsmail_MessageInfoType.tp_new = PyType_GenericNew;
- if(PyType_Ready(&clawsmail_MessageInfoType) < 0)
- return;
+ clawsmail_MessageInfoType.tp_new = PyType_GenericNew;
+ if(PyType_Ready(&clawsmail_MessageInfoType) < 0)
+ return FALSE;
- Py_INCREF(&clawsmail_MessageInfoType);
- PyModule_AddObject(module, "MessageInfo", (PyObject*)&clawsmail_MessageInfoType);
+ Py_INCREF(&clawsmail_MessageInfoType);
+ return (PyModule_AddObject(module, "MessageInfo", (PyObject*)&clawsmail_MessageInfoType) == 0);
}
#define MSGINFO_STRING_TO_PYTHON_MESSAGEINFO_MEMBER(fis, pms) \
#ifndef MESSAGEINFOTYPE_H
#define MESSAGEINFOTYPE_H
+#include <glib.h>
#include <Python.h>
#include "procmsg.h"
-#ifndef PyMODINIT_FUNC /* declarations for DLL import/export */
-#define PyMODINIT_FUNC void
-#endif
-
-PyMODINIT_FUNC initmessageinfo(PyObject *module);
+gboolean cmpy_add_messageinfo(PyObject *module);
PyObject* clawsmail_messageinfo_new(MsgInfo *msginfo);
MsgInfo* clawsmail_messageinfo_get_msginfo(PyObject *self);
#include "claws-features.h"
#endif
-#include <glib.h>
#include <glib/gi18n.h>
#include "nodetype.h"
#include <structmember.h>
-PyMODINIT_FUNC initnode(PyObject *module)
+/* returns true on success, false if an exception was thrown */
+gboolean cmpy_add_node(PyObject *module)
{
+ gboolean retval;
PyObject *dict;
PyObject *res;
const char *cmd =
PyDict_SetItemString(dict, "__builtins__", PyEval_GetBuiltins());
res = PyRun_String(cmd, Py_file_input, dict, dict);
+
+ retval = (res != NULL);
Py_XDECREF(res);
+ return retval;
}
+
PyObject* clawsmail_node_new(PyObject *module)
{
PyObject *class, *dict;
#ifndef NODETYPE_H
#define NODETYPE_H
+#include <glib.h>
+
#include <Python.h>
-#ifndef PyMODINIT_FUNC /* declarations for DLL import/export */
-#define PyMODINIT_FUNC void
-#endif
-PyMODINIT_FUNC initnode(PyObject *module);
+gboolean cmpy_add_node(PyObject *module);
PyObject* clawsmail_node_new(PyObject *module);
}
#endif // ENABLE_PYTHON
-void
-parasite_python_init(void)
+int
+parasite_python_init(char **error)
{
#ifdef ENABLE_PYTHON
- int res;
struct sigaction old_sigint;
PyObject *pygtk;
- if (is_blacklisted())
- return;
+ if (is_blacklisted()) {
+ *error = g_strdup("Application is blacklisted");
+ return 0;
+ }
/* This prevents errors such as "undefined symbol: PyExc_ImportError" */
if (!dlopen(PYTHON_SHARED_LIB, RTLD_NOW | RTLD_GLOBAL))
{
- g_error("%s\n", dlerror());
- return;
+ *error = g_strdup_printf("Parasite: Error on dlopen(): %s\n", dlerror());
+ return 0;
}
captured_stdout = g_string_new("");
captured_stderr = g_string_new("");
/* Back up and later restore SIGINT so Python doesn't steal it from us. */
- res = sigaction(SIGINT, NULL, &old_sigint);
+ sigaction(SIGINT, NULL, &old_sigint);
if (!Py_IsInitialized())
Py_Initialize();
- res = sigaction(SIGINT, &old_sigint, NULL);
+ sigaction(SIGINT, &old_sigint, NULL);
Py_InitModule("parasite", parasite_python_methods);
- PyRun_SimpleString(
+ if(PyRun_SimpleString(
"import parasite\n"
"import sys\n"
"\n"
" def flush(self):\n"
" pass\n"
"\n"
- );
+ ) == -1)
+ return 0;
if (!pygobject_init(-1, -1, -1))
- return;
+ return 0;
pygtk = PyImport_ImportModule("gtk");
_PyGtk_API = (struct _PyGtk_FunctionStruct*)
PyCObject_AsVoidPtr(cobject);
else {
- PyErr_SetString(PyExc_RuntimeError,
- "could not find _PyGtk_API object");
- return;
+ *error = g_strdup("Parasite: Could not find _PyGtk_API object");
+ return 0;
}
}
} else {
- PyErr_SetString(PyExc_ImportError, "could not import gtk");
- return;
+ *error = g_strdup("Parasite: Could not import gtk");
+ return 0;
}
python_enabled = TRUE;
#endif // ENABLE_PYTHON
+ return !0;
}
void
typedef void (*ParasitePythonLogger)(const char *text, gpointer user_data);
-void parasite_python_init(void);
+int parasite_python_init(char **error);
void parasite_python_run(const char *command,
ParasitePythonLogger stdout_logger,
ParasitePythonLogger stderr_logger,
FILE *fp;
fp = fopen(filename, "r");
if(!fp) {
- g_print("Error: Could not open file '%s'\n", filename);
+ debug_print("Error: Could not open file '%s'\n", filename);
return;
}
put_composewindow_into_module(compose);
- PyRun_SimpleFile(fp, filename);
+ if(PyRun_SimpleFile(fp, filename) == 0)
+ debug_print("Problem running script file '%s'\n", filename);
fclose(fp);
}
gchar *dest_file;
dest_file = g_strconcat(dest_dir, G_DIR_SEPARATOR_S, filename, NULL);
if(move_file(filepath, dest_file, FALSE) == 0)
- g_print("Python plugin: Moved file '%s' to %s subdir\n", filename, PYTHON_SCRIPTS_MAIN_DIR);
+ debug_print("Python plugin: Moved file '%s' to %s subdir\n", filename, PYTHON_SCRIPTS_MAIN_DIR);
else
- g_print("Python plugin: Warning: Could not move file '%s' to %s subdir\n", filename, PYTHON_SCRIPTS_MAIN_DIR);
+ debug_print("Python plugin: Warning: Could not move file '%s' to %s subdir\n", filename, PYTHON_SCRIPTS_MAIN_DIR);
g_free(dest_file);
}
g_free(filepath);
g_free(scripts_dir);
if(!dir) {
- g_print("Could not open directory '%s': %s\n", subdir, error->message);
+ debug_print("Could not open directory '%s': %s\n", subdir, error->message);
g_error_free(error);
return;
}
{"Tools/PythonScripts/---", NULL, "---" },
};
-static void python_menu_init(void)
+static int python_menu_init(char **error)
{
MainWindow *mainwin;
guint id;
mainwin = mainwindow_get_mainwindow();
+ if(!mainwin) {
+ *error = g_strdup("Could not get main window");
+ return 0;
+ }
gtk_action_group_add_toggle_actions(mainwin->action_group, mainwindow_tools_python_toggle, 1, mainwin);
gtk_action_group_add_actions(mainwin->action_group, mainwindow_tools_python_actions, 3, mainwin);
menu_id_list = g_slist_prepend(menu_id_list, GUINT_TO_POINTER(id));
refresh_python_scripts_menus(NULL, NULL);
+
+ return !0;
}
static void python_menu_done(void)
}
}
+
+static PyObject *get_StringIO_instance(void)
+{
+ PyObject *module_StringIO = NULL;
+ PyObject *class_StringIO = NULL;
+ PyObject *inst_StringIO = NULL;
+
+ module_StringIO = PyImport_ImportModule("cStringIO");
+ if(!module_StringIO) {
+ debug_print("Error getting traceback: Could not import module cStringIO\n");
+ goto done;
+ }
+
+ class_StringIO = PyObject_GetAttrString(module_StringIO, "StringIO");
+ if(!class_StringIO) {
+ debug_print("Error getting traceback: Could not get StringIO class\n");
+ goto done;
+ }
+
+ inst_StringIO = PyObject_CallObject(class_StringIO, NULL);
+ if(!inst_StringIO) {
+ debug_print("Error getting traceback: Could not create an instance of the StringIO class\n");
+ goto done;
+ }
+
+done:
+ Py_XDECREF(module_StringIO);
+ Py_XDECREF(class_StringIO);
+
+ return inst_StringIO;
+}
+
+static char* get_exception_information(PyObject *inst_StringIO)
+{
+ char *retval = NULL;
+ PyObject *meth_getvalue = NULL;
+ PyObject *result_getvalue = NULL;
+
+ if(!inst_StringIO)
+ goto done;
+
+ if(PySys_SetObject("stderr", inst_StringIO) != 0) {
+ debug_print("Error getting traceback: Could not set sys.stderr to a StringIO instance\n");
+ goto done;
+ }
+
+ meth_getvalue = PyObject_GetAttrString(inst_StringIO, "getvalue");
+ if(!meth_getvalue) {
+ debug_print("Error getting traceback: Could not get the getvalue method of the StringIO instance\n");
+ goto done;
+ }
+
+ PyErr_Print();
+
+ result_getvalue = PyObject_CallObject(meth_getvalue, NULL);
+ if(!result_getvalue) {
+ debug_print("Error getting traceback: Could not call the getvalue method of the StringIO instance\n");
+ goto done;
+ }
+
+ retval = g_strdup(PyString_AsString(result_getvalue));
+
+done:
+
+ Py_XDECREF(meth_getvalue);
+ Py_XDECREF(result_getvalue);
+
+ return retval ? retval : g_strdup("Unspecified error occured");
+}
+
+
gint plugin_init(gchar **error)
{
+ PyObject *inst_StringIO = NULL;
+
/* Version check */
if(!check_plugin_version(MAKE_NUMERIC_VERSION(3,7,6,9), VERSION_NUMERIC, _("Python"), error))
return -1;
/* script directories */
if(!make_sure_directories_exist(error))
- return -1;
+ goto err;
/* initialize python interpreter */
Py_Initialize();
- /* initialize python interactive shell */
- parasite_python_init();
+ /* The Python C API only offers to print an exception to sys.stderr. In order to catch it
+ * in a string, a StringIO object is created, to which sys.stderr can be redirected in case
+ * an error occured. */
+ inst_StringIO = get_StringIO_instance();
/* initialize Claws Mail Python module */
- claws_mail_python_init();
+ initclawsmail();
+ if(PyErr_Occurred()) {
+ *error = get_exception_information(inst_StringIO);
+ goto err;
+ }
+
+ if(PyRun_SimpleString("import clawsmail") == -1) {
+ *error = g_strdup("Error importing the clawsmail module");
+ goto err;
+ }
+
+ /* initialize python interactive shell */
+ if(!parasite_python_init(error)) {
+ goto err;
+ }
/* load menu options */
- python_menu_init();
+ if(!python_menu_init(error)) {
+ goto err;
+ }
+ /* problems here are not fatal */
run_auto_script_file_if_it_exists(PYTHON_SCRIPTS_AUTO_STARTUP, NULL);
debug_print("Python plugin loaded\n");
return 0;
+
+err:
+ hooks_unregister_hook(COMPOSE_CREATED_HOOKLIST, hook_compose_create);
+ Py_XDECREF(inst_StringIO);
+ return -1;
}
gboolean plugin_done(void)