1 /* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*-
3 * Copyright (C) 2005 Raphael Slinckx
5 * This program is free software; you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License as published by
7 * the Free Software Foundation; either version 2 of the License, or
8 * (at your option) any later version.
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
15 * You should have received a copy of the GNU General Public License
16 * along with this program; if not, write to the Free Software
17 * Foundation, Inc., 51 Franklin St, Fifth Floor,
18 * Boston, MA 02110-1301 USA.
25 #include <pygobject.h>
26 #include <pygtk/pygtk.h>
32 #include "rb-plugin.h"
33 #include "rb-python-module.h"
34 #include "rb-python-plugin.h"
37 #define RB_PYTHON_MODULE_GET_PRIVATE(object) (G_TYPE_INSTANCE_GET_PRIVATE ((object), \
38 RB_TYPE_PYTHON_MODULE, \
39 RBPythonModulePrivate))
46 } RBPythonModulePrivate
;
55 /* Exported by pyrhythmdb module */
56 void pyrhythmdb_register_classes (PyObject
*d
);
57 void pyrhythmdb_add_constants (PyObject
*module
, const gchar
*strip_prefix
);
58 extern PyMethodDef pyrhythmdb_functions
[];
60 /* Exported by pyrb module */
61 void pyrb_register_classes (PyObject
*d
);
62 void pyrb_add_constants (PyObject
*module
, const gchar
*strip_prefix
);
63 extern PyMethodDef pyrb_functions
[];
65 /* We retreive this to check for correct class hierarchy */
66 static PyTypeObject
*PyRBPlugin_Type
;
68 G_DEFINE_TYPE (RBPythonModule
, rb_python_module
, G_TYPE_TYPE_MODULE
);
71 rb_python_module_init_python (void)
73 PyObject
*pygtk
, *mdict
, *require
;
74 PyObject
*rb
, *rhythmdb
, *gtk
, *pygtk_version
, *pygtk_required_version
;
75 PyObject
*gettext
, *install
, *gettext_args
;
77 struct sigaction old_sigint
;
79 char *argv
[] = { "rb", "rhythmdb", NULL
};
82 if (Py_IsInitialized ()) {
83 g_warning ("Python Should only be initialized once, since it's in class_init");
84 g_return_if_reached ();
87 /* Hack to make python not overwrite SIGINT: this is needed to avoid
88 * the crash reported on gedit bug #326191 */
90 /* Save old handler */
91 res
= sigaction (SIGINT
, NULL
, &old_sigint
);
93 g_warning ("Error initializing Python interpreter: cannot get "
94 "handler to SIGINT signal (%s)",
100 /* Python initialization */
103 /* Restore old handler */
104 res
= sigaction (SIGINT
, &old_sigint
, NULL
);
106 g_warning ("Error initializing Python interpreter: cannot restore "
107 "handler to SIGINT signal (%s)",
112 PySys_SetArgv (1, argv
);
114 /* pygtk.require("2.8") */
115 pygtk
= PyImport_ImportModule ("pygtk");
117 g_warning ("Could not import pygtk");
122 mdict
= PyModule_GetDict (pygtk
);
123 require
= PyDict_GetItemString (mdict
, "require");
124 PyObject_CallObject (require
, Py_BuildValue ("(S)", PyString_FromString ("2.8")));
132 gtk
= PyImport_ImportModule ("gtk");
134 g_warning ("Could not import gtk");
139 mdict
= PyModule_GetDict (gtk
);
140 pygtk_version
= PyDict_GetItemString (mdict
, "pygtk_version");
141 pygtk_required_version
= Py_BuildValue ("(iii)", 2, 4, 0);
142 if (PyObject_Compare (pygtk_version
, pygtk_required_version
) == -1) {
143 g_warning("PyGTK %s required, but %s found.",
144 PyString_AsString (PyObject_Repr (pygtk_required_version
)),
145 PyString_AsString (PyObject_Repr (pygtk_version
)));
146 Py_DECREF (pygtk_required_version
);
149 Py_DECREF (pygtk_required_version
);
151 /* import rhythmdb */
152 rhythmdb
= Py_InitModule ("rhythmdb", pyrhythmdb_functions
);
153 mdict
= PyModule_GetDict (rhythmdb
);
155 pyrhythmdb_register_classes (mdict
);
156 pyrhythmdb_add_constants (rhythmdb
, "RHYTHMDB_");
159 paths
= rb_get_plugin_paths ();
160 sys_path
= PySys_GetObject ("path");
161 while (paths
!= NULL
) {
164 path
= PyString_FromString (paths
->data
);
165 if (PySequence_Contains (sys_path
, path
) == 0) {
166 PyList_Insert (sys_path
, 0, path
);
169 g_free (paths
->data
);
170 paths
= g_list_delete_link (paths
, paths
);
173 rb
= PyImport_ImportModule ("rb");
176 g_warning ("could not import python module 'rb'");
181 /* add pyrb_functions */
182 for (res
= 0; pyrb_functions
[res
].ml_name
!= NULL
; res
++) {
185 func
= PyCFunction_New (&pyrb_functions
[res
], rb
);
187 g_warning ("unable object for function '%s' create", pyrb_functions
[res
].ml_name
);
191 if (PyModule_AddObject (rb
, pyrb_functions
[res
].ml_name
, func
) < 0) {
192 g_warning ("unable to insert function '%s' in 'rb' module", pyrb_functions
[res
].ml_name
);
197 mdict
= PyModule_GetDict (rb
);
199 pyrb_register_classes (mdict
);
200 pyrb_add_constants (rb
, "RB_");
202 /* Retreive the Python type for rb.Plugin */
203 PyRBPlugin_Type
= (PyTypeObject
*) PyDict_GetItemString (mdict
, "Plugin");
204 if (PyRBPlugin_Type
== NULL
) {
210 gettext
= PyImport_ImportModule ("gettext");
211 if (gettext
== NULL
) {
212 g_warning ("Could not import gettext");
217 mdict
= PyModule_GetDict (gettext
);
218 install
= PyDict_GetItemString (mdict
, "install");
219 gettext_args
= Py_BuildValue ("ss", GETTEXT_PACKAGE
, GNOMELOCALEDIR
);
220 PyObject_CallObject (install
, gettext_args
);
221 Py_DECREF (gettext_args
);
225 rb_python_module_load (GTypeModule
*gmodule
)
227 RBPythonModulePrivate
*priv
= RB_PYTHON_MODULE_GET_PRIVATE (gmodule
);
228 PyObject
*main_module
, *main_locals
, *locals
, *key
, *value
;
229 PyObject
*module
, *fromlist
;
232 main_module
= PyImport_AddModule ("__main__");
233 if (main_module
== NULL
)
235 g_warning ("Could not get __main__.");
239 /* If we have a special path, we register it */
240 if (priv
->path
!= NULL
)
242 PyObject
*sys_path
= PySys_GetObject ("path");
243 PyObject
*path
= PyString_FromString (priv
->path
);
245 if (PySequence_Contains(sys_path
, path
) == 0)
246 PyList_Insert (sys_path
, 0, path
);
251 main_locals
= PyModule_GetDict (main_module
);
252 /* we need a fromlist to be able to import modules with a '.' in the
254 fromlist
= PyTuple_New(0);
255 module
= PyImport_ImportModuleEx (priv
->module
, main_locals
,
256 main_locals
, fromlist
);
257 Py_DECREF (fromlist
);
263 locals
= PyModule_GetDict (module
);
264 while (PyDict_Next (locals
, &pos
, &key
, &value
))
266 if (!PyType_Check(value
))
269 if (PyObject_IsSubclass (value
, (PyObject
*) PyRBPlugin_Type
))
271 priv
->type
= rb_python_object_get_type (gmodule
, value
);
280 rb_python_module_unload (GTypeModule
*module
)
282 RBPythonModulePrivate
*priv
= RB_PYTHON_MODULE_GET_PRIVATE (module
);
283 rb_debug ("Unloading python module");
289 rb_python_module_new_object (RBPythonModule
*module
)
291 RBPythonModulePrivate
*priv
= RB_PYTHON_MODULE_GET_PRIVATE (module
);
292 RBPythonObject
*object
;
297 rb_debug ("Creating object of type %s", g_type_name (priv
->type
));
298 object
= (RBPythonObject
*) (g_object_new (priv
->type
,
299 "name", priv
->module
,
301 if (object
->instance
== NULL
) {
302 g_warning ("could not instantiate python object");
306 /* FIXME, HACK: this is a hack because the gobject object->instance references
307 * isn't the same gobject as we think it is. Which Causes Issues.
309 * This still has issues, notably that it isn't safe to call any rb.Plugin methods
310 * from python before we get here.
312 * The solution is to not have weird proxy objects.
314 g_object_set (((PyGObject
*)(object
->instance
))->obj
, "name", priv
->module
, NULL
);
316 return G_OBJECT (object
);
320 rb_python_module_init (RBPythonModule
*module
)
322 rb_debug ("Init of python module");
326 rb_python_module_finalize (GObject
*object
)
328 RBPythonModulePrivate
*priv
= RB_PYTHON_MODULE_GET_PRIVATE (object
);
329 rb_debug ("Finalizing python module %s", g_type_name (priv
->type
));
331 g_free (priv
->module
);
334 G_OBJECT_CLASS (rb_python_module_parent_class
)->finalize (object
);
338 rb_python_module_get_property (GObject
*object
,
343 /* no readable properties */
344 g_return_if_reached ();
348 rb_python_module_set_property (GObject
*object
,
353 RBPythonModule
*mod
= RB_PYTHON_MODULE (object
);
358 RB_PYTHON_MODULE_GET_PRIVATE (mod
)->module
= g_value_dup_string (value
);
361 RB_PYTHON_MODULE_GET_PRIVATE (mod
)->path
= g_value_dup_string (value
);
364 g_return_if_reached ();
369 rb_python_module_class_init (RBPythonModuleClass
*class)
371 GObjectClass
*object_class
= G_OBJECT_CLASS (class);
372 GTypeModuleClass
*module_class
= G_TYPE_MODULE_CLASS (class);
374 object_class
->finalize
= rb_python_module_finalize
;
375 object_class
->get_property
= rb_python_module_get_property
;
376 object_class
->set_property
= rb_python_module_set_property
;
378 g_object_class_install_property
381 g_param_spec_string ("module",
383 "The python module to load for this plugin",
385 G_PARAM_WRITABLE
| G_PARAM_READABLE
| G_PARAM_CONSTRUCT_ONLY
));
387 g_object_class_install_property
390 g_param_spec_string ("path",
392 "The python path to use when loading this module",
394 G_PARAM_WRITABLE
| G_PARAM_READABLE
| G_PARAM_CONSTRUCT_ONLY
));
396 g_type_class_add_private (object_class
, sizeof (RBPythonModulePrivate
));
398 module_class
->load
= rb_python_module_load
;
399 module_class
->unload
= rb_python_module_unload
;
401 /* Init python subsystem, this should happen only once
402 * in the process lifetime, and doing it here is ok since
403 * class_init is called once */
404 rb_python_module_init_python ();
408 rb_python_module_new (const gchar
*path
,
411 RBPythonModule
*result
;
414 if (module
== NULL
|| module
[0] == '\0')
417 dir
= g_path_get_dirname (path
);
418 result
= g_object_new (RB_TYPE_PYTHON_MODULE
,
424 g_type_module_set_name (G_TYPE_MODULE (result
), module
);
429 /* --- these are not module methods, they are here out of convenience --- */
431 static gint idle_garbage_collect_id
= 0;
434 run_gc (gpointer data
)
436 while (PyGC_Collect ())
439 idle_garbage_collect_id
= 0;
445 rb_python_garbage_collect ()
447 if (Py_IsInitialized() && idle_garbage_collect_id
== 0) {
448 idle_garbage_collect_id
= g_idle_add (run_gc
, NULL
);
453 finalise_collect_cb (gpointer data
)
455 while (PyGC_Collect ())
458 /* useful if python is refusing to give up it's shell reference for some reason.
459 PyRun_SimpleString ("import gc, gobject\nfor o in gc.get_objects():\n\tif isinstance(o, gobject.GObject):\n\t\tprint o, gc.get_referrers(o)");
466 rb_python_shutdown ()
468 if (Py_IsInitialized ()) {
469 if (idle_garbage_collect_id
!= 0) {
470 g_source_remove (idle_garbage_collect_id
);
471 idle_garbage_collect_id
= 0;
475 /* this helps to force python to give up it's shell reference */
476 g_timeout_add (1000, finalise_collect_cb
, NULL
);
478 /* disable for now, due to bug 334188