File: python.c

package info (click to toggle)
dia 0.97.3%2Bgit20160930-9
  • links: PTS
  • area: main
  • in suites: bullseye
  • size: 54,372 kB
  • sloc: ansic: 155,065; xml: 16,326; python: 6,641; cpp: 4,935; makefile: 3,833; sh: 540; perl: 137; sed: 19
file content (174 lines) | stat: -rw-r--r-- 5,029 bytes parent folder | download | duplicates (3)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
/* Python plug-in for dia
 * Copyright (C) 1999  James Henstridge
 * Copyright (C) 2000  Hans Breuer
 *
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation; either version 2 of the License, or
 * (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program; if not, write to the Free Software
 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
 */

#ifdef HAVE_CONFIG_H
#include <config.h>
#endif

#include <Python.h>
#include <stdio.h>
#include <glib.h>

#include "intl.h"
#include "plug-ins.h"
#include "dia_dirs.h"

#include "pydia-error.h"

DIA_PLUGIN_CHECK_INIT

void initdia(void);

static gboolean
on_error_report (void)
{
    if (PyErr_Occurred()) {
#ifndef G_OS_WIN32
        PyErr_Print();
#else
        /* On Win32 there is not necessary a console attached to the
         * program, so delegate the stack dump to the error object,
         * which finally uses g_print()
         */
        PyObject *exc, *v, *tb, *ef;
        PyErr_Fetch (&exc, &v, &tb);
        ef = PyDiaError_New ("Initialization Error:", FALSE);
        PyFile_WriteObject (exc, ef, 0);
        PyFile_WriteObject (v, ef, 0);
        PyTraceBack_Print(tb, ef);
        Py_DECREF (ef);

        Py_XDECREF (exc);
        Py_XDECREF (v);
        Py_XDECREF (tb);
#endif
        return TRUE;
    }
    else
        return FALSE; 
}

static gboolean
dia_py_plugin_can_unload (PluginInfo *info)
{
    /* until we can properly clean up the python plugin, it is not safe to
     * unload it from a dia */
    return FALSE; /* TRUE */
}

static void
dia_py_plugin_unload (PluginInfo *info)
{
    /* should call filter_unregister_export () */
    Py_Finalize ();
}

PluginInitResult
dia_plugin_init(PluginInfo *info)
{
    gchar *python_argv[] = { "dia-python", NULL };
    gchar *startup_file;
    FILE *fp;
    PyObject *__main__, *__file__;

    if (Py_IsInitialized ()) {
        g_warning ("Dia's Python embedding is not designed for concurrency.");
	return DIA_PLUGIN_INIT_ERROR;
    }
    if (!dia_plugin_info_init(info, "Python",
			      _("Python scripting support"),
			      dia_py_plugin_can_unload, 
			      dia_py_plugin_unload))
	return DIA_PLUGIN_INIT_ERROR;

    Py_SetProgramName("dia");
    Py_Initialize();

    PySys_SetArgv(1, python_argv);
    /* Sanitize sys.path */
    PyRun_SimpleString("import sys; sys.path = filter(None, sys.path)");

    if (on_error_report())
	return DIA_PLUGIN_INIT_ERROR;

    initdia();
    if (on_error_report())
	return DIA_PLUGIN_INIT_ERROR;

#ifdef G_OS_WIN32
    PySys_SetObject("stderr", PyDiaError_New (NULL, TRUE));
#endif
    if (g_getenv ("DIA_PYTHON_PATH")) {
	startup_file = g_build_filename (g_getenv ("DIA_PYTHON_PATH"), "python-startup.py", NULL);
    } else {
	startup_file = dia_get_data_directory("python-startup.py");
    }
    if (!startup_file) {
	g_warning("could not find python-startup.py");
	return DIA_PLUGIN_INIT_ERROR;
    }

    /* set __file__ in __main__ so that python-startup.py knows where it is */
    __main__ = PyImport_AddModule("__main__");
    __file__ = PyString_FromString(startup_file);
    PyObject_SetAttrString(__main__, "__file__", __file__);
    Py_DECREF(__file__);
#if defined(G_OS_WIN32) && (PY_VERSION_HEX >= 0x02040000)
    /* this code should work for every supported Python version, but it is needed 
     * on win32 since Python 2.4 due to mixed runtime issues, i.e.
     * crashing in PyRun_SimpleFile for python2(5|6)/msvcr(71|90) 
     * 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;
	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);
	    g_error_free(error);
	    g_free(startup_file);
	    return DIA_PLUGIN_INIT_ERROR;
	}
	/* PyRun_SimpleString does not like the windows format */
	for (i = 0; i < length; ++i)
	    if (startup_string[i] == '\r')
		startup_string[i] = '\n';

	if (PyRun_SimpleString(startup_string) != 0) {
	    g_warning("Python: Couldn't run startup file %s\n", startup_file);
	}
	g_free(startup_string);
    }
#else
    fp = fopen(startup_file, "r");
    if (!fp) {
	g_warning("Python: Couldn't find startup file %s\n", startup_file);
	g_free(startup_file);
	return DIA_PLUGIN_INIT_ERROR;
    }
    PyRun_SimpleFile(fp, startup_file);
#endif
    g_free(startup_file);

    if (on_error_report())
	return DIA_PLUGIN_INIT_ERROR;

    return DIA_PLUGIN_INIT_OK;
}