/* This is the interface to the python interpreter
Originally from the now defunct gnocci project.
C. Steenberg 15 May 2000
*/
#include <stdio.h>
#include <string.h>
#include <glib.h>
#include <gdk/gdk.h>
#include <gdk/gdkkeysyms.h>
#include <gtkextra/gtkextra.h>
#include "python_main.h"
#include "../sg.h"
#include "../sg_project_autosave.h"
#include "../sg_config.h"
#include "../sg_dialogs.h"
/* autosave timeout interval defaults to 5 minutes */
gint sg_autosave_interval = 5;
/* compress level defaults to best compression */
gint sg_compress_level = 9;
gboolean sg_report_python_error;
PyObject *main_dict, *sys_dict, *sg_o, *sg_dict, *config_dict;
static gchar def_safe_modules[][80]={"audioop", "array","binascii", "cmath","errno",
"imageop","marshal", "math", "md5", "operator","parser", "regex", "rotor",
"select","strop", "struct","time","gtk","_gtk","GDK","GTK","gnome","GNOME","pickle","Numeric","pysga",""};
static gchar def_safe_os[][80]={"error", "fstat","listdir", "lstat", "readlink",
"stat","times", "uname", "getpid", "getppid","getcwd","getuid", "getgid",
"geteuid","getegid","name","environ","ctermid","getgroups","getlogin",
"getpgrp","getpid","getppid","strerror","umask","uname","fpathconf","isatty",
"times","confstr","confstr_names","sysconf","sysconf_names","curdir",
"pardir","sep","altsep","pathsep","defpath","linesep","path","_get_exports_list","_names",""};
static gchar def_safe_sys[][80]={"argv","ps1","ps2", "copyright", "version", "platform","exit",
"maxint","stderr","stdout","stdin","byteorder","builtin_module_names",
"executable","exitfunc","getrefcount","getrecursionlimit","maxint","platform",
"prefix","version_info","path","excepthook","displayhook",""};
typedef struct _module_opts module_opts;
struct _module_opts
{ gchar *name;
gint flags; };
static module_opts comp_imports[]={
{"os",SG_MODULE_LOAD_MAIN|SG_MODULE_LOAD_REQ},
{"sys",SG_MODULE_LOAD_MAIN|SG_MODULE_LOAD_REQ},
{"Numeric",SG_MODULE_LOAD_SYMBOLS|SG_MODULE_LOAD_REQ},
{"pickle",SG_MODULE_LOAD_MAIN|SG_MODULE_LOAD_REQ},
{"gtk",SG_MODULE_LOAD_MAIN}, /* These two modules are not absolutely required*/
{"pysga",SG_MODULE_LOAD_SYMBOLS}, /* and may be loaded from non-standard places */
{NULL,0}};
/* Remember to increase the size of save_vars and save_obj when adding to this list
static gchar *save_vars_names[]={"sg_safe_modules","sg_safe_os","sg_safe_sys","sg_import_modules","sg_canvas_labels_pos",
"sg_canvas_labels_width","sg_save_freq","sg_compression_level","sg_module_paths",""};*/
static PyObject *default_paths = NULL,
*builtin_dict = NULL,
*builtin_o = NULL,
*os_dict = NULL,
*os_o = NULL,
*main_o = NULL,
*sys_o = NULL;
gint python_init_minimal(gchar *progname)
{ PyObject *module_object, *module_dict, *keys, *functions, *key_name, *object,
*full, *empty, *items, *string,*pickle;
gint i,flag,size;
gchar temp[200],*name,*homedir;
PyObject *av;
int argc;
char **argv;
Py_SetProgramName(progname);
Py_Initialize();
import_array();
sg_report_python_error=TRUE;
main_o=PyImport_ImportModule("__main__");
builtin_o=PyImport_AddModule("__builtin__");
sys_o=PyImport_ImportModule ("sys");
sys_o=PyImport_AddModule ("sys");
os_o=PyImport_ImportModule ("os");
os_o=PyImport_AddModule ("os");
main_dict=PyModule_GetDict(main_o);
sys_dict=PyModule_GetDict(sys_o);
os_dict=PyModule_GetDict(os_o);
builtin_dict=PyModule_GetDict(builtin_o);
PyDict_SetItemString (main_dict, "os", os_o);
PyDict_SetItemString (main_dict, "sys", sys_o);
/* sg module init */
init_sg_python();
sg_o=PyImport_AddModule("sg");
sg_dict=PyModule_GetDict(sg_o);
PyDict_SetItemString (main_dict, "sg", sg_o);
/* gtk.py requires this*/
full=PyList_New (1);
string=PyString_FromString (progname);
PyList_SET_ITEM (full, 0, string);
PyDict_SetItemString (sys_dict, "argv",full);
default_paths=PyDict_GetItemString (sys_dict, "path");
pickle=PyImport_ImportModule("pickle");
pickle=PyImport_AddModule("pickle");
PyDict_SetItemString (main_dict, "pickle", pickle);
if (!pickle) return FALSE;
return TRUE;
}
static gint pickle_config_file(gchar *fname, PyObject *globals, PyObject *locals)
{ gint i=0;
FILE *fp;
PyObject *object, *fo;
gchar temp[200];
if (!(fp=fopen(fname,"w"))) return FALSE;
fo=PyFile_FromFile (fp, "pickle_file", "w", NULL);
PyDict_SetItemString (sg_dict, "pickle_file", fo);
g_snprintf(temp,200,"pickler=pickle.Pickler(pickle_file)");
object=PyRun_String (temp, Py_file_input, globals, locals);
if (python_error_report(object))
return FALSE;
object=PyRun_String ("pickler.dump(sg.config)", Py_file_input, globals, locals);
python_error_report(object);
object=PyRun_String ("del pickle_file,pickler", Py_file_input, globals, locals);
if (python_error_report(object))
return (FALSE);
fclose(fp);
return TRUE;
}
gint python_config_save(void)
{ gchar dir[] = ".scigraphica";
gchar file[] = "config";
gint size;
gchar *rcdir,*rcfile;
PyObject *config_dict;
size = strlen(g_get_home_dir())+1 + strlen(dir)+1;
rcdir = g_new(gchar,size);
g_snprintf(rcdir,size,"%s/%s",g_get_home_dir(),dir);
size = strlen(rcdir)+1 + strlen(file)+1;
rcfile = g_new(gchar,size);
g_snprintf(rcfile,size,"%s/%s",rcdir,file);
if ( pickle_config_file(rcfile, main_dict, sg_dict) == FALSE )
{/* create scigraphica directory and try again */
gchar *create_dir;
size = strlen(rcdir) + 10;
create_dir = g_new(gchar,size);
g_snprintf(create_dir,size,"mkdir -p %s",rcdir);
system(create_dir);
g_free(create_dir);
pickle_config_file(rcfile, main_dict, sg_dict);
}
g_free(rcdir);
g_free(rcfile);
return (TRUE);
}
static gint init_modules(SGconfig *config){
gint i;
PyObject *dict,*items;
dict=PyDict_New();
for (i=0;comp_imports[i].name!=NULL;i++){
PyDict_SetItemString(dict,comp_imports[i].name,
PyInt_FromLong ((long) comp_imports[i].flags));
}
items=PyDict_Items(dict);
sg_config_set_value(config->name, config->group, dict, FALSE);
return TRUE;
}
static gint commit_modules(SGconfig *config){
PyObject *keys, *items, *key_name, *module_object,*object,*full,*string,*dict;
int i=0;
gint flag;
gchar *name,temp[200];
dict=sg_config_get_value(config->name, config->group);
full=PyList_New (1);
string=PyString_FromString ("*");
PyList_SET_ITEM (full, 0, string);
keys=PyDict_Keys(dict);
for (i=0;i<PyList_GET_SIZE (keys);i++)
{ gchar *name;
gint flag;
PyObject *pflag;
key_name=PyList_GetItem (keys,i);
name=PyString_AsString (key_name);
flag=(gint)PyInt_AsLong(PyDict_GetItemString (dict,name));
module_object=PyImport_ImportModuleEx (name, main_dict, sg_dict, full);
/*python_error_report(module_object);*/
if (!module_object) {
snprintf(temp,200,"Couldn't import module '%s'\nView verbose error log?",name);
python_error_report_verbose(module_object,FALSE,temp,1);
continue;
}
Py_INCREF(module_object);
if (flag&SG_MODULE_LOAD_SYMBOLS){
g_snprintf(temp,200,"from %s import *",name);
object=PyRun_String (temp, Py_single_input, main_dict, sg_dict);
python_error_report(object);
if (module_object)
PyDict_SetItemString (main_dict, name, module_object);
}
else if (comp_imports[i].flags&SG_MODULE_LOAD_MAIN && module_object){
PyDict_SetItemString (main_dict, name, module_object);
}
}
Py_XDECREF(full);
return i;
}
static gint init_canvas_labels_pos(SGconfig *config){
sg_config_set_value(config->name, config->group,
PyInt_FromLong ((long) sg_canvas_label_pos),FALSE);
return TRUE;
}
static gint commit_canvas_labels_pos(SGconfig *config){
gint pos;
pos=(gint)PyInt_AsLong(sg_config_get_value(config->name, config->group));
sg_canvas_label_pos=pos;
gtk_icon_list_freeze(GTK_ICON_LIST(iconlist1));
gtk_icon_list_set_mode(GTK_ICON_LIST(iconlist1), pos + 1);
gtk_icon_list_thaw(GTK_ICON_LIST(iconlist1));
gtk_icon_list_freeze(GTK_ICON_LIST(iconlist2));
gtk_icon_list_set_mode(GTK_ICON_LIST(iconlist2), pos + 1);
gtk_icon_list_thaw(GTK_ICON_LIST(iconlist2));
return TRUE;
}
static gint init_canvas_labels_width(SGconfig *config){
sg_config_set_value(config->name, config->group,
PyInt_FromLong ((long) sg_canvas_label_width),FALSE);
return TRUE;
}
static gint commit_canvas_labels_width(SGconfig *config){
gint width;
width=(gint)PyInt_AsLong(sg_config_get_value(config->name, config->group));
sg_canvas_label_width=width;
gtk_icon_list_freeze(GTK_ICON_LIST(iconlist1));
gtk_icon_list_set_text_space(GTK_ICON_LIST(iconlist1), width);
gtk_icon_list_thaw(GTK_ICON_LIST(iconlist1));
gtk_icon_list_freeze(GTK_ICON_LIST(iconlist2));
gtk_icon_list_set_text_space(GTK_ICON_LIST(iconlist2), width);
gtk_icon_list_thaw(GTK_ICON_LIST(iconlist2));
return TRUE;
}
static gint init_show_plot_toolbar(SGconfig *config){
sg_config_set_value(config->name, config->group,
PyInt_FromLong ((long) sg_show_plot_toolbar),FALSE);
return TRUE;
}
static gint commit_show_plot_toolbar(SGconfig *config){
gint show;
GList *list;
SGplot *plot;
show=(gint)PyInt_AsLong(sg_config_get_value(config->name, config->group));
sg_show_plot_toolbar=show;
list=plots;
while (list)
{ plot=(SGplot *)list->data;
if (show==TRUE)
gtk_widget_show_all(plot->toolbox);
else
gtk_widget_hide(plot->toolbox);
list=list->next;
}
return TRUE;
}
static gint init_show_plot_menubar(SGconfig *config){
sg_config_set_value(config->name, config->group,
PyInt_FromLong ((long) sg_show_plot_menubar),FALSE);
return TRUE;
}
static gint commit_show_plot_menubar(SGconfig *config){
gint show;
SGplot *plot;
GList *plotlist;
show=(gint)PyInt_AsLong(sg_config_get_value(config->name, config->group));
sg_show_plot_menubar=show;
plotlist=plots;
while (plotlist)
{ plot=(SGplot *)plotlist->data;
sg_plot_show_top_toolbar(plot);
plotlist=plotlist->next;
}
return TRUE;
}
static gint init_save_interval(SGconfig *config){
sg_config_set_value(config->name, config->group,
PyInt_FromLong((long)sg_autosave_interval),FALSE);
return TRUE;
}
static gint commit_save_interval(SGconfig *config){
PyObject *value;
value=sg_config_get_value(config->name, config->group);
sg_autosave_interval=(gint)PyInt_AsLong(value);
sg_project_autosave_set(sg_autosave_interval);
return TRUE;
}
static gint init_compress_level(SGconfig *config){
sg_config_set_value(config->name, config->group,
PyInt_FromLong ((long) sg_compress_level),FALSE);
return TRUE;
}
static gint commit_compress_level(SGconfig *config){
PyObject *value;
value=sg_config_get_value(config->name, config->group);
sg_compress_level=(gint)PyInt_AsLong(value);
return TRUE;
}
static gint init_autoscale(SGconfig *config){
if (!strcmp(config->name,"autoscale_left"))
sg_config_set_value(config->name, config->group,
PyInt_FromLong ((long) sg_autoscale_left),FALSE);
else if (!strcmp(config->name,"autoscale_right"))
sg_config_set_value(config->name, config->group,
PyInt_FromLong ((long) sg_autoscale_right),FALSE);
if (!strcmp(config->name,"autoscale_top"))
sg_config_set_value(config->name, config->group,
PyInt_FromLong ((long) sg_autoscale_top),FALSE);
else if (!strcmp(config->name,"autoscale_bottom"))
sg_config_set_value(config->name, config->group,
PyInt_FromLong ((long) sg_autoscale_bottom),FALSE);
else return FALSE;
return TRUE;
}
static gint commit_autoscale(SGconfig *config){
PyObject *value;
value=sg_config_get_value(config->name, config->group);
if (!strcmp(config->name,"autoscale_left"))
sg_autoscale_left=(gint)PyInt_AsLong(value);
else if (!strcmp(config->name,"autoscale_right"))
sg_autoscale_right=(gint)PyInt_AsLong(value);
else if (!strcmp(config->name,"autoscale_top"))
sg_autoscale_top=(gint)PyInt_AsLong(value);
else if (!strcmp(config->name,"autoscale_bottom"))
sg_autoscale_bottom=(gint)PyInt_AsLong(value);
else return FALSE;
return TRUE;
}
static gint init_module_paths(SGconfig *config){
int j;
PyObject *items;
items=PyDict_New();
for (j=0;j<PyList_GET_SIZE (default_paths);j++){
PyDict_SetItem(items, PyList_GetItem (default_paths,j),Py_None);
}
if (!PyDict_GetItemString(items, PYTHON_MODULE_PATH))
PyDict_SetItemString(items, PYTHON_MODULE_PATH,Py_None);
sg_config_set_value(config->name, config->group,
items,FALSE);
return TRUE;
}
static gint commit_module_paths(SGconfig *config){
PyObject *value;
value=sg_config_get_value(config->name, config->group);
PyDict_SetItemString (sys_dict, "path", PyDict_Keys(value));
return TRUE;
}
static gint unpickle_config_file(gchar *fname, PyObject *globals, PyObject *locals)
{
gint i=0;
FILE *fp;
PyObject *object, *fo, *dict;
gchar temp[200];
if (!(fp=fopen(fname,"r"))) return FALSE;
fo=PyFile_FromFile (fp, "pickle_file", "r", NULL);
PyDict_SetItemString (sg_dict, "pickle_file", fo);
g_snprintf(temp,200,"unpickler=pickle.Unpickler(pickle_file)");
object=PyRun_String (temp, Py_file_input, globals, locals);
if (!object){
python_error_report_verbose(object,FALSE,"Cannot load preferences - Restoring defaults.\n\n"
"View verbose error log?",1);
Py_XDECREF(object);
fclose(fp);
Py_XDECREF(fo);
return 0;
}
g_snprintf(temp,200,"sg.config=unpickler.load()");
object=PyRun_String (temp, Py_file_input, globals, locals);
if (!object){
python_error_report_verbose(object,FALSE,"Cannot load preferences - Restoring defaults.\n\n"
"View verbose error log?",1);
Py_XDECREF(object);
fclose(fp);
Py_XDECREF(fo);
return 0;
}
g_snprintf(temp,200,"del pickle_file,unpickler");
object=PyRun_String (temp, Py_file_input, globals, locals);
sg_config_dict=PyDict_GetItemString(sg_dict,"config");
fclose(fp);
Py_XDECREF(object);
Py_XDECREF(fo);
if (dict) return 1;
else return 0;
}
gint python_config_init(void)
{ gchar dir[] = ".scigraphica";
gchar file[] = "config";
gchar *rcdir,*rcfile;
gint size;
PyObject *config_dict;
size = strlen(g_get_home_dir())+1 + strlen(dir)+1;
rcdir = g_new(gchar,size);
g_snprintf(rcdir,size,"%s/%s",g_get_home_dir(),dir);
size = strlen(rcdir)+1 + strlen(file)+1;
rcfile=g_new(gchar,size);
g_snprintf(rcfile,size,"%s/%s",rcdir,file);
if ( unpickle_config_file(rcfile, main_dict, sg_dict) == FALSE )
{/* create scigraphica directory and try again */
gchar *create_dir;
size = strlen(rcdir) + 10;
create_dir=g_new(gchar,size);
g_snprintf(create_dir,size,"mkdir -p %s", rcdir);
system(create_dir);
g_free(create_dir);
/* try again */
unpickle_config_file(rcfile, main_dict, sg_dict);
}
g_free(rcdir);
g_free(rcfile);
sg_config_init();
sg_config_new_c("startup", "module", init_modules, commit_modules);
sg_config_new_c("path", "module", init_module_paths, commit_module_paths);
sg_config_new_c("label_width", "maingui", init_canvas_labels_width, commit_canvas_labels_width);
sg_config_new_c("label_pos", "maingui", init_canvas_labels_pos, commit_canvas_labels_pos);
sg_config_new_c("save_interval", "file", init_save_interval, commit_save_interval);
sg_config_new_c("compress_level", "file", init_compress_level, commit_compress_level);
sg_config_new_c("autoscale_left", "plotgui", init_autoscale, commit_autoscale);
sg_config_new_c("autoscale_right", "plotgui", init_autoscale, commit_autoscale);
sg_config_new_c("autoscale_top", "plotgui", init_autoscale, commit_autoscale);
sg_config_new_c("autoscale_bottom", "plotgui", init_autoscale, commit_autoscale);
sg_config_new_c("show_toolbar", "plotgui", init_show_plot_toolbar, commit_show_plot_toolbar);
sg_config_new_c("show_menubar", "plotgui", init_show_plot_menubar, commit_show_plot_menubar);
/* Make sure the standard modules are loaded */
sg_config_exec_commit(sg_config_get_config("path", "module"));
return (TRUE);
}
gint python_error_report(PyObject *object)
{
if (!object)
{ if (sg_report_python_error)
create_python_term(NULL,NULL);
PyErr_Print();
if (Py_FlushLine())
PyErr_Clear();
return TRUE;
}
return FALSE;
}
gint python_error_report_verbose(PyObject *object,gboolean report, gchar *message, gint type){
if (!object){
if (report|| sg_accept_dialog(message,type)==YES_CLICKED){
create_python_term(NULL,NULL);
PyErr_Print();
}
if (Py_FlushLine())
PyErr_Clear();
return TRUE;
}
return FALSE;
}
syntax highlighted by Code2HTML, v. 0.9.1