Python plugin: Improve error reporting during plugin init
[claws.git] / src / plugins / python / foldertype.c
1 /* Python plugin for Claws-Mail
2  * Copyright (C) 2009 Holger Berndt
3  *
4  * This program is free software; you can redistribute it and/or modify
5  * it under the terms of the GNU General Public License as published by
6  * the Free Software Foundation; either version 3 of the License, or
7  * (at your option) any later version.
8  *
9  * This program is distributed in the hope that it will be useful,
10  * but WITHOUT ANY WARRANTY; without even the implied warranty of
11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12  * GNU General Public License for more details.
13  *
14  * You should have received a copy of the GNU General Public License
15  * along with this program. If not, see <http://www.gnu.org/licenses/>.
16  */
17
18 #ifdef HAVE_CONFIG_H
19 #  include "config.h"
20 #include "claws-features.h"
21 #endif
22
23 #include <glib/gi18n.h>
24
25 #include "foldertype.h"
26 #include "messageinfotype.h"
27
28 #include <structmember.h>
29
30
31 typedef struct {
32     PyObject_HEAD
33     PyObject *name;
34     PyObject *path;
35     PyObject *mailbox_name;
36     FolderItem *folderitem;
37 } clawsmail_FolderObject;
38
39
40 static void Folder_dealloc(clawsmail_FolderObject* self)
41 {
42   Py_XDECREF(self->name);
43   Py_XDECREF(self->path);
44   Py_XDECREF(self->mailbox_name);
45   self->ob_type->tp_free((PyObject*)self);
46 }
47
48 #define FOLDERITEM_STRING_TO_PYTHON_FOLDER_MEMBER(self,fis, pms)    \
49   do {                                                              \
50     if(fis) {                                                       \
51       PyObject *str;                                                \
52       str = PyString_FromString(fis);                               \
53       if(str) {                                                     \
54         int retval;                                                 \
55         retval = PyObject_SetAttrString((PyObject*)self, pms, str); \
56         Py_DECREF(str);                                             \
57         if(retval == -1)                                            \
58           goto err;                                                 \
59       }                                                             \
60     }                                                               \
61   } while(0)
62
63 static int Folder_init(clawsmail_FolderObject *self, PyObject *args, PyObject *kwds)
64 {
65   const char *ss = NULL;
66   FolderItem *folderitem = NULL;
67   char create = 0;
68
69   /* optional constructor argument: folderitem id string */
70   if(!PyArg_ParseTuple(args, "|sb", &ss, &create))
71     return -1;
72
73   Py_INCREF(Py_None);
74   self->name = Py_None;
75
76   Py_INCREF(Py_None);
77   self->path = Py_None;
78
79   Py_INCREF(Py_None);
80   self->mailbox_name = Py_None;
81
82   if(ss) {
83     if(create == 0) {
84       folderitem = folder_find_item_from_identifier(ss);
85       if(!folderitem) {
86         PyErr_SetString(PyExc_ValueError, "A folder with that path does not exist, and the create parameter was False.");
87         return -1;
88       }
89     }
90     else {
91       folderitem = folder_get_item_from_identifier(ss);
92       if(!folderitem) {
93         PyErr_SetString(PyExc_IOError, "A folder with that path does not exist, and could not be created.");
94         return -1;
95       }
96     }
97   }
98
99   if(folderitem) {
100     FOLDERITEM_STRING_TO_PYTHON_FOLDER_MEMBER(self, folderitem->name, "name");
101     FOLDERITEM_STRING_TO_PYTHON_FOLDER_MEMBER(self, folderitem->path, "path");
102     FOLDERITEM_STRING_TO_PYTHON_FOLDER_MEMBER(self, folderitem->folder->name, "mailbox_name");
103     self->folderitem = folderitem;
104   }
105
106   return 0;
107
108  err:
109   return -1;
110 }
111
112 static PyObject* Folder_str(PyObject *self)
113 {
114   PyObject *str;
115   str = PyString_FromString("Folder: ");
116   PyString_ConcatAndDel(&str, PyObject_GetAttrString(self, "name"));
117   return str;
118 }
119
120 static PyObject* Folder_get_identifier(clawsmail_FolderObject *self, PyObject *args)
121 {
122   PyObject *obj;
123   gchar *id;
124   if(!self->folderitem)
125     return NULL;
126   id = folder_item_get_identifier(self->folderitem);
127   obj = Py_BuildValue("s", id);
128   g_free(id);
129   return obj;
130 }
131
132 static PyObject* Folder_get_messages(clawsmail_FolderObject *self, PyObject *args)
133 {
134   GSList *msglist, *walk;
135   PyObject *retval;
136   Py_ssize_t pos;
137
138   if(!self->folderitem)
139     return NULL;
140
141   msglist = folder_item_get_msg_list(self->folderitem);
142   retval = PyTuple_New(g_slist_length(msglist));
143   if(!retval) {
144     procmsg_msg_list_free(msglist);
145     Py_INCREF(Py_None);
146     return Py_None;
147   }
148
149   for(pos = 0, walk = msglist; walk; walk = walk->next, ++pos) {
150     PyObject *msg;
151     msg = clawsmail_messageinfo_new(walk->data);
152     PyTuple_SET_ITEM(retval, pos, msg);
153   }
154   procmsg_msg_list_free(msglist);
155
156   return retval;
157 }
158
159 static PyMethodDef Folder_methods[] = {
160     {"get_identifier", (PyCFunction)Folder_get_identifier, METH_NOARGS,
161      "get_identifier() - get identifier\n"
162      "\n"
163      "Get identifier for folder as a string (e.g. #mh/foo/bar)."},
164     {"get_messages", (PyCFunction)Folder_get_messages, METH_NOARGS,
165      "get_messages() - get a tuple of messages in folder\n"
166      "\n"
167      "Get a tuple of MessageInfos for the folder."},
168     {NULL}
169 };
170
171 static PyMemberDef Folder_members[] = {
172   {"name", T_OBJECT_EX, offsetof(clawsmail_FolderObject, name), 0,
173    "name - name of folder"},
174
175   {"path", T_OBJECT_EX, offsetof(clawsmail_FolderObject, path), 0,
176    "path - path of folder"},
177
178   {"mailbox_name", T_OBJECT_EX, offsetof(clawsmail_FolderObject, mailbox_name), 0,
179    "mailbox_name - name of the corresponding mailbox"},
180
181   {NULL}
182 };
183
184 static PyTypeObject clawsmail_FolderType = {
185     PyObject_HEAD_INIT(NULL)
186     0,                         /* ob_size*/
187     "clawsmail.Folder",        /* tp_name*/
188     sizeof(clawsmail_FolderObject), /* tp_basicsize*/
189     0,                         /* tp_itemsize*/
190     (destructor)Folder_dealloc, /* tp_dealloc*/
191     0,                         /* tp_print*/
192     0,                         /* tp_getattr*/
193     0,                         /* tp_setattr*/
194     0,                         /* tp_compare*/
195     0,                         /* tp_repr*/
196     0,                         /* tp_as_number*/
197     0,                         /* tp_as_sequence*/
198     0,                         /* tp_as_mapping*/
199     0,                         /* tp_hash */
200     0,                         /* tp_call*/
201     Folder_str,                /* tp_str*/
202     0,                         /* tp_getattro*/
203     0,                         /* tp_setattro*/
204     0,                         /* tp_as_buffer*/
205     Py_TPFLAGS_DEFAULT,        /* tp_flags*/
206     "Folder objects.\n\n"      /* tp_doc */
207     "The __init__ function takes two optional arguments:\n"
208     "folder = Folder(identifier, [create_if_not_existing=False])\n"
209     "The identifier is an id string (e.g. '#mh/Mail/foo/bar'),"
210     "create_if_not_existing is a boolean expression.",
211     0,                         /* tp_traverse */
212     0,                         /* tp_clear */
213     0,                         /* tp_richcompare */
214     0,                         /* tp_weaklistoffset */
215     0,                         /* tp_iter */
216     0,                         /* tp_iternext */
217     Folder_methods,            /* tp_methods */
218     Folder_members,            /* tp_members */
219     0,                         /* tp_getset */
220     0,                         /* tp_base */
221     0,                         /* tp_dict */
222     0,                         /* tp_descr_get */
223     0,                         /* tp_descr_set */
224     0,                         /* tp_dictoffset */
225     (initproc)Folder_init,     /* tp_init */
226     0,                         /* tp_alloc */
227     0,                         /* tp_new */
228 };
229
230 gboolean cmpy_add_folder(PyObject *module)
231 {
232   clawsmail_FolderType.tp_new = PyType_GenericNew;
233   if(PyType_Ready(&clawsmail_FolderType) < 0)
234     return FALSE;
235
236   Py_INCREF(&clawsmail_FolderType);
237   return (PyModule_AddObject(module, "Folder", (PyObject*)&clawsmail_FolderType) == 0);
238 }
239
240 PyObject* clawsmail_folder_new(FolderItem *folderitem)
241 {
242   clawsmail_FolderObject *ff;
243   PyObject *arglist;
244   gchar *id;
245
246   if(!folderitem)
247     return NULL;
248
249   id = folder_item_get_identifier(folderitem);
250   arglist = Py_BuildValue("(s)", id);
251   g_free(id);
252   ff = (clawsmail_FolderObject*) PyObject_CallObject((PyObject*) &clawsmail_FolderType, arglist);
253   Py_DECREF(arglist);
254   return (PyObject*)ff;
255 }
256
257 FolderItem* clawsmail_folder_get_item(PyObject *self)
258 {
259   return ((clawsmail_FolderObject*)self)->folderitem;
260 }
261
262 PyTypeObject* clawsmail_folder_get_type_object()
263 {
264   return &clawsmail_FolderType;
265 }
266
267 gboolean clawsmail_folder_check(PyObject *self)
268 {
269   return (PyObject_TypeCheck(self, &clawsmail_FolderType) != 0);
270 }