Python plugin: Improve error reporting during plugin init
authorHolger Berndt <hb@claws-mail.org>
Tue, 11 Jun 2013 21:27:28 +0000 (23:27 +0200)
committerHolger Berndt <hb@claws-mail.org>
Tue, 11 Jun 2013 21:29:25 +0000 (23:29 +0200)
13 files changed:
src/plugins/python/clawsmailmodule.c
src/plugins/python/clawsmailmodule.h
src/plugins/python/composewindowtype.c
src/plugins/python/composewindowtype.h
src/plugins/python/foldertype.c
src/plugins/python/foldertype.h
src/plugins/python/messageinfotype.c
src/plugins/python/messageinfotype.h
src/plugins/python/nodetype.c
src/plugins/python/nodetype.h
src/plugins/python/python-hooks.c
src/plugins/python/python-hooks.h
src/plugins/python/python_plugin.c

index e0a3a5d0d17d7743da0fde556a1b0d9c225bb47b..c34283e909cb9a9988a036f3f758199b00e577e1 100644 (file)
@@ -519,7 +519,7 @@ static gboolean get_message_list_for_move_or_copy(PyObject *messagelist, PyObjec
 {
   Py_ssize_t size, iEl;
   FolderItem *folderitem;
 {
   Py_ssize_t size, iEl;
   FolderItem *folderitem;
-  
+
   *list = NULL;
 
   folderitem = clawsmail_folder_get_item(folder);
   *list = NULL;
 
   folderitem = clawsmail_folder_get_item(folder);
@@ -537,17 +537,17 @@ static gboolean get_message_list_for_move_or_copy(PyObject *messagelist, PyObjec
       PyErr_SetString(PyExc_TypeError, "Argument must be a list of MessageInfo objects.");
       return FALSE;
     }
       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;
     }
     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);
   }
     procmsg_msginfo_set_to_folder(msginfo, folderitem);
     *list = g_slist_prepend(*list, msginfo);
   }
+
   return TRUE;
 }
 
   return TRUE;
 }
 
@@ -557,23 +557,23 @@ static PyObject* move_or_copy_messages(PyObject *self, PyObject *args, gboolean
   PyObject *folder;
   int retval;
   GSList *list = NULL;
   PyObject *folder;
   int retval;
   GSList *list = NULL;
-  
+
   retval = PyArg_ParseTuple(args, "O!O!",
     &PyList_Type, &messagelist,
     clawsmail_folder_get_type_object(), &folder);
   if(!retval )
   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();
 
   folder_item_update_freeze();
-  
+
   if(!get_message_list_for_move_or_copy(messagelist, folder, &list))
     goto err;
   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);
     procmsg_move_messages(list);
   else
     procmsg_copy_messages(list);
-      
+
   folder_item_update_thaw();
   g_slist_free(list);
   Py_RETURN_NONE;
   folder_item_update_thaw();
   g_slist_free(list);
   Py_RETURN_NONE;
@@ -602,7 +602,7 @@ static PyMethodDef ClawsMailMethods[] = {
      "\n"
      "Returns the gtk.ActionGroup for the main window."},
 
      "\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."},
      "get_mainwindow_ui_manager() - get ui manager of main window\n"
      "\n"
      "Returns the gtk.UIManager for the main window."},
@@ -705,8 +705,9 @@ static PyMethodDef ClawsMailMethods[] = {
     {NULL, NULL, 0, NULL}
 };
 
     {NULL, NULL, 0, NULL}
 };
 
-static void initmiscstuff(PyObject *module)
+static gboolean add_miscstuff(PyObject *module)
 {
 {
+  gboolean retval;
   PyObject *dict;
   PyObject *res;
   const char *cmd =
   PyObject *dict;
   PyObject *res;
   const char *cmd =
@@ -719,14 +720,15 @@ static void initmiscstuff(PyObject *module)
       "\n";
   dict = PyModule_GetDict(module);
   res = PyRun_String(cmd, Py_file_input, dict, dict);
       "\n";
   dict = PyModule_GetDict(module);
   res = PyRun_String(cmd, Py_file_input, dict, dict);
+  retval = (res != NULL);
   Py_XDECREF(res);
   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,
 
   /* create module */
   cm_module = Py_InitModule3("clawsmail", ClawsMailMethods,
@@ -740,17 +742,19 @@ void claws_mail_python_init(void)
       "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.");
 
       "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 */
   /* 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 */
 
   /* initialize misc things */
-  initmiscstuff(cm_module);
-
-  PyRun_SimpleString("import clawsmail\n");
-  PyRun_SimpleString("clawsmail.compose_window = None\n");
+  if(ok)
+    add_miscstuff(cm_module);
 }
 
 
 }
 
 
