lib

pythoninterpreter.cpp
1/***************************************************************************
2 * pythoninterpreter.cpp
3 * This file is part of the KDE project
4 * copyright (C)2004-2005 by Sebastian Sauer (mail@dipe.org)
5 *
6 * This program is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU Library General Public
8 * License as published by the Free Software Foundation; either
9 * version 2 of the License, or (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 GNU
13 * Library General Public License for more details.
14 * You should have received a copy of the GNU Library General Public License
15 * along with this program; see the file COPYING. If not, write to
16 * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
17 * Boston, MA 02110-1301, USA.
18 ***************************************************************************/
19
20#include "pythoninterpreter.h"
21#include "pythonscript.h"
22#include "pythonmodule.h"
23#include "pythonsecurity.h"
24//#include "pythonextension.h"
25#include "../api/variant.h"
26
27#include <tdeglobal.h>
28#include <kstandarddirs.h>
29
30#if defined(TQ_WS_WIN)
31 #define PYPATHDELIMITER ";"
32#else
33 #define PYPATHDELIMITER ":"
34#endif
35
36extern "C"
37{
47 void* krossinterpreter(Kross::Api::InterpreterInfo* info)
48 {
49 try {
50 return new Kross::Python::PythonInterpreter(info);
51 }
53 Kross::krosswarning("krossinterpreter(Kross::Api::InterpreterInfo* info): Unhandled exception.");
54 }
55 return 0;
56 }
57}
58
59using namespace Kross::Python;
60
61namespace Kross { namespace Python {
62
64 class PythonInterpreterPrivate
65 {
66 public:
67
69 PythonModule* mainmodule;
70
72 PythonSecurity* security;
73 };
74
75}}
76
78 : Kross::Api::Interpreter(info)
79 , d(new PythonInterpreterPrivate())
80{
81 // Initialize the python interpreter.
82 initialize();
83
84 // Set name of the program.
85 Py_SetProgramName(const_cast<char*>("Kross"));
86
87 /*
88 // Set arguments.
89 //char* comm[0];
90 const char* comm = const_cast<char*>("kross"); // name.
91 PySys_SetArgv(1, comm);
92 */
93
94 // In the python sys.path are all module-directories are
95 // listed in.
96 TQString path;
97
98 // First import the sys-module to remember it's sys.path
99 // list in our path TQString.
100 Py::Module sysmod( PyImport_ImportModule("sys"), true );
101 Py::Dict sysmoddict = sysmod.getDict();
102 Py::Object syspath = sysmoddict.getItem("path");
103 if(syspath.isList()) {
104 Py::List syspathlist = syspath;
105 for(Py::List::iterator it = syspathlist.begin(); it != syspathlist.end(); ++it)
106 if( (*it).isString() )
107 path.append( TQString(Py::String(*it).as_string().c_str()) + PYPATHDELIMITER );
108 }
109 else
110 path = Py_GetPath();
111
112 // Determinate additional module-paths we like to add.
113 // First add the global Kross modules-path.
114 TQStringList krossdirs = TDEGlobal::dirs()->findDirs("data", "kross/python");
115 for(TQStringList::Iterator krossit = krossdirs.begin(); krossit != krossdirs.end(); ++krossit)
116 path.append(*krossit + PYPATHDELIMITER);
117 // Then add the application modules-path.
118 TQStringList appdirs = TDEGlobal::dirs()->findDirs("appdata", "kross/python");
119 for(TQStringList::Iterator appit = appdirs.begin(); appit != appdirs.end(); ++appit)
120 path.append(*appit + PYPATHDELIMITER);
121
122 // Set the extended sys.path.
123 PySys_SetPath( (char*) path.latin1() );
124
125 krossdebug(TQString("Python ProgramName: %1").arg(Py_GetProgramName()));
126 krossdebug(TQString("Python ProgramFullPath: %1").arg(Py_GetProgramFullPath()));
127 krossdebug(TQString("Python Version: %1").arg(Py_GetVersion()));
128 krossdebug(TQString("Python Platform: %1").arg(Py_GetPlatform()));
129 krossdebug(TQString("Python Prefix: %1").arg(Py_GetPrefix()));
130 krossdebug(TQString("Python ExecPrefix: %1").arg(Py_GetExecPrefix()));
131 krossdebug(TQString("Python Path: %1").arg(Py_GetPath()));
132 krossdebug(TQString("Python System Path: %1").arg(path));
133
134 // Initialize the main module.
135 d->mainmodule = new PythonModule(this);
136
137 // The main dictonary.
138 Py::Dict moduledict = d->mainmodule->getDict();
139 //TODO moduledict["KrossPythonVersion"] = Py::Int(KROSS_PYTHON_VERSION);
140
141 // Prepare the interpreter.
142 TQString s =
143 "import sys\n"
144 //"sys.setdefaultencoding('latin-1')\n"
145
146 // Dirty hack to get sys.argv defined. Needed for e.g. TKinter.
147 "sys.argv = ['']\n"
148
149 // On the try to read something from stdin always return an empty
150 // string. That way such reads don't block our script.
151 "import cStringIO\n"
152 "sys.stdin = cStringIO.StringIO()\n"
153
154 // Class to redirect something. We use this class e.g. to redirect
155 // <stdout> and <stderr> to a c++ event.
156 "class Redirect:\n"
157 " def __init__(self, target):\n"
158 " self.target = target\n"
159 " def write(self, s):\n"
160 " self.target.call(s)\n"
161
162 // Wrap builtin __import__ method. All import requests are
163 // first redirected to our PythonModule.import method and
164 // if the call returns None, then we call the original
165 // python import mechanism.
166 "import __builtin__\n"
167 "import __main__\n"
168 "class Importer:\n"
169 " def __init__(self):\n"
170 " self.realImporter = __builtin__.__import__\n"
171 " __builtin__.__import__ = self._import\n"
172 " def _import(self, name, globals=None, locals=None, fromlist=[]):\n"
173 " mod = __main__._import(name, globals, locals, fromlist)\n"
174 " if mod != None: return mod\n"
175 " return self.realImporter(name, globals, locals, fromlist)\n"
176 "Importer()\n"
177 ;
178
179 PyObject* pyrun = PyRun_String(s.latin1(), Py_file_input, moduledict.ptr(), moduledict.ptr());
180 if(! pyrun) {
181 Py::Object errobj = Py::value(Py::Exception()); // get last error
182 throw Kross::Api::Exception::Ptr( new Kross::Api::Exception(TQString("Failed to prepare the __main__ module: %1").arg(errobj.as_string().c_str())) );
183 }
184 Py_XDECREF(pyrun); // free the reference.
185
186 // Initialize the RestrictedPython module.
187 d->security = new PythonSecurity(this);
188}
189
191{
192 // Free the zope security module.
193 delete d->security; d->security = 0;
194 // Free the main module.
195 delete d->mainmodule; d->mainmodule = 0;
196 // Finalize the python interpreter.
197 finalize();
198 // Delete the private d-pointer.
199 delete d;
200}
201
202void PythonInterpreter::initialize()
203{
204 // Initialize python.
205 Py_Initialize();
206
207 /* Not needed cause we use the >= Python 2.3 GIL-mechanism.
208 PyThreadState* d->globalthreadstate, d->threadstate;
209 // First we have to initialize threading if python supports it.
210 PyEval_InitThreads();
211 // The main thread. We don't use it later.
212 d->globalthreadstate = PyThreadState_Swap(NULL);
213 d->globalthreadstate = PyEval_SaveThread();
214 // We use an own sub-interpreter for each thread.
215 d->threadstate = Py_NewInterpreter();
216 // Note that this application has multiple threads.
217 // It maintains a separate interp (sub-interpreter) for each thread.
218 PyThreadState_Swap(d->threadstate);
219 // Work done, release the lock.
220 PyEval_ReleaseLock();
221 */
222}
223
224void PythonInterpreter::finalize()
225{
226 /* Not needed cause we use the >= Python 2.3 GIL-mechanism.
227 // Lock threads.
228 PyEval_AcquireLock();
229 // Free the used thread.
230 PyEval_ReleaseThread(d->threadstate);
231 // Set back to rememberd main thread.
232 PyThreadState_Swap(d->globalthreadstate);
233 // Work done, unlock.
234 PyEval_ReleaseLock();
235 */
236
237 // Finalize python.
238 Py_Finalize();
239}
240
242{
243 return new PythonScript(this, scriptcontainer);
244}
245
247{
248 return d->mainmodule;
249}
250
252{
253 return d->security;
254}
255
Common exception class used for representing exceptions in Kross.
Definition exception.h:39
TDESharedPtr< Exception > Ptr
Shared pointer to implement reference-counting.
Definition exception.h:45
While the Interpreter is the implemented interpreter this class is used to provide some abstract info...
Definition interpreter.h:42
Interpreter(InterpreterInfo *info)
Constructor.
The ScriptContainer class is something like a single standalone scriptfile.
Base class for interpreter dependend functionality each script provides.
Definition script.h:46
Python interpreter bridge.
PythonInterpreter(Kross::Api::InterpreterInfo *info)
Constructor.
virtual Kross::Api::Script * createScript(Kross::Api::ScriptContainer *scriptcontainer)
The PythonModule is the main python environment used as global object namespace.
Handle python scripts.
This class handles the used Zope3 RestrictedPython package to spend a restricted sandbox for scriptin...
The common Kross API used as common codebase.
Definition callable.h:33
The Python plugin for the Kross scripting framework.
The Kross scripting bridge to embed scripting functionality into an application.
Definition callable.h:33
KOFFICE_EXPORT void krossdebug(const TQString &s)
Debugging function.
KOFFICE_EXPORT void krosswarning(const TQString &s)
Warning function.