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