index 21846a6d9310f9a13040767a740854917fa4cb1c..1f1056ffc80719a53f582284b433839d507bf3d4 100644 (file)
 
 #include "compose.h"
 
 
 #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);
 
 PyObject* get_gobj_from_address(gpointer addr);
 void put_composewindow_into_module(Compose *compose);
index 59ebeeadeb774ea127267ad61f85bb4869b5944f..110296bd38cbcecbfb6d19199fad5aa42453544b 100644 (file)
@@ -585,14 +585,14 @@ static PyTypeObject clawsmail_ComposeWindowType = {
     0,                         /* tp_new */
 };
 
     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)
 }
 
 PyObject* clawsmail_compose_new(PyObject *module, Compose *compose)
index 4d7b422a42adaeb326295d92c916b18d9540cb35..9de8546df9e249874b0356cea2555fb9a15054c3 100644 (file)
 #ifndef COMPOSEWINDOWTYPE_H
 #define COMPOSEWINDOWTYPE_H
 
 #ifndef COMPOSEWINDOWTYPE_H
 #define COMPOSEWINDOWTYPE_H
 
+#include <glib.h>
 #include <Python.h>
 
 #include "compose.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);
 
 
 PyObject* clawsmail_compose_new(PyObject *module, Compose *compose);
 
index 3d36223d0d0b8106a2822b443c3d548a0c9c0ef7..ccf580605ee68cda6eddf1c3d619b75afd38496d 100644 (file)
@@ -20,7 +20,6 @@
 #include "claws-features.h"
 #endif
 
 #include "claws-features.h"
 #endif
 
-#include <glib.h>
 #include <glib/gi18n.h>
 
 #include "foldertype.h"
 #include <glib/gi18n.h>
 
 #include "foldertype.h"
@@ -70,10 +69,10 @@ static int Folder_init(clawsmail_FolderObject *self, PyObject *args, PyObject *k
   /* optional constructor argument: folderitem id string */
   if(!PyArg_ParseTuple(args, "|sb", &ss, &create))
     return -1;
   /* 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->name = Py_None;
-  
+
   Py_INCREF(Py_None);
   self->path = Py_None;
 
   Py_INCREF(Py_None);
   self->path = Py_None;
 
@@ -146,14 +145,14 @@ static PyObject* Folder_get_messages(clawsmail_FolderObject *self, PyObject *arg
     Py_INCREF(Py_None);
     return 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);
   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;
 }
 
   return retval;
 }
 
@@ -172,10 +171,10 @@ static PyMethodDef Folder_methods[] = {
 static PyMemberDef Folder_members[] = {
   {"name", T_OBJECT_EX, offsetof(clawsmail_FolderObject, name), 0,
    "name - name of folder"},
 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"},
   {"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"},
 
   {"mailbox_name", T_OBJECT_EX, offsetof(clawsmail_FolderObject, mailbox_name), 0,
    "mailbox_name - name of the corresponding mailbox"},
 
@@ -228,14 +227,14 @@ static PyTypeObject clawsmail_FolderType = {
     0,                         /* tp_new */
 };
 
     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)
 }
 
 PyObject* clawsmail_folder_new(FolderItem *folderitem)
index 7a913b1ecaa8006fdfd881cbe4f80ff2fb9acfb5..d85d483dee00e226a0e5499a4d4faead1b93b803 100644 (file)
 #ifndef FOLDERTYPE_H
 #define FOLDERTYPE_H
 
 #ifndef FOLDERTYPE_H
 #define FOLDERTYPE_H
 
