1 /*
2 * gnm-python.c :
3 *
4 * Author: Zbigniew Chyla (cyba@gnome.pl)
5 */
6
7 #include <gnumeric-config.h>
8
9 #include "gnm-py-interpreter.h"
10 #include "gnm-python.h"
11 #include "py-gnumeric.h"
12
13 #include <goffice/goffice.h>
14 #include <goffice/app/module-plugin-defs.h>
15 #include <gsf/gsf-impl-utils.h>
16
17 #include <glib/gi18n-lib.h>
18 #include <unistd.h>
19
20 #include <Python.h>
21
22 struct _GnmPython {
23 GObject parent_instance;
24
25 GnmPyInterpreter *current_interpreter, *default_interpreter;
26 GSList *interpreters;
27 };
28
29 typedef struct {
30 GObjectClass parent_class;
31
32 void (*created_interpreter) (GnmPython *gpy, GnmPyInterpreter *interpreter);
33 void (*switched_interpreter) (GnmPython *gpy, GnmPyInterpreter *interpreter);
34 } GnmPythonClass;
35
36 enum {
37 CREATED_INTERPRETER_SIGNAL,
38 SWITCHED_INTERPRETER_SIGNAL,
39 LAST_SIGNAL
40 };
41
42 static guint signals[LAST_SIGNAL] = { 0 };
43 static GObjectClass *parent_class = NULL;
44
45 static GnmPython *gnm_python_obj = NULL;
46
47 static int
cb_test_signals(void)48 cb_test_signals (void)
49 {
50 if (PyErr_CheckSignals () < 0)
51 exit (0);
52 return TRUE;
53 }
54
55 static void
gnm_python_init(GnmPython * gpy)56 gnm_python_init (GnmPython *gpy)
57 {
58 gpy->default_interpreter = gnm_py_interpreter_new (NULL);
59 gpy->current_interpreter = gpy->default_interpreter;
60 gpy->interpreters = g_slist_append (NULL, gpy->default_interpreter);
61 g_return_if_fail (gnm_python_obj == NULL);
62 gnm_python_obj = gpy;
63 g_timeout_add_full (G_PRIORITY_LOW, 100, (GSourceFunc) cb_test_signals,
64 gnm_python_obj, NULL);
65 }
66
67 static void
gnm_python_finalize(GObject * obj)68 gnm_python_finalize (GObject *obj)
69 {
70 GnmPython *gpy = GNM_PYTHON (obj);
71
72 g_source_remove_by_user_data (gnm_python_obj);
73 if (gpy->default_interpreter != NULL) {
74 GSList *ints = g_slist_copy (gpy->interpreters);
75 GO_SLIST_FOREACH (ints, GnmPyInterpreter, interpreter,
76 if (interpreter != gpy->default_interpreter) {
77 gnm_py_interpreter_destroy (interpreter, gpy->default_interpreter);
78 }
79 );
80 g_slist_free (ints);
81 gnm_py_interpreter_switch_to (gpy->default_interpreter);
82 GO_SLIST_REMOVE (gpy->interpreters, gpy->default_interpreter);
83 g_object_unref (gpy->default_interpreter);
84 gpy->default_interpreter = NULL;
85 }
86 gnm_python_obj = NULL;
87
88 parent_class->finalize (obj);
89 }
90
91 static void
gnm_python_class_init(GObjectClass * gobject_class)92 gnm_python_class_init (GObjectClass *gobject_class)
93 {
94 parent_class = g_type_class_peek_parent (gobject_class);
95
96 gobject_class->finalize = gnm_python_finalize;
97
98 signals[CREATED_INTERPRETER_SIGNAL] =
99 g_signal_new (
100 "created_interpreter",
101 G_TYPE_FROM_CLASS (gobject_class),
102 G_SIGNAL_RUN_FIRST,
103 G_STRUCT_OFFSET (GnmPythonClass, created_interpreter),
104 NULL, NULL,
105 g_cclosure_marshal_VOID__POINTER,
106 G_TYPE_NONE,
107 1, G_TYPE_POINTER);
108 signals[SWITCHED_INTERPRETER_SIGNAL] =
109 g_signal_new (
110 "switched_interpreter",
111 G_TYPE_FROM_CLASS (gobject_class),
112 G_SIGNAL_RUN_FIRST,
113 G_STRUCT_OFFSET (GnmPythonClass, switched_interpreter),
114 NULL, NULL,
115 g_cclosure_marshal_VOID__POINTER,
116 G_TYPE_NONE,
117 1, G_TYPE_POINTER);
118 }
119
120 /* ---------- */
121
122 GnmPython *
gnm_python_object_get(GOErrorInfo ** err)123 gnm_python_object_get (GOErrorInfo **err)
124 {
125 GO_INIT_RET_ERROR_INFO (err);
126 if (!Py_IsInitialized ()) {
127 PyImport_AppendInittab ("Gnumeric", py_initgnumeric);
128 Py_InitializeEx (1);
129 #ifdef WITH_THREAD
130 PyEval_InitThreads ();
131 #endif
132 }
133 if (err && *err != NULL) {
134 Py_Finalize ();
135 return NULL;
136 }
137
138 if (gnm_python_obj == NULL) {
139 (void) g_object_new (GNM_PYTHON_TYPE, NULL);
140 } else {
141 g_object_ref (gnm_python_obj);
142 }
143
144 return gnm_python_obj;
145 }
146
147 static void
cb_interpreter_switched(GnmPyInterpreter * interpreter,GnmPython * gpy)148 cb_interpreter_switched (GnmPyInterpreter *interpreter, GnmPython *gpy)
149 {
150 g_return_if_fail (GNM_IS_PY_INTERPRETER (interpreter));
151 g_return_if_fail (GNM_IS_PYTHON (gpy));
152
153 gpy->current_interpreter = interpreter;
154 g_signal_emit (
155 gpy, signals[SWITCHED_INTERPRETER_SIGNAL], 0, interpreter);
156 }
157
158 GnmPyInterpreter *
gnm_python_new_interpreter(GnmPython * gpy,GOPlugin * plugin)159 gnm_python_new_interpreter (GnmPython *gpy, GOPlugin *plugin)
160 {
161 GnmPyInterpreter *interpreter;
162
163 g_return_val_if_fail (GNM_IS_PYTHON (gpy), NULL);
164 g_return_val_if_fail (GO_IS_PLUGIN (plugin), NULL);
165
166 interpreter = gnm_py_interpreter_new (plugin);
167 GO_SLIST_PREPEND (gpy->interpreters, interpreter);
168 gpy->current_interpreter = interpreter;
169 g_signal_connect (
170 interpreter, "set_current", G_CALLBACK (cb_interpreter_switched), gpy);
171 g_signal_emit (gpy, signals[CREATED_INTERPRETER_SIGNAL], 0, interpreter);
172 g_object_ref (gpy);
173
174 return interpreter;
175 }
176
177 void
gnm_python_destroy_interpreter(GnmPython * gpy,GnmPyInterpreter * interpreter)178 gnm_python_destroy_interpreter (GnmPython *gpy, GnmPyInterpreter *interpreter)
179 {
180 g_return_if_fail (GNM_IS_PYTHON (gpy));
181 g_return_if_fail (GNM_IS_PY_INTERPRETER (interpreter));
182 g_return_if_fail (interpreter != gpy->default_interpreter);
183
184 GO_SLIST_REMOVE (gpy->interpreters, interpreter);
185 gnm_py_interpreter_destroy (interpreter, gpy->default_interpreter);
186 g_object_unref (gpy);
187 }
188
189 GnmPyInterpreter *
gnm_python_get_current_interpreter(GnmPython * gpy)190 gnm_python_get_current_interpreter (GnmPython *gpy)
191 {
192 g_return_val_if_fail (GNM_IS_PYTHON (gpy), NULL);
193
194 return gpy->current_interpreter;
195 }
196
197 GnmPyInterpreter *
gnm_python_get_default_interpreter(GnmPython * gpy)198 gnm_python_get_default_interpreter (GnmPython *gpy)
199 {
200 g_return_val_if_fail (GNM_IS_PYTHON (gpy), NULL);
201
202 return gpy->default_interpreter;
203 }
204
205 GSList *
gnm_python_get_interpreters(GnmPython * gpy)206 gnm_python_get_interpreters (GnmPython *gpy)
207 {
208 g_return_val_if_fail (GNM_IS_PYTHON (gpy), NULL);
209
210 return gpy->interpreters;
211 }
212
213 void
gnm_python_clear_error_if_needed(GnmPython * gpy)214 gnm_python_clear_error_if_needed (GnmPython *gpy)
215 {
216 g_return_if_fail (GNM_IS_PYTHON (gpy));
217
218 if (PyErr_Occurred () != NULL) {
219 PyErr_Clear ();
220 }
221 }
222
223 GSF_DYNAMIC_CLASS (GnmPython, gnm_python,
224 gnm_python_class_init, gnm_python_init,
225 G_TYPE_OBJECT)
226