diff --git a/app/app_procs.c b/app/app_procs.c index 33041d0..e39d843 100644 --- a/app/app_procs.c +++ b/app/app_procs.c @@ -685,6 +685,7 @@ app_init (int argc, char **argv) static char *export_file_format = NULL; static char *size = NULL; static char *show_layers = NULL; + static char *python_script = NULL; gboolean made_conversions = FALSE; GSList *files = NULL; static const gchar **filenames = NULL; @@ -716,6 +717,8 @@ app_init (int argc, char **argv) N_("Directory containing input files"), N_("DIRECTORY")}, {"output-directory", 'O', 0, G_OPTION_ARG_CALLBACK, _check_option_output_directory, N_("Directory containing output files"), N_("DIRECTORY")}, + {"python", 'i', 0, G_OPTION_ARG_FILENAME, NULL, + N_("Run python script after initialization, then terminate"), N_("SCRIPTFILE")}, {"credits", 'c', 0, G_OPTION_ARG_NONE, &credits, N_("Display credits list and exit"), NULL }, {"verbose", 0, 0, G_OPTION_ARG_NONE, &verbose, @@ -734,8 +737,9 @@ app_init (int argc, char **argv) options[1].arg_data = &export_file_format; options[3].arg_data = &size; options[4].arg_data = &show_layers; - g_assert (strcmp (options[14].long_name, G_OPTION_REMAINING) == 0); - options[14].arg_data = (void*)&filenames; + options[11].arg_data = &python_script; + g_assert (strcmp (options[15].long_name, G_OPTION_REMAINING) == 0); + options[15].arg_data = (void*)&filenames; argv0 = (argc > 0) ? argv[0] : "(none)"; @@ -806,7 +810,7 @@ app_init (int argc, char **argv) } } /* given some files to output (or something;)), we are not starting up the UI */ - if (export_file_name || export_file_format || size || credits || version || list_filters) + if (export_file_name || export_file_format || size || credits || version || list_filters || python_script) dia_is_interactive = FALSE; } @@ -961,6 +965,33 @@ app_init (int argc, char **argv) } dia_log_message ("diagrams"); + + + if (python_script) { + GList *tmp; + PluginInfo *info; + gint (*run_script_func) (gchar*); + + const char* python_plugin_name = "Python"; + for (tmp = dia_list_plugins(); tmp != NULL; tmp = tmp->next) { + info = tmp->data; + if (strstr(info->name, python_plugin_name)) + break; + } + if (tmp == NULL) { + g_critical( _("Python plug-in not loaded! Not running %s.\n"), + python_script); + } + else if (!g_module_symbol(info->module, "run_script_oneshot", + (gpointer)&run_script_func)) { + g_critical("Unable to retrieve %s from module %s at %p!\n", + "run_script_oneshot", info->name, info->module); + } + else { + (* run_script_func)(python_script); + } + } + made_conversions = handle_all_diagrams(files, export_file_name, export_file_format, size, show_layers, input_directory, output_directory); diff --git a/lib/plug-ins.c b/lib/plug-ins.c index ce31b18..5434acf 100644 --- a/lib/plug-ins.c +++ b/lib/plug-ins.c @@ -49,21 +49,6 @@ #undef Rectangle #endif -struct _PluginInfo { - GModule *module; - gchar *filename; /* plugin filename */ - - gboolean is_loaded; - gboolean inhibit_load; - - gchar *name; - gchar *description; - - PluginInitFunc init_func; - PluginCanUnloadFunc can_unload_func; - PluginUnloadFunc unload_func; -}; - static GList *plugins = NULL; diff --git a/lib/plug-ins.h b/lib/plug-ins.h index 3fa6665..58031d0 100644 --- a/lib/plug-ins.h +++ b/lib/plug-ins.h @@ -110,6 +110,21 @@ g_module_check_init(GModule *gmodule) \ /* prototype for plugin init function (should be implemented by plugin) */ G_MODULE_EXPORT PluginInitResult dia_plugin_init(PluginInfo *info); +struct _PluginInfo { + GModule *module; + gchar *filename; /* plugin filename */ + + gboolean is_loaded; + gboolean inhibit_load; + + gchar *name; + gchar *description; + + PluginInitFunc init_func; + PluginCanUnloadFunc can_unload_func; + PluginUnloadFunc unload_func; +}; + G_END_DECLS #endif diff --git a/plug-ins/python/python.c b/plug-ins/python/python.c index 54b3e02..a3c0b44 100644 --- a/plug-ins/python/python.c +++ b/plug-ins/python/python.c @@ -34,6 +34,7 @@ DIA_PLUGIN_CHECK_INIT void initdia(void); +gint run_script_oneshot(gchar*); static gboolean on_error_report (void) @@ -48,7 +49,7 @@ on_error_report (void) */ PyObject *exc, *v, *tb, *ef; PyErr_Fetch (&exc, &v, &tb); - ef = PyDiaError_New ("Initialization Error:", FALSE); + ef = PyDiaError_New ("Execution Error:", FALSE); PyFile_WriteObject (exc, ef, 0); PyFile_WriteObject (v, ef, 0); PyTraceBack_Print(tb, ef); @@ -84,8 +85,7 @@ dia_plugin_init(PluginInfo *info) { gchar *python_argv[] = { "dia-python", NULL }; gchar *startup_file; - FILE *fp; - PyObject *__main__, *__file__; + gint script_fail = 0; if (Py_IsInitialized ()) { g_warning ("Dia's Python embedding is not designed for concurrency."); @@ -124,9 +124,31 @@ dia_plugin_init(PluginInfo *info) return DIA_PLUGIN_INIT_ERROR; } + script_fail = run_script_oneshot(startup_file); + g_free(startup_file); + + if (script_fail) + return DIA_PLUGIN_INIT_ERROR; + + return DIA_PLUGIN_INIT_OK; +} + +gint +run_script_oneshot (gchar* filename) { + /* + * Let it be noted explicitly, that (currently) there is exactly one + * instance of the python interpreter for the entire dia session. + * This means that every call to this function runs a script with the + * interpreter in the very state left behind by any previous call to any + * python function, especially the execution of the startup file. + */ + + FILE *fp; + PyObject *__main__, *__file__; + /* set __file__ in __main__ so that python-startup.py knows where it is */ __main__ = PyImport_AddModule("__main__"); - __file__ = PyString_FromString(startup_file); + __file__ = PyString_FromString(filename); PyObject_SetAttrString(__main__, "__file__", __file__); Py_DECREF(__file__); #if defined(G_OS_WIN32) && (PY_VERSION_HEX >= 0x02040000) @@ -136,39 +158,37 @@ dia_plugin_init(PluginInfo *info) * It is not enabled by default yet, because I could not get PyGtk using * plug-ins to work at all with 2.5/2.6 */ { - gchar *startup_string = NULL; + gchar *python_string = NULL; gsize i, length = 0; GError *error = NULL; - if (!g_file_get_contents(startup_file, &startup_string, &length, &error)) { - g_warning("Python: Couldn't find startup file %s\n%s\n", - startup_file, error->message); + if (!g_file_get_contents(filename, &python_string, &length, &error)) { + g_warning("Python: Couldn't find file %s\n%s\n", + filename, error->message); g_error_free(error); - g_free(startup_file); - return DIA_PLUGIN_INIT_ERROR; + return -1; } /* PyRun_SimpleString does not like the windows format */ for (i = 0; i < length; ++i) - if (startup_string[i] == '\r') - startup_string[i] = '\n'; + if (python_string[i] == '\r') + python_string[i] = '\n'; - if (PyRun_SimpleString(startup_string) != 0) { - g_warning("Python: Couldn't run startup file %s\n", startup_file); + if (PyRun_SimpleString(python_string) != 0) { + g_warning("Python: Couldn't run file %s\n", filename); } - g_free(startup_string); + g_free(python_string); } #else - fp = fopen(startup_file, "r"); + fp = fopen(filename, "r"); if (!fp) { - g_warning("Python: Couldn't find startup file %s\n", startup_file); - g_free(startup_file); - return DIA_PLUGIN_INIT_ERROR; + g_warning("Python: Couldn't find file %s\n", filename); + return -1; } - PyRun_SimpleFile(fp, startup_file); + PyRun_SimpleFile(fp, filename); #endif - g_free(startup_file); if (on_error_report()) - return DIA_PLUGIN_INIT_ERROR; - - return DIA_PLUGIN_INIT_OK; + { + return -2; + } + return 0; }