+#include <glib.h>
 #include <Python.h>
 
 #include "folder.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);
 
 PyObject* clawsmail_folder_new(FolderItem *folderitem);
 FolderItem* clawsmail_folder_get_item(PyObject *self);
index 766b29a1d69ed1c09167cc7cebede98d065db7af..77d5724ed13f44d8e8fc419e4a5a643d9f0f600b 100644 (file)
@@ -20,7 +20,6 @@
 #include "claws-features.h"
 #endif
 
 #include "claws-features.h"
 #endif
 
-#include <glib.h>
 #include <glib/gi18n.h>
 
 #include "messageinfotype.h"
 #include <glib/gi18n.h>
 
 #include "messageinfotype.h"
@@ -374,14 +373,14 @@ static PyTypeObject clawsmail_MessageInfoType = {
     0,                         /* tp_new */
 };
 
     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)     \
 }
 
 #define MSGINFO_STRING_TO_PYTHON_MESSAGEINFO_MEMBER(fis, pms)     \
index 1beb37ac98227735a3dbf44bdac8441380efb736..df3c217b1bf775e0ee002e2f1de3490b7aa0b1a8 100644 (file)
 #ifndef MESSAGEINFOTYPE_H
 #define MESSAGEINFOTYPE_H
 
 #ifndef MESSAGEINFOTYPE_H
 #define MESSAGEINFOTYPE_H
 
+#include <glib.h>
 #include <Python.h>
 
 #include "procmsg.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);
 
 PyObject* clawsmail_messageinfo_new(MsgInfo *msginfo);
 MsgInfo* clawsmail_messageinfo_get_msginfo(PyObject *self);
index 8bf8b650cb13fe3ffbe43051ee88777191eca4f4..60425f829786e0f440c629ba3a6d1051574dfdf0 100644 (file)
 #include "claws-features.h"
 #endif
 
 #include "claws-features.h"
 #endif
 
-#include <glib.h>
 #include <glib/gi18n.h>
 
 #include "nodetype.h"
 
 #include <structmember.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 =
   PyObject *dict;
   PyObject *res;
   const char *cmd =
@@ -85,9 +86,13 @@ PyMODINIT_FUNC initnode(PyObject *module)
     PyDict_SetItemString(dict, "__builtins__", PyEval_GetBuiltins());
 
   res = PyRun_String(cmd, Py_file_input, dict, dict);
     PyDict_SetItemString(dict, "__builtins__", PyEval_GetBuiltins());
 
   res = PyRun_String(cmd, Py_file_input, dict, dict);
+
+  retval = (res != NULL);
   Py_XDECREF(res);
   Py_XDECREF(res);
+  return retval;
 }
 
 }
 
+
 PyObject* clawsmail_node_new(PyObject *module)
 {
   PyObject *class, *dict;
 PyObject* clawsmail_node_new(PyObject *module)
 {
   PyObject *class, *dict;
index cb437e6789f2c912ad5af60c250531c7137e105b..03daa314f447dd887f52d3ecf5d9152162898b40 100644 (file)
 #ifndef NODETYPE_H
 #define NODETYPE_H
 
 #ifndef NODETYPE_H
 #define NODETYPE_H
 
+#include <glib.h>
+
 #include <Python.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);
 
 
 PyObject* clawsmail_node_new(PyObject *module);
 
index 24822b648b4c6587e61440ebff18d165d3de379a..f0228908bbd4341885112140dea9d1f01eeb52e0 100644 (file)
@@ -122,37 +122,38 @@ is_blacklisted(void)
 }
 #endif // ENABLE_PYTHON
 
 }
 #endif // ENABLE_PYTHON
 
-void
-parasite_python_init(void)
+int
+parasite_python_init(char **error)
 {
 #ifdef ENABLE_PYTHON
 {
 #ifdef ENABLE_PYTHON
-    int res;
     struct sigaction old_sigint;
     PyObject *pygtk;
 
     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))
     {
 
     /* 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. */
     }
 
     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();
 
 
     if (!Py_IsInitialized())
         Py_Initialize();
 
-    res = sigaction(SIGINT, &old_sigint, NULL);
+    sigaction(SIGINT, &old_sigint, NULL);
 
     Py_InitModule("parasite", parasite_python_methods);
 
     Py_InitModule("parasite", parasite_python_methods);
-    PyRun_SimpleString(
+    if(PyRun_SimpleString(
         "import parasite\n"
         "import sys\n"
         "\n"
         "import parasite\n"
         "import sys\n"
         "\n"
@@ -176,10 +177,11 @@ parasite_python_init(void)
         "    def flush(self):\n"
         "        pass\n"
         "\n"
         "    def flush(self):\n"
         "        pass\n"
         "\n"
-    );
+    ) == -1)
+      return 0;
 
     if (!pygobject_init(-1, -1, -1))
 
     if (!pygobject_init(-1, -1, -1))
-        return;
+        return 0;
 
     pygtk = PyImport_ImportModule("gtk");
 
 
     pygtk = PyImport_ImportModule("gtk");
 
@@ -198,18 +200,18 @@ parasite_python_init(void)
                 _PyGtk_API = (struct _PyGtk_FunctionStruct*)
                 PyCObject_AsVoidPtr(cobject);
             else {
                 _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 {
             }
         }
     } 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
     }
 
     python_enabled = TRUE;
 #endif // ENABLE_PYTHON
+    return !0;
 }
 
 void
 }
 
 void
index d6bf1bdf7d381db97e5272ed06c2eb80c08a6997..2744fc3507bc9509d35efdc771841c7f41e2c1ab 100644 (file)
@@ -28,7 +28,7 @@
 
 typedef void (*ParasitePythonLogger)(const char *text, gpointer user_data);
 
 
 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,
 void parasite_python_run(const char *command,
                          ParasitePythonLogger stdout_logger,
                          ParasitePythonLogger stderr_logger,
index 7becb932cafa9731b3dd3f269e145daff0314803..4cdba316faeafb48e98453dbb778736a506012a9 100644 (file)
@@ -160,11 +160,12 @@ static void run_script_file(const gchar *filename, Compose *compose)
   FILE *fp;
   fp = fopen(filename, "r");
   if(!fp) {
   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);
     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);
 }
 
   fclose(fp);
 }
 
@@ -297,9 +298,9 @@ static void migrate_scripts_out_of_base_dir(void)
       gchar *dest_file;
       dest_file = g_strconcat(dest_dir, G_DIR_SEPARATOR_S, filename, NULL);
       if(move_file(filepath, dest_file, FALSE) == 0)
       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
       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(dest_file);
     }
     g_free(filepath);
@@ -429,7 +430,7 @@ static void refresh_scripts_in_dir(const gchar *subdir, ToolbarType toolbar_type
   g_free(scripts_dir);
 
   if(!dir) {
   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;
   }
     g_error_free(error);
     return;
   }
@@ -506,12 +507,16 @@ static GtkActionEntry mainwindow_tools_python_actions[] = {
     {"Tools/PythonScripts/---", NULL, "---" },
 };
 
     {"Tools/PythonScripts/---", NULL, "---" },
 };
 
-static void python_menu_init(void)
+static int python_menu_init(char **error)
 {
   MainWindow *mainwin;
   guint id;
 
   mainwin =  mainwindow_get_mainwindow();
 {
   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);
 
   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);
@@ -537,6 +542,8 @@ static void python_menu_init(void)
   menu_id_list = g_slist_prepend(menu_id_list, GUINT_TO_POINTER(id));
 
   refresh_python_scripts_menus(NULL, NULL);
   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 void python_menu_done(void)
@@ -560,8 +567,81 @@ 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)
 {
 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;
   /* Version check */
   if(!check_plugin_version(MAKE_NUMERIC_VERSION(3,7,6,9), VERSION_NUMERIC, _("Python"), error))
     return -1;
@@ -575,25 +655,49 @@ gint plugin_init(gchar **error)
 
   /* script directories */
   if(!make_sure_directories_exist(error))
 
   /* script directories */
   if(!make_sure_directories_exist(error))
-    return -1;
+    goto err;
 
   /* initialize python interpreter */
   Py_Initialize();
 
 
   /* 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 */
 
   /* 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 */
 
   /* 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;
   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)
 }
 
 gboolean plugin_done(void)