itom 1.4.0
|
00001 /* ******************************************************************** 00002 itom software 00003 URL: http://www.uni-stuttgart.de/ito 00004 Copyright (C) 2013, Institut fuer Technische Optik (ITO), 00005 Universitaet Stuttgart, Germany 00006 00007 This file is part of itom. 00008 00009 itom is free software; you can redistribute it and/or modify it 00010 under the terms of the GNU Library General Public Licence as published by 00011 the Free Software Foundation; either version 2 of the Licence, or (at 00012 your option) any later version. 00013 00014 itom is distributed in the hope that it will be useful, but 00015 WITHOUT ANY WARRANTY; without even the implied warranty of 00016 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Library 00017 General Public Licence for more details. 00018 00019 You should have received a copy of the GNU Library General Public License 00020 along with itom. If not, see <http://www.gnu.org/licenses/>. 00021 *********************************************************************** */ 00022 00023 #ifndef PYTHONENGINE_H 00024 #define PYTHONENGINE_H 00025 00026 /*if you add any include to this file you will DIE an immediate, horrible, painful death*/ 00027 00028 #include <string> 00029 #include <exception> 00030 //#ifndef Q_MOC_RUN 00031 // #define PY_ARRAY_UNIQUE_SYMBOL itom_ARRAY_API 00032 // #define NO_IMPORT_ARRAY 00033 //#endif 00034 00035 #ifndef ITOM_NPDATAOBJECT 00036 #define NPY_NO_DEPRECATED_API NPY_1_7_API_VERSION //see comment in pythonNpDataObject.cpp 00037 #endif 00038 00039 #ifndef Q_MOC_RUN 00040 //python 00041 // see http://vtk.org/gitweb?p=VTK.git;a=commitdiff;h=7f3f750596a105d48ea84ebfe1b1c4ca03e0bab3 00042 #if (defined _DEBUG) && (!defined linux) 00043 #undef _DEBUG 00044 #if (defined linux) | (defined CMAKE) 00045 #include "Python.h" 00046 #include "node.h" 00047 #include "numpy/arrayobject.h" 00048 #else 00049 #include "Python.h" 00050 #include "node.h" 00051 #include "../Lib/site-packages/numpy/core/include/numpy/arrayobject.h" //for numpy arrays 00052 #endif 00053 #define _DEBUG 00054 #else 00055 #ifdef linux 00056 #include "Python.h" 00057 #include "node.h" 00058 #include "numpy/arrayobject.h" 00059 #else 00060 #include "Python.h" 00061 #include "node.h" 00062 #include "../Lib/site-packages/numpy/core/include/numpy/arrayobject.h" //for numpy arrays 00063 #endif 00064 #endif 00065 #endif // Q_MOC_RUN 00066 00067 /* includes */ 00068 00069 #include "pythonNpDataObject.h" 00070 #include "pythonItom.h" 00071 #include "pythonProxy.h" 00072 00073 #include "../models/breakPointModel.h" 00074 #include "../../common/sharedStructuresQt.h" 00075 #include "../../common/addInInterface.h" 00076 00077 #include "pythonWorkspace.h" 00078 00079 #include <qstringlist.h> 00080 #include <qqueue.h> 00081 #include <qset.h> 00082 #include <qpointer.h> 00083 #include <qatomic.h> 00084 00085 00086 /* definition and macros */ 00087 00088 /* global variables (avoid) */ 00089 00090 /* content */ 00091 00092 class QDesktopWidget; 00093 class QTimer; 00094 00095 namespace ito 00096 { 00097 00098 class FuncWeakRef 00099 { 00100 public: 00101 FuncWeakRef(); 00102 FuncWeakRef(PythonProxy::PyProxy *proxyObject, PyObject *argTuple = NULL); 00103 FuncWeakRef(const FuncWeakRef &rhs); 00104 ~FuncWeakRef(); 00105 FuncWeakRef& operator =(FuncWeakRef rhs); 00106 00107 PythonProxy::PyProxy* getProxyObject() const { return m_proxyObject; } //borrowed reference 00108 PyObject* getArguments() const { return m_argument; } //borrowed reference 00109 bool isValid() const { return (m_proxyObject != NULL); } 00110 00111 void setHandle(const size_t &handle); 00112 size_t getHandle() const { return m_handle; } 00113 private: 00114 PythonProxy::PyProxy *m_proxyObject; 00115 PyObject *m_argument; 00116 size_t m_handle; 00117 }; 00118 00119 00120 class PythonEngine : public QObject 00121 { 00122 Q_OBJECT 00123 00124 public: 00125 PythonEngine(); //constructor 00126 ~PythonEngine(); //destructor 00127 00128 Q_INVOKABLE void pythonSetup(ito::RetVal *retValue); //setup 00129 Q_INVOKABLE ito::RetVal scanAndRunAutostartFolder(QString currentDirAfterScan = QString() ); 00130 Q_INVOKABLE ito::RetVal pythonShutdown(ItomSharedSemaphore *aimWait = NULL); //shutdown 00131 00132 Q_INVOKABLE ito::RetVal stringEncodingChanged(); 00133 00134 inline ito::BreakPointModel *getBreakPointModel() const { return bpModel; } 00135 inline bool isPythonBusy() const { return pythonState != ito::pyStateIdle; } 00136 inline bool isPythonDebugging() const { return (pythonState == ito::pyStateDebuggingWaitingButBusy || pythonState == ito::pyStateDebugging || pythonState == ito::pyStateDebuggingWaiting); } 00137 inline bool isPythonDebuggingAndWaiting() const { return pythonState == ito::pyStateDebuggingWaiting; } 00138 inline bool execInternalCodeByDebugger() const { return m_executeInternalPythonCodeInDebugMode; } 00139 inline void setExecInternalCodeByDebugger(bool value) { m_executeInternalPythonCodeInDebugMode = value; } 00140 00141 ito::RetVal checkForPyExceptions(); 00142 void printPythonErrorWithoutTraceback(); 00143 00144 void pythonDebugFunction(PyObject *callable, PyObject *argTuple); 00145 void pythonRunFunction(PyObject *callable, PyObject *argTuple); 00146 00147 inline PyObject *getGlobalDictionary() const { return globalDictionary; } 00149 inline bool pySyntaxCheckAvailable() const { return (m_pyModSyntaxCheck != NULL); } 00150 00151 static const PythonEngine *getInstance(); 00152 00153 QList<int> parseAndSplitCommandInMainComponents(const char *str, QByteArray &encoding) const; //can be directly called from different thread 00154 00155 protected: 00156 //RetVal syntaxCheck(char* pythonFileName); // syntaxCheck for file with filename pythonFileName 00157 ito::RetVal runPyFile(const QString &pythonFileName); // run file pythonFileName 00158 ito::RetVal debugFile(const QString &pythonFileName); // debug file pythonFileName 00159 ito::RetVal runString(const QString &command); // run string command 00160 ito::RetVal debugString(const QString &command); // debug string command 00161 ito::RetVal debugFunction(PyObject *callable, PyObject *argTuple); 00162 ito::RetVal runFunction(PyObject *callable, PyObject *argTuple); 00163 00164 ito::RetVal modifyTracebackDepth(int NrOfLevelsToPopAtFront = -1, bool showTraceback = true); 00165 00166 PyObject* setPyErrFromException(const std::exception &exc); 00167 00168 #if QT_VERSION >= 0x050000 00169 void connectNotify(const QMetaMethod &signal); 00170 #else 00171 void connectNotify(const char* signal); 00172 #endif 00173 00174 private: 00175 static PythonEngine *getInstanceInternal(); 00176 00177 inline PyObject *getLocalDictionary() { return localDictionary; } 00179 PyObject *getPyObjectByFullName(bool globalNotLocal, const QStringList &fullName); 00180 00181 void setGlobalDictionary(PyObject* mainDict = NULL); 00182 void setLocalDictionary(PyObject* localDict); 00183 00184 void emitPythonDictionary(bool emitGlobal, bool emitLocal, PyObject* globalDict, PyObject* localDict); 00185 00186 ito::RetVal pickleDictionary(PyObject *dict, const QString &filename); 00187 ito::RetVal unpickleDictionary(PyObject *destinationDict, const QString &filename, bool overwrite); 00188 00189 //methods for maintaining python functionality 00190 ito::RetVal addMethodToModule(PyMethodDef* def); 00191 ito::RetVal delMethodFromModule(const char* ml_name); 00192 ito::RetVal pythonAddBuiltinMethods(); 00193 00194 //methods for debugging 00195 void enqueueDbgCmd(ito::tPythonDbgCmd dbgCmd); 00196 ito::tPythonDbgCmd dequeueDbgCmd(); 00197 bool DbgCommandsAvailable(); 00198 void clearDbgCmdLoop(); 00199 00200 ito::RetVal pythonStateTransition(tPythonTransitions transition); 00201 00202 //methods for breakpoint 00203 ito::RetVal pythonAddBreakpoint(const QString &filename, const int lineno, const bool enabled, const bool temporary, const QString &condition, const int ignoreCount, int &pyBpNumber); 00204 ito::RetVal pythonEditBreakpoint(const int pyBpNumber, const QString &filename, const int lineno, const bool enabled, const bool temporary, const QString &condition, const int ignoreCount); 00205 ito::RetVal pythonDeleteBreakpoint(const int pyBpNumber); 00206 00207 ito::RetVal autoReloaderCheck(); 00208 00209 static int queuedInterrupt(void *unused); 00210 00211 //member variables 00212 bool m_started; 00213 //QString m_itomMemberClasses; 00214 00215 //PyGILState_STATE threadState; 00216 00217 QMutex dbgCmdMutex; 00218 QMutex pythonStateChangeMutex; 00219 QMutex dictChangeMutex; 00220 QDesktopWidget *m_pDesktopWidget; 00221 QQueue<ito::tPythonDbgCmd> debugCommandQueue; 00222 ito::tPythonDbgCmd debugCommand; 00223 00224 ito::tPythonState pythonState; 00225 00226 ito::BreakPointModel *bpModel; 00227 00228 PyObject* mainModule; 00229 PyObject* mainDictionary; 00230 PyObject* localDictionary; 00231 PyObject* globalDictionary; 00232 PyObject *itomDbgModule; 00233 PyObject *itomDbgInstance; 00234 PyObject *itomModule; 00235 PyObject *itomFunctions; 00236 PyObject *m_pyModGC; 00237 PyObject *m_pyModSyntaxCheck; 00238 //PyObject *itomReturnException; //!< if this exception is thrown, the execution of the main application is stopped 00239 00240 PyObject *dictUnicode; 00241 00242 QSet<ito::PyWorkspaceContainer*> m_mainWorkspaceContainer; 00243 QSet<ito::PyWorkspaceContainer*> m_localWorkspaceContainer; 00244 QHash<size_t, FuncWeakRef> m_pyFuncWeakRefHashes; 00245 size_t m_pyFuncWeakRefAutoInc; 00246 00247 bool m_executeInternalPythonCodeInDebugMode; 00248 PyMethodDef* PythonAdditionalModuleITOM; 00249 00250 // decides if itom is automatically included in every source file before it is handed to the syntax checker 00251 bool m_includeItom; 00252 00253 struct AutoReload 00254 { 00255 PyObject *modAutoReload; 00256 PyObject *classAutoReload; 00257 bool enabled; 00258 bool checkFileExec; 00259 bool checkStringExec; 00260 bool checkFctExec; 00261 }; 00262 00263 AutoReload m_autoReload; 00264 00266 static PyMethodDef PyMethodItomDbg[]; 00267 static PyModuleDef PyModuleItomDbg; 00268 static PyObject* PyInitItomDbg(void); 00269 static PyObject* PyDbgCommandLoop(PyObject *pSelf, PyObject *pArgs); 00270 00271 //helper methods 00272 //static PyObject* checkForTimeoutHelper(ItomSharedSemaphore* semaphore, int timeout, PyObject *retValueOk); 00273 00274 //other static members 00275 static QMutex instatiated; 00276 static QMutex instancePtrProtection; 00277 static QString fctHashPrefix; 00278 00279 static PythonEngine* instance; 00280 00281 QAtomicInt m_interruptCounter; //protects that a python interrupt can only be placed if there is no interrupt event queued yet. 00282 00283 // friend class 00284 friend class ito::PythonItom; 00285 00286 signals: 00287 void pythonDebugPositionChanged(QString filename, int lineNo); 00288 void pythonStateChanged(tPythonTransitions pyTransition); 00289 void pythonModifyLocalDict(PyObject* localDict, ItomSharedSemaphore* semaphore); 00290 void pythonModifyGlobalDict(PyObject* globalDict, ItomSharedSemaphore* semaphore); 00291 void pythonCurrentDirChanged(); 00292 void updateCallStack(QStringList filenames, IntList lines, QStringList methods); 00293 void deleteCallStack(); 00294 00295 void pythonSetCursor(const Qt::CursorShape cursor); 00296 void pythonResetCursor(); 00297 void pythonAutoReloadChanged(bool enabled, bool checkFile, bool checkCmd, bool checkFct); 00298 void clearCommandLine(); 00299 00300 public slots: 00301 void pythonRunString(QString cmd); 00302 void pythonDebugString(QString cmd); 00303 void pythonExecStringFromCommandLine(QString cmd); 00304 void pythonRunFile(QString filename); 00305 void pythonDebugFile(QString filename); 00306 void pythonRunStringOrFunction(QString cmdOrFctHash); 00307 void pythonDebugStringOrFunction(QString cmdOrFctHash); 00308 void pythonInterruptExecution(); 00309 void pythonDebugCommand(tPythonDbgCmd cmd); 00310 00311 void setAutoReloader(bool enabled, bool checkFile, bool checkCmd, bool checkFct); 00312 00313 // Settings are neccesary for automatic itom inclusion and syntax check 00314 void readSettings(); 00315 void propertiesChanged(); 00316 00317 void pythonSyntaxCheck(const QString &code, QPointer<QObject> sender); 00318 00319 void pythonGenericSlot(PyObject* callable, PyObject *argumentTuple); 00320 00322 void breakPointAdded(BreakPointItem bp, int row); 00323 void breakPointDeleted(QString filename, int lineNo, int pyBpNumber); 00324 void breakPointChanged(BreakPointItem oldBp, BreakPointItem newBp); 00325 ito::RetVal setupBreakPointDebugConnections(); 00326 ito::RetVal shutdownBreakPointDebugConnections(); 00327 00328 bool renameVariable(bool globalNotLocal, QString oldKey, QString newKey, ItomSharedSemaphore *semaphore = NULL); 00329 bool deleteVariable(bool globalNotLocal, QStringList keys, ItomSharedSemaphore *semaphore = NULL); 00330 ito::RetVal pickleVariables(bool globalNotLocal, QString filename, QStringList varNames, ItomSharedSemaphore *semaphore = NULL); 00331 ito::RetVal unpickleVariables(bool globalNotLocal, QString filename, ItomSharedSemaphore *semaphore = NULL); 00332 ito::RetVal saveMatlabVariables(bool globalNotLocal, QString filename, QStringList varNames, ItomSharedSemaphore *semaphore = NULL); 00333 ito::RetVal loadMatlabVariables(bool globalNotLocal, QString filename, ItomSharedSemaphore *semaphore = NULL); 00334 ito::RetVal registerAddInInstance(QString varname, ito::AddInBase *instance, ItomSharedSemaphore *semaphore = NULL); 00335 ito::RetVal getSysModules(QSharedPointer<QStringList> modNames, QSharedPointer<QStringList> modFilenames, QSharedPointer<IntList> modTypes, ItomSharedSemaphore *semaphore = NULL); 00336 ito::RetVal reloadSysModules(QSharedPointer<QStringList> modNames, ItomSharedSemaphore *semaphore = NULL); 00337 00338 void registerWorkspaceContainer(PyWorkspaceContainer *container, bool registerNotUnregister, bool globalNotLocal); 00339 void workspaceGetChildNode(PyWorkspaceContainer *container, QString fullNameParentItem); 00340 void workspaceGetValueInformation(PyWorkspaceContainer *container, QString fullItemName, QSharedPointer<QString> extendedValue, ItomSharedSemaphore *semaphore = NULL); 00341 00342 void putParamsToWorkspace(bool globalNotLocal, QStringList names, QVector<SharedParamBasePointer > values, ItomSharedSemaphore *semaphore = NULL); 00343 void getParamsFromWorkspace(bool globalNotLocal, QStringList names, QVector<int> paramBaseTypes, QSharedPointer<SharedParamBasePointerVector > values, ItomSharedSemaphore *semaphore = NULL); 00344 00345 private slots: 00346 00347 }; 00348 00349 } //end namespace ito 00350 00351 00352 #endif