1 // Copyright (C) 2007-2016 CEA/DEN, EDF R&D, OPEN CASCADE
3 // Copyright (C) 2003-2007 OPEN CASCADE, EADS/CCR, LIP6, CEA/DEN,
4 // CEDRAT, EDF R&D, LEG, PRINCIPIA R&D, BUREAU VERITAS
6 // This library is free software; you can redistribute it and/or
7 // modify it under the terms of the GNU Lesser General Public
8 // License as published by the Free Software Foundation; either
9 // version 2.1 of the License, or (at your option) any later version.
11 // This library is distributed in the hope that it will be useful,
12 // but WITHOUT ANY WARRANTY; without even the implied warranty of
13 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 // Lesser General Public License for more details.
16 // You should have received a copy of the GNU Lesser General Public
17 // License along with this library; if not, write to the Free Software
18 // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
20 // See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com
22 // File : PyConsole_Interp.cxx
23 // Author : Nicolas REJNERI (OPEN CASCADE), Adrien BRUNETON (CEA/DEN), Vadim SANDLER (OPEN CASCADE)
25 #include "PyConsole_Interp.h"
28 \class PyConsole_Interp
29 \brief Python interpreter to be embedded to the SALOME study's GUI.
31 There is only one Python interpreter for the whole SALOME environment.
33 Call the initialize() method defined in the base class PyInterp_Interp,
34 to initialize the interpreter after instance creation.
36 The method initialize() calls virtuals methods
37 - initPython() to initialize global Python interpreter
38 - initContext() to initialize interpreter internal context
39 - initRun() to prepare interpreter for running commands
41 See PyInterp_Interp class for more details.
47 Creates new python interpreter.
49 PyConsole_Interp::PyConsole_Interp()
57 PyConsole_Interp::~PyConsole_Interp()
62 \brief Performs specific actions before each Python command
64 Sets the variable "__IN_SALOME_GUI_CONSOLE" to True.
65 This is not attached to a module (like salome_iapp.IN_SALOME_GUI_CONSOLE)
66 since modules are shared across all interpreters in SALOME.
68 \note GIL is already acquired here.
70 int PyConsole_Interp::beforeRun()
72 return PyRun_SimpleString("__builtins__.__IN_SALOME_GUI_CONSOLE=True");
76 \brief Performs specific actions after each Python command
78 Sets the variable "__IN_SALOME_GUI_CONSOLE" to False.
81 \note GIL is already acquired here.
83 int PyConsole_Interp::afterRun()
85 return PyRun_SimpleString("__builtins__.__IN_SALOME_GUI_CONSOLE=False");
89 \brief Run Python dir() command to get matches.
91 \param dirArgument Python expression to pass to the dir command. The parsing of what the
92 user actually started typing is dedicated to the caller
93 \param startMatch string representing the begining of the patter to be completed. For example, when
94 the user types "a_string_variable.rsp <TAB>", this is "rsp".
95 \param[out] matches resulting list of matches
96 \param[out] docString resulting docstring of single match
97 \return \true if completion succeeded, \c false otherwise
99 bool PyConsole_Interp::runDirCommand( const QString& dirArgument, const QString& startMatch,
100 QStringList& matches, QString& docString )
102 static QStringList keywords;
103 if ( keywords.isEmpty() ) {
104 keywords << "and" << "as" << "assert" << "break" << "class" << "continue"
105 << "def" << "del" << "elif" << "else" << "except" << "exec"
106 << "finally" << "for" << "from" << "global" << "if" << "import"
107 << "in" << "is" << "lambda" << "not" << "or" << "pass" << "print" << "raise"
108 << "return" << "try" << "while" << "with" << "yield";
111 // run dir() command and extract completions
112 if ( !runDirAndExtract( dirArgument, startMatch, matches ) )
115 // If dirArgument is empty, we append the __builtins__
116 if ( dirArgument.isEmpty() ) {
117 if ( !runDirAndExtract( QString( "__builtins__" ), startMatch, matches, false ) )
120 // ... and we match on Python's keywords as well
121 foreach( QString keyword, keywords ) {
122 if ( keyword.startsWith( startMatch ) )
123 matches.append( keyword );
127 // Try to get doc string of the first match
128 if ( matches.size() > 0 ) {
129 QString cmd = QString( "%1.__doc__" ).arg( matches[0] );
130 if ( !dirArgument.trimmed().isEmpty() )
131 cmd.prepend( QString( "%1." ).arg( dirArgument ) );
133 PyObject* str = PyRun_String( cmd.toStdString().c_str(), Py_eval_input, _global_context, _local_context );
134 if ( !str || str == Py_None || !PyString_Check( str ) )
140 docString = QString( PyString_AsString( str ) );
150 \param dirArgument see runDirCommand()
151 \param startMatch see runDirCommand()
152 \param[out] result resulting list of matches
153 \param discardSwig if \c true, a regular expression is used to discard all static method generated
154 by SWIG. Typically: MEDCouplingUMesh_Blabla
155 \return \c true if the call to dir() and parsing of the result succeeded, \false otherwise.
157 bool PyConsole_Interp::runDirAndExtract( const QString& dirArgument,
158 const QString& startMatch,
160 bool discardSwig ) const
162 QRegExp re( "^[A-Z].+_[A-Z]+[a-z]+.+$" ); // REX to discard SWIG static method, e.g. MEDCouplingUMesh_Blabla
164 // Execute dir() command
165 QString command( "dir(" + dirArgument + ")" );
166 PyObject* plst = PyRun_String( command.toStdString().c_str(), Py_eval_input, _global_context, _local_context );
167 if ( !plst || plst == Py_None ) {
175 if ( !PySequence_Check( plst ) ) {
176 // Should never happen ...
181 // Extract the returned list
182 int n = PySequence_Length( plst );
183 for ( int i = 0; i < n; i++ ) {
185 it = PySequence_GetItem( plst, i );
186 QString s( PyString_AsString( it ) );
187 // if the method is not from swig, not static (guessed from the reg exp) and matches
188 // what is already there
189 if ( s.startsWith( startMatch ) ) {
190 if ( !discardSwig || ( !re.exactMatch( s ) && !s.contains( "swig" ) ) )