From 2b460648e9df51f73967eb072a63e7ef61d891fb Mon Sep 17 00:00:00 2001 From: =?utf8?q?C=C3=A9dric=20Aguerre?= Date: Mon, 26 Oct 2015 14:59:31 +0100 Subject: [PATCH] Fix EDF 11688 - handle list as script argument --- src/PyInterp/PyInterp_Interp.cxx | 83 +++++++++++++++++++++++-- src/SalomeApp/SalomeApp_Application.cxx | 21 ++++++- 2 files changed, 99 insertions(+), 5 deletions(-) diff --git a/src/PyInterp/PyInterp_Interp.cxx b/src/PyInterp/PyInterp_Interp.cxx index 7cbb3e304..4461c75c4 100644 --- a/src/PyInterp/PyInterp_Interp.cxx +++ b/src/PyInterp/PyInterp_Interp.cxx @@ -35,6 +35,7 @@ #include #include #include +#include #include #define TOP_HISTORY_PY "--- top of history ---" @@ -362,6 +363,75 @@ void replaceAll(std::string& str, const std::string& from, const std::string& to start_pos += to.length(); // In case 'to' contains 'from', like replacing 'x' with 'yx' } } + +std::vector +__split(const std::string& str, char delimiter) +{ + std::vector internal; + std::stringstream ss(str); // Turn the string into a stream. + std::string tok; + + while (getline(ss, tok, delimiter)) { + internal.push_back(tok); + } + + return internal; +} + +std::string +__join(const std::vector& v, int begin=0, int end=-1) +{ + if (end == -1) + end = v.size(); + std::stringstream ss; + for (size_t i = begin; i < end; ++i) { + if (i != begin) + ss << ","; + ss << v[i]; + } + return ss.str(); +} + +std::vector +__getArgsList(std::string argsString) +{ + // Special process if some items of 'args:' list are themselves lists + // Note that an item can be a list, but not a list of lists... + // So we can have something like this: + // myscript.py args:[\'file1\',\'file2\'],\'val1\',\"done\",[1,2,3],[True,False],\"ok\",kwarg1=\'kwarg1\',kwarg2=\'kwarg2\',\'fin\' + // With such a call, argsString variable contains the string representing ['file1','file2'],'val1','done',[1,2,3],[True,False],'ok',kwarg1='kwarg1',kwarg2='kwarg2','fin' + // We have to split argsString to obtain a 9 string elements list + std::vector x = __split(argsString, ','); + bool containsList = (argsString.find('[') != std::string::npos); + if (containsList) { + std::vector listBeginIndices, listEndIndices; + for (int pos = 0; pos < x.size(); ++pos) { + if (x[pos][0] == '[') + listBeginIndices.push_back(pos); + else if (x[pos][x[pos].size()-1] == ']') + listEndIndices.push_back(pos); + } + std::vector extractedArgs; + int start = 0; + for (int pos = 0; pos < listBeginIndices.size(); ++pos) { + int lbeg = listBeginIndices[pos]; + int lend = listEndIndices[pos]; + if (lbeg > start) + for (int k = start; k < lbeg; ++k) + extractedArgs.push_back(x[k]); + extractedArgs.push_back(__join(x, lbeg, lend+1)); + start = lend+1; + } + if (start < x.size()) + for (int k = start; k < x.size(); ++k) + extractedArgs.push_back(x[k]); + return extractedArgs; + } + else { + return x; + } +} + /*! \brief Compile Python command and evaluate it in the python dictionary context if possible. Command might correspond to @@ -380,7 +450,7 @@ static int compile_command(const char *command, PyObject * global_ctxt, PyObject std::string singleCommand = command; std::string commandArgs = ""; - if (singleCommand.at(singleCommand.size()-1) == '\n') + while (singleCommand.at(singleCommand.size()-1) == '\n') singleCommand.erase(singleCommand.size()-1); std::size_t pos = singleCommand.find("args:"); if (pos != std::string::npos) { @@ -398,12 +468,17 @@ static int compile_command(const char *command, PyObject * global_ctxt, PyObject // process command: execfile(r"/absolute/path/to/script.py [args:arg1,...,argn]") std::string script = singleCommand.substr(11); // remove leading execfile(r" script = script.substr(0, script.length()-2); // remove trailing ") + std::vector argList = __getArgsList(commandArgs); std::string preCommandBegin = "import sys; save_argv = sys.argv; sys.argv=["; std::string preCommandEnd = "];"; - replaceAll(commandArgs, ",", "\",\""); - commandArgs = "\""+commandArgs+"\""; - std::string completeCommand = preCommandBegin+"\""+script+"\","+commandArgs+preCommandEnd+singleCommand+";sys.argv=save_argv"; + std::string completeCommand = preCommandBegin+"\""+script+"\","; + for (std::vector::iterator itr = argList.begin(); itr != argList.end(); ++itr) { + if (itr != argList.begin()) + completeCommand += ","; + completeCommand = completeCommand + "\"" + *itr + "\""; + } + completeCommand = completeCommand+preCommandEnd+singleCommand+";sys.argv=save_argv"; return run_command(completeCommand.c_str(), global_ctxt, local_ctxt); } } diff --git a/src/SalomeApp/SalomeApp_Application.cxx b/src/SalomeApp/SalomeApp_Application.cxx index b7db9089f..309f65866 100644 --- a/src/SalomeApp/SalomeApp_Application.cxx +++ b/src/SalomeApp/SalomeApp_Application.cxx @@ -175,6 +175,25 @@ SalomeApp_Application::~SalomeApp_Application() //SALOME_EventFilter::Destroy(); } +QStringList __getArgsList(QString argsString) +{ + // Special process if some items of 'args:' list are themselves lists + // Note that an item can be a list, but not a list of lists... + // So we can have something like this: + // myscript.py args:['file1','file2'],val1,"done",[1,2,3],[True,False],"ok" + // With such a call, argsString variable contains the string representing "[file1,file2]", "val1", "done", "[1,2,3]", "[True,False]", "ok" + // We have to split argsString to obtain: [[file1,file2],val1,done,[1,2,3],[True,False],ok] + argsString.replace("\\\"", "'"); // replace escaped double quotes by simple quotes + bool containsList = (QRegExp("(\\[[^\\]]*\\])").indexIn(argsString) >= 0); + if (containsList) { + QStringList sl = argsString.split("\"", QString::SkipEmptyParts); + sl.removeAll(", "); + return sl; + } + else + return argsString.split(",", QString::SkipEmptyParts); +} + /*!Start application.*/ void SalomeApp_Application::start() { @@ -243,7 +262,7 @@ void SalomeApp_Application::start() if ( rxp.indexIn( pyfiles[j] ) >= 0 && rxp.capturedTexts().count() == 3 ) { QString script = rxp.capturedTexts()[1]; QString args = ""; - QStringList argList = rxp.capturedTexts()[2].split(",", QString::SkipEmptyParts); + QStringList argList = __getArgsList(rxp.capturedTexts()[2]); for (uint k = 0; k < argList.count(); k++ ) { QString arg = argList[k].trimmed(); arg.remove( QRegExp("^[\"]") ); -- 2.39.2