Improve some sieve-related translations
[claws.git] / src / plugins / python / python-hooks.c
blob9d482f6e33abb4279a61773395aee7d4000524d1
1 /*
2 * Copyright (c) 2008-2009 Christian Hammond
3 * Copyright (c) 2008-2009 David Trowbridge
5 * Permission is hereby granted, free of charge, to any person obtaining a
6 * copy of this software and associated documentation files (the "Software"),
7 * to deal in the Software without restriction, including without limitation
8 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
9 * and/or sell copies of the Software, and to permit persons to whom the
10 * Software is furnished to do so, subject to the following conditions:
12 * The above copyright notice and this permission notice shall be included
13 * in all copies or substantial portions of the Software.
15 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
21 * THE SOFTWARE.
23 #ifdef HAVE_CONFIG_H
24 # include "config.h"
25 #include "claws-features.h"
26 #endif
28 #ifdef ENABLE_PYTHON
29 #include <Python.h>
30 #include <pygobject.h>
31 #endif // ENABLE_PYTHON
33 #include <glib.h>
34 #include <glib/gi18n.h>
36 #include <dlfcn.h>
38 #include <signal.h>
40 #include "python-hooks.h"
43 static gboolean python_enabled = FALSE;
44 static void *python_dlhandle = NULL;
46 #ifdef ENABLE_PYTHON
47 static GString *captured_stdout = NULL;
48 static GString *captured_stderr = NULL;
51 static PyObject *
52 capture_stdout(PyObject *self, PyObject *args)
54 char *str = NULL;
56 if (!PyArg_ParseTuple(args, "s", &str))
57 return NULL;
59 g_string_append(captured_stdout, str);
61 Py_INCREF(Py_None);
62 return Py_None;
65 static PyObject *
66 capture_stderr(PyObject *self, PyObject *args)
68 char *str = NULL;
70 if (!PyArg_ParseTuple(args, "s", &str))
71 return NULL;
73 g_string_append(captured_stderr, str);
75 Py_INCREF(Py_None);
76 return Py_None;
79 static PyObject *
80 capture_stdin(PyObject *self, PyObject *args)
82 /* Return an empty string.
83 * This is what read() returns when hitting EOF. */
84 return PyUnicode_FromString("");
87 static PyObject *
88 wrap_gobj(PyObject *self, PyObject *args)
90 void *addr;
91 GObject *obj;
93 if (!PyArg_ParseTuple(args, "l", &addr))
94 return NULL;
96 if (!G_IS_OBJECT(addr))
97 return NULL; // XXX
99 obj = G_OBJECT(addr);
101 if (!obj)
102 return NULL; // XXX
104 return pygobject_new(obj);
107 static PyMethodDef parasite_python_methods[] = {
108 {"capture_stdout", capture_stdout, METH_VARARGS, "Captures stdout"},
109 {"capture_stderr", capture_stderr, METH_VARARGS, "Captures stderr"},
110 {"capture_stdin", capture_stdin, METH_VARARGS, "Captures stdin"},
111 {"gobj", wrap_gobj, METH_VARARGS, "Wraps a C GObject"},
112 {NULL, NULL, 0, NULL}
116 static gboolean
117 is_blacklisted(void)
119 const char *prgname = g_get_prgname();
121 return (!strcmp(prgname, "gimp"));
123 #endif // ENABLE_PYTHON
125 static struct PyModuleDef moduledef = {
126 PyModuleDef_HEAD_INIT,
127 "parasite",
128 NULL,
130 parasite_python_methods,
131 NULL,
132 NULL,
133 NULL,
134 NULL
137 PyMODINIT_FUNC
138 parasite_python_module_init(void)
140 #ifdef ENABLE_PYTHON
141 return PyModule_Create(&moduledef);
142 #endif // ENABLE_PYTHON
143 return NULL;
147 parasite_python_init(char **error)
149 #ifdef ENABLE_PYTHON
150 struct sigaction old_sigint;
151 PyObject *pygtk;
153 if (is_blacklisted()) {
154 *error = g_strdup("Application is blacklisted");
155 return 0;
158 /* This prevents errors such as "undefined symbol: PyExc_ImportError" */
159 python_dlhandle = dlopen(PYTHON_SHARED_LIB, RTLD_NOW | RTLD_GLOBAL);
160 if (python_dlhandle == NULL)
162 *error = g_strdup_printf("Parasite: Error on dlopen(): %s\n", dlerror());
163 return 0;
166 captured_stdout = g_string_new("");
167 captured_stderr = g_string_new("");
169 /* Back up and later restore SIGINT so Python doesn't steal it from us. */
170 sigaction(SIGINT, NULL, &old_sigint);
172 if (!Py_IsInitialized())
173 Py_Initialize();
175 sigaction(SIGINT, &old_sigint, NULL);
177 if(PyRun_SimpleString(
178 "import parasite\n"
179 "import sys\n"
180 "\n"
181 "class StdoutCatcher:\n"
182 " def write(self, str):\n"
183 " parasite.capture_stdout(str)\n"
184 " def flush(self):\n"
185 " pass\n"
186 "\n"
187 "class StderrCatcher:\n"
188 " def write(self, str):\n"
189 " parasite.capture_stderr(str)\n"
190 " def flush(self):\n"
191 " pass\n"
192 "\n"
193 "class StdinCatcher:\n"
194 " def readline(self, size=-1):\n"
195 " return parasite.capture_stdin(size)\n"
196 " def read(self, size=-1):\n"
197 " return parasite.capture_stdin(size)\n"
198 " def flush(self):\n"
199 " pass\n"
200 "\n"
201 ) == -1) {
202 dlclose(python_dlhandle);
203 python_dlhandle = NULL;
204 return 0;
207 pygtk = PyImport_ImportModule("gi");
209 if (pygtk == NULL)
211 *error = g_strdup("Parasite: Could not import gi");
212 dlclose(python_dlhandle);
213 python_dlhandle = NULL;
214 return 0;
217 python_enabled = TRUE;
218 #endif // ENABLE_PYTHON
219 return !0;
222 void
223 parasite_python_done(void)
225 #ifdef ENABLE_PYTHON
226 if(python_dlhandle != NULL) {
227 dlclose(python_dlhandle);
228 python_dlhandle = NULL;
230 #endif
233 void
234 parasite_python_run(const char *command,
235 ParasitePythonLogger stdout_logger,
236 ParasitePythonLogger stderr_logger,
237 gpointer user_data)
239 #ifdef ENABLE_PYTHON
240 PyGILState_STATE gstate;
241 PyObject *module;
242 PyObject *dict;
243 PyObject *obj;
244 const char *cp;
246 /* empty string as command is a noop */
247 if(!strcmp(command, ""))
248 return;
250 /* if first non-whitespace character is '#', command is also a noop */
251 cp = command;
252 while(cp && (*cp != '\0') && g_ascii_isspace(*cp))
253 cp++;
254 if(cp && *cp == '#')
255 return;
257 gstate = PyGILState_Ensure();
259 module = PyImport_AddModule("__main__");
260 dict = PyModule_GetDict(module);
262 PyRun_SimpleString("old_stdout = sys.stdout\n"
263 "old_stderr = sys.stderr\n"
264 "old_stdin = sys.stdin\n"
265 "sys.stdout = StdoutCatcher()\n"
266 "sys.stderr = StderrCatcher()\n"
267 "sys.stdin = StdinCatcher()\n");
269 obj = PyRun_String(command, Py_single_input, dict, dict);
270 if(PyErr_Occurred())
271 PyErr_Print();
272 PyRun_SimpleString("sys.stdout = old_stdout\n"
273 "sys.stderr = old_stderr\n"
274 "sys.stdin = old_stdin\n");
276 if (stdout_logger != NULL)
277 stdout_logger(captured_stdout->str, user_data);
279 if (stderr_logger != NULL)
280 stderr_logger(captured_stderr->str, user_data);
282 // Print any returned object
283 if (obj != NULL && obj != Py_None) {
284 PyObject *repr = PyObject_Repr(obj);
285 if (repr != NULL) {
286 char *string = PyBytes_AsString(repr);
288 if (stdout_logger != NULL) {
289 stdout_logger(string, user_data);
290 stdout_logger("\n", user_data);
294 Py_XDECREF(repr);
296 Py_XDECREF(obj);
298 PyGILState_Release(gstate);
299 g_string_erase(captured_stdout, 0, -1);
300 g_string_erase(captured_stderr, 0, -1);
301 #endif // ENABLE_PYTHON
304 gboolean
305 parasite_python_is_enabled(void)
307 return python_enabled;
310 // vim: set et sw=4 ts=4: