-// Copyright (C) 2007-2016 CEA/DEN, EDF R&D, OPEN CASCADE
+// Copyright (C) 2007-2023 CEA/DEN, EDF R&D, OPEN CASCADE
//
// Copyright (C) 2003-2007 OPEN CASCADE, EADS/CCR, LIP6, CEA/DEN,
// CEDRAT, EDF R&D, LEG, PRINCIPIA R&D, BUREAU VERITAS
#include <sstream>
#include <algorithm>
-#include <QRegExp>
+#include <QRegularExpression>
+#include <QStringList>
#define TOP_HISTORY_PY "--- top of history ---"
#define BEGIN_HISTORY_PY "--- begin of history ---"
}
static PyObject*
-PyStdOut_flush(PyStdOut *self)
+PyStdOut_flush(PyStdOut * /*self*/, PyObject * /*args*/)
{
Py_INCREF(Py_None);
return Py_None;
}
+static PyObject*
+PyStdOut_isatty(PyStdOut * /*self*/, PyObject */*args*/)
+{
+ return Py_False;
+}
+
static PyMethodDef PyStdOut_methods[] = {
{"write", (PyCFunction)PyStdOut_write, METH_VARARGS, PyDoc_STR("write(string) -> None")},
{"flush", (PyCFunction)PyStdOut_flush, METH_NOARGS, PyDoc_STR("flush() -> None")},
- {NULL, NULL} /* sentinel */
+ {"isatty", (PyCFunction)PyStdOut_isatty, METH_NOARGS, PyDoc_STR("isatty() -> bool")},
+ {NULL, (PyCFunction)NULL, 0, NULL} /* sentinel */
};
static PyMemberDef PyStdOut_memberlist[] = {
{(char*)"softspace", T_INT, offsetof(PyStdOut, softspace), 0,
(char*)"flag indicating that a space needs to be printed; used by print"},
- {NULL} /* Sentinel */
+ {NULL, 0, 0, 0, NULL} /* Sentinel */
};
static PyTypeObject PyStdOut_Type = {
0, /*tp_del*/
0, /*tp_version_tag*/
0, /*tp_finalize*/
+#if PY_VERSION_HEX >= 0x03080000
+ 0, /*tp_vectorcall*/
+#if PY_VERSION_HEX < 0x03090000
+ 0, /*tp_print*/
+#endif
+#endif
};
#define PyStdOut_Check(v) ((v)->ob_type == &PyStdOut_Type)
\brief Basic constructor.
After construction the interpreter instance successor classes
- must call virtual method initalize().
+ must call virtual method initialize().
*/
PyInterp_Interp::PyInterp_Interp():
- _vout(0), _verr(0), _local_context(0), _global_context(0), _initialized(false)
+ _vout(0), _verr(0), _global_context(0), _local_context(0), _initialized(false)
{
}
/*!
\brief Initialize embedded interpreter.
- This method shoud be called after construction of the interpreter.
+ This method should be called after construction of the interpreter.
The method initialize() calls virtuals methods
- initPython() to initialize global Python interpreter
- initContext() to initialize interpreter internal context
if (!Py_IsInitialized()){
// Python is not initialized
wchar_t **changed_argv = new wchar_t*[_argc]; // Setting arguments
- size_t mbslen;
for (int i = 0; i < _argc; i++)
{
changed_argv[i] = Py_DecodeLocale(_argv[i], NULL);
}
-
+
+#if PY_VERSION_HEX < 0x03080000
Py_SetProgramName(changed_argv[0]);
Py_Initialize(); // Initialize the interpreter
PySys_SetArgv(_argc, changed_argv);
-
+#else
+ PyConfig config;
+ PyConfig_InitPythonConfig(&config);
+ PyStatus status = PyConfig_SetString(&config, &config.program_name, changed_argv[0]);
+ status = PyConfig_SetArgv(&config, _argc, changed_argv);
+ status = Py_InitializeFromConfig(&config);
+ PyConfig_Clear(&config);
+#endif
+
+#if PY_VERSION_HEX < 0x03070000
PyEval_InitThreads(); // Create (and acquire) the Python global interpreter lock (GIL)
+#endif
PyEval_SaveThread(); // release safely GIL
}
}
/*!
\brief Compile Python command and evaluate it in the
python dictionary contexts if possible. This is not thread-safe.
- This is the caller's responsability to make this thread-safe.
+ This is the caller's responsibility to make this thread-safe.
\internal
\param command Python command string
\return -1 on fatal error, 1 if command is incomplete and 0
__join(const std::vector<std::string>& v, int begin=0, int end=-1)
{
if (end == -1)
- end = v.size();
+ end = (int)v.size(); //!< TODO: conversion from size_t to int
std::stringstream ss;
- for (size_t i = begin; i < end; ++i) {
+ for (int i = begin; i < end; ++i) {
if (i != begin)
ss << ",";
ss << v[i];
bool containsList = (argsString.find('[') != std::string::npos);
if (containsList) {
std::vector<int> listBeginIndices, listEndIndices;
- for (int pos = 0; pos < x.size(); ++pos) {
+ for (int pos = 0; pos < (int)x.size(); ++pos) {
if (x[pos][0] == '[')
listBeginIndices.push_back(pos);
else if (x[pos][x[pos].size()-1] == ']')
}
std::vector<std::string> extractedArgs;
int start = 0;
- for (int pos = 0; pos < listBeginIndices.size(); ++pos) {
+ for (int pos = 0; pos < (int)listBeginIndices.size(); ++pos) {
int lbeg = listBeginIndices[pos];
int lend = listEndIndices[pos];
if (lbeg > start)
extractedArgs.push_back(__join(x, lbeg, lend+1));
start = lend+1;
}
- if (start < x.size())
- for (int k = start; k < x.size(); ++k)
+ if (start < (int)x.size())
+ for (int k = start; k < (int)x.size(); ++k)
extractedArgs.push_back(x[k]);
return extractedArgs;
}
python dictionary context if possible. Command might correspond to
the execution of a script with optional arguments.
In this case, command is:
- execfile(r"/absolute/path/to/script.py [args:arg1,...,argn]")
+ exec(open(r"/absolute/path/to/script.py", "rb").read(), args=(arg1,...,argn))
+ and args parameter is optional one. This parameter is specified as a tuple of strings.
\internal
\param command Python command string
\param context Python context (dictionary)
static int compile_command(const char *command, PyObject * global_ctxt, PyObject * local_ctxt)
{
// First guess if command is execution of a script with args, or a simple Python command
- std::string singleCommand = command;
- std::string commandArgs = "";
-
- QRegExp rx("execfile\\s*\\(.*(args:.*)\"\\s*\\)");
- if (rx.indexIn(command) != -1) {
- commandArgs = rx.cap(1).remove(0,5).toStdString(); // arguments of command
- singleCommand = rx.cap().remove(rx.cap(1)).remove(" ").toStdString(); // command for execution without arguments
+ QString singleCommand = command;
+ QString commandArgs = "";
+
+ QRegularExpression rx("exec\\s*\\(.*open\\s*\\(\\s*(.*)\\s*\\)\\s*\\.\\s*read\\s*\\(\\)(\\s*,\\s*args\\s*=\\s*\\(.*\\))\\s*\\)");
+ QRegularExpressionMatch match = rx.match(command);
+ if (match.hasMatch()) {
+ commandArgs = match.captured(2).remove(0, match.captured(2).indexOf("(")); // arguments of command
+ commandArgs.insert(commandArgs.indexOf('(')+1, match.captured(1).split(",")[0].trimmed() + ","); // prepend arguments list by the script file itself
+ singleCommand = singleCommand.remove(match.capturedStart(2), match.captured(2).size()); // command for execution without arguments
}
- if (commandArgs.empty()) {
- // process command: expression
- // process command: execfile(r"/absolute/path/to/script.py") (no args)
- return run_command(singleCommand.c_str(), global_ctxt, local_ctxt);
+ if (commandArgs.isEmpty()) {
+ return run_command(singleCommand.toStdString().c_str(), global_ctxt, local_ctxt);
}
else {
- // 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<std::string> argList = __getArgsList(commandArgs);
-
- std::string preCommandBegin = "import sys; save_argv = sys.argv; sys.argv=[";
- std::string preCommandEnd = "];";
- std::string completeCommand = preCommandBegin+"\""+script+"\",";
- for (std::vector<std::string>::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);
+ ///////////////std::vector<std::string> argList = __getArgsList(commandArgs);
+ QString preCommandBegin = "import sys; save_argv = sys.argv; sys.argv=list(";
+ QString preCommandEnd = ");";
+ QString postCommand = ";sys.argv=save_argv";
+ QString completeCommand = preCommandBegin+commandArgs+preCommandEnd+singleCommand.trimmed()+postCommand;
+ return run_command(completeCommand.toStdString().c_str(), global_ctxt, local_ctxt);
}
}
}
/**
- * Called before a command is run (when calling run() method). Not thread-safe. Caller's responsability
+ * Called before a command is run (when calling run() method). Not thread-safe. Caller's responsibility
* to acquire GIL if needed.
*/
int PyInterp_Interp::beforeRun()
}
/**
- * Called after a command is run (when calling run() method). Not thread-safe. Caller's responsability
+ * Called after a command is run (when calling run() method). Not thread-safe. Caller's responsibility
* to acquire GIL if needed.
*/
int PyInterp_Interp::afterRun()
}
/*!
- \brief Run Python command (used internally). Not thread-safe. GIL acquisition is caller's responsability.
+ \brief Run Python command (used internally). Not thread-safe. GIL acquisition is caller's responsibility.
\param command Python command
\param addToHistory if \c true (default), the command is added to the commands history
\return command status