1
/***************************************************************************
2
File : PythonScript.cpp
4
--------------------------------------------------------------------
5
Copyright : (C) 2006 by Knut Franke
6
Email (use @ for *) : knut.franke*gmx.de
7
Description : Execute Python code from within QtiPlot
9
***************************************************************************/
11
/***************************************************************************
13
* This program is free software; you can redistribute it and/or modify *
14
* it under the terms of the GNU General Public License as published by *
15
* the Free Software Foundation; either version 2 of the License, or *
16
* (at your option) any later version. *
18
* This program is distributed in the hope that it will be useful, *
19
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
20
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
21
* GNU General Public License for more details. *
23
* You should have received a copy of the GNU General Public License *
24
* along with this program; if not, write to the Free Software *
25
* Foundation, Inc., 51 Franklin Street, Fifth Floor, *
26
* Boston, MA 02110-1301 USA *
28
***************************************************************************/
29
// get rid of a compiler warning
30
#ifdef _POSIX_C_SOURCE
31
#undef _POSIX_C_SOURCE
35
#include "PythonScript.h"
36
#include "PythonScripting.h"
37
#include "ApplicationWindow.h"
42
PythonScript::PythonScript(PythonScripting *env, const QString &code, QObject *context, const QString &name)
43
: Script(env, code, context, name)
46
localDict = PyDict_New();
47
setQObject(Context, "self");
50
PythonScript::~PythonScript()
56
void PythonScript::setContext(QObject *context)
58
Script::setContext(context);
59
setQObject(Context, "self");
62
bool PythonScript::compile(bool for_eval)
64
// Support for the convenient col() and cell() functions.
65
// This can't be done anywhere else, because we need access to the local
66
// variables self, i and j.
67
if(Context->inherits("Table")) {
68
// A bit of a hack, but we need either IndexError or len() from __builtins__.
69
PyDict_SetItemString(localDict, "__builtins__",
70
PyDict_GetItemString(env()->globalDict(), "__builtins__"));
71
PyObject *ret = PyRun_String(
73
"\ttry: return self.cell(c,arg[0])\n"
74
"\texcept(IndexError): return self.cell(c,i)\n"
76
"\treturn self.cell(c,r)",
77
Py_file_input, localDict, localDict);
82
} else if(Context->inherits("Matrix")) {
83
// A bit of a hack, but we need either IndexError or len() from __builtins__.
84
PyDict_SetItemString(localDict, "__builtins__",
85
PyDict_GetItemString(env()->globalDict(), "__builtins__"));
86
PyObject *ret = PyRun_String(
88
"\ttry: return self.cell(arg[0],arg[1])\n"
89
"\texcept(IndexError): return self.cell(i,j)\n",
90
Py_file_input, localDict, localDict);
98
// Simplest case: Code is a single expression
99
PyCode = Py_CompileString(Code.ascii(), Name, Py_eval_input);
102
} else if (for_eval) {
103
// Code contains statements (or errors) and we want to get a return
105
// So we wrap the code into a function definition,
106
// execute that (as Py_file_input) and store the function object in PyCode.
107
// See http://mail.python.org/pipermail/python-list/2001-June/046940.html
108
// for why there isn't an easier way to do this in Python.
109
PyErr_Clear(); // silently ignore errors
110
PyObject *key, *value;
111
#if PY_VERSION_HEX >= 0x02050000
116
QString signature = "";
117
while(PyDict_Next(localDict, &i, &key, &value))
118
signature.append(PyString_AsString(key)).append(",");
119
signature.truncate(signature.length()-1);
120
QString fdef = "def __doit__("+signature+"):\n";
122
fdef.replace('\n',"\n\t");
123
PyCode = Py_CompileString(fdef, Name, Py_file_input);
126
PyObject *tmp = PyDict_New();
127
Py_XDECREF(PyEval_EvalCode((PyCodeObject*)PyCode, env()->globalDict(), tmp));
129
PyCode = PyDict_GetItemString(tmp,"__doit__");
133
success = PyCode != NULL;
135
// Code contains statements (or errors), but we do not need to get
137
PyErr_Clear(); // silently ignore errors
138
PyCode = Py_CompileString(Code.ascii(), Name, Py_file_input);
139
success = PyCode != NULL;
143
compiled = compileErr;
144
emit_error(env()->errorMsg(), 0);
146
compiled = isCompiled;
150
QVariant PythonScript::eval()
152
if (!isFunction) compiled = notCompiled;
153
if (compiled != isCompiled && !compile(true))
156
beginStdoutRedirect();
157
if (PyCallable_Check(PyCode))
159
PyObject *empty_tuple = PyTuple_New(0);
160
pyret = PyObject_Call(PyCode, empty_tuple, localDict);
161
Py_DECREF(empty_tuple);
163
pyret = PyEval_EvalCode((PyCodeObject*)PyCode, env()->globalDict(), localDict);
167
emit_error(env()->errorMsg(), 0);
171
QVariant qret = QVariant();
173
if (pyret == Py_None)
176
else if (PyFloat_Check(pyret))
177
qret = QVariant(PyFloat_AS_DOUBLE(pyret));
178
else if (PyInt_Check(pyret))
179
qret = QVariant((qlonglong)PyInt_AS_LONG(pyret));
180
else if (PyLong_Check(pyret))
181
qret = QVariant((qlonglong)PyLong_AsLongLong(pyret));
182
else if (PyNumber_Check(pyret))
184
PyObject *number = PyNumber_Float(pyret);
187
qret = QVariant(PyFloat_AS_DOUBLE(number));
191
} else if (PyBool_Check(pyret))
192
qret = QVariant(pyret==Py_True, 0);
193
// could handle advanced types (such as PyList->QValueList) here if needed
194
/* fallback: try to convert to (unicode) string */
195
if(!qret.isValid()) {
196
PyObject *pystring = PyObject_Unicode(pyret);
198
PyObject *asUTF8 = PyUnicode_EncodeUTF8(PyUnicode_AS_UNICODE(pystring), PyUnicode_GET_DATA_SIZE(pystring), 0);
201
qret = QVariant(QString::fromUtf8(PyString_AS_STRING(asUTF8)));
203
} else if (pystring = PyObject_Str(pyret)) {
204
qret = QVariant(QString(PyString_AS_STRING(pystring)));
211
if (PyErr_Occurred()) {
212
emit_error(env()->errorMsg(), 0);
218
bool PythonScript::exec()
220
if (isFunction) compiled = notCompiled;
221
if (compiled != Script::isCompiled && !compile(false))
224
beginStdoutRedirect();
225
if (PyCallable_Check(PyCode))
227
PyObject *empty_tuple = PyTuple_New(0);
229
emit_error(env()->errorMsg(), 0);
232
pyret = PyObject_Call(PyCode,empty_tuple,localDict);
233
Py_DECREF(empty_tuple);
235
pyret = PyEval_EvalCode((PyCodeObject*)PyCode, env()->globalDict(), localDict);
241
emit_error(env()->errorMsg(), 0);
245
void PythonScript::beginStdoutRedirect()
247
stdoutSave = PyDict_GetItemString(env()->sysDict(), "stdout");
248
Py_XINCREF(stdoutSave);
249
stderrSave = PyDict_GetItemString(env()->sysDict(), "stderr");
250
Py_XINCREF(stderrSave);
251
env()->setQObject(this, "stdout", env()->sysDict());
252
env()->setQObject(this, "stderr", env()->sysDict());
255
void PythonScript::endStdoutRedirect()
257
PyDict_SetItemString(env()->sysDict(), "stdout", stdoutSave);
258
Py_XDECREF(stdoutSave);
259
PyDict_SetItemString(env()->sysDict(), "stderr", stderrSave);
260
Py_XDECREF(stderrSave);
263
bool PythonScript::setQObject(QObject *val, const char *name)
265
if (!PyDict_Contains(localDict, PyString_FromString(name)))
266
compiled = notCompiled;
267
return env()->setQObject(val, name, localDict);
270
bool PythonScript::setInt(int val, const char *name)
272
if (!PyDict_Contains(localDict, PyString_FromString(name)))
273
compiled = notCompiled;
274
return env()->setInt(val, name, localDict);
277
bool PythonScript::setDouble(double val, const char *name)
279
if (!PyDict_Contains(localDict, PyString_FromString(name)))
280
compiled = notCompiled;
281
return env()->setDouble(val, name, localDict);