Commit bc726caa authored by Nikita Sirgienko's avatar Nikita Sirgienko
Browse files

Improve logic of running command in PythonServer:

 - Make behavare more similar to interpreter - if we run single expression, print result of them to output
 - Remove code, which try to do the same thing (but don't work very well)
 - Move addition code for server working from session into server (init.py)
Also add setting worksheet path to python session (and forward passing the path to server, because Python use filename in traceback)
parent 5b54afa8
import sys
class CatchOutPythonBackend:
def __init__(self):
self.value = ''
def write(self, txt):
self.value += txt
outputPythonBackend = CatchOutPythonBackend()
errorPythonBackend = CatchOutPythonBackend()
sys.stdout = outputPythonBackend
sys.stderr = errorPythonBackend
<RCC>
<qresource prefix="/py">
<file>import_default_modules.py</file>
<file>init.py</file>
<file>variables_cleaner.py</file>
<file>variables_loader.py</file>
<file>variables_saver.py</file>
......
......@@ -45,11 +45,51 @@ void PythonServer::login()
{
Py_Initialize();
m_pModule = PyImport_AddModule("__main__");
filePath = QLatin1String("python_cantor_worksheet");
}
void PythonServer::runPythonCommand(const QString& command) const
{
PyRun_SimpleString(command.toStdString().c_str());
PyObject* py_dict = PyModule_GetDict(m_pModule);
const char* prepareCommand =
"import sys;\n"\
"class CatchOutPythonBackend:\n"\
" def __init__(self):\n"\
" self.value = ''\n"\
" def write(self, txt):\n"\
" self.value += txt\n"\
"outputPythonBackend = CatchOutPythonBackend()\n"\
"errorPythonBackend = CatchOutPythonBackend()\n"\
"sys.stdout = outputPythonBackend\n"\
"sys.stderr = errorPythonBackend\n";
PyRun_SimpleString(prepareCommand);
PyObject* compile = Py_CompileString(command.toStdString().c_str(), filePath.toStdString().c_str(), Py_single_input);
// There are two reasons for the error:
// 1) This code is not single expression, so we can't compile this with flag Py_single_input
// 2) There are errors in the code
if (PyErr_Occurred())
{
PyErr_Clear();
// Try to recompile code as sequence of expressions
compile = Py_CompileString(command.toStdString().c_str(), filePath.toStdString().c_str(), Py_file_input);
if (PyErr_Occurred())
{
// We now know, that we have a syntax error, so print the traceback and exit
PyErr_PrintEx(0);
return;
}
}
#if PY_MAJOR_VERSION == 3
PyEval_EvalCode(compile, py_dict, py_dict);
#elif PY_MAJOR_VERSION == 2
PyEval_EvalCode((PyCodeObject*)compile, py_dict, py_dict);
#else
#warning Unknown Python version
#endif
if (PyErr_Occurred())
PyErr_PrintEx(0);
}
QString PythonServer::getError() const
......@@ -68,5 +108,10 @@ QString PythonServer::getOutput() const
return pyObjectToQString(output);
}
void PythonServer::setFilePath(const QString& path)
{
this->filePath = path;
PyRun_SimpleString(("__file__ = '"+path.toStdString()+"'").c_str());
}
......@@ -34,12 +34,14 @@ class PythonServer : public QObject
public Q_SLOTS:
Q_SCRIPTABLE void login();
Q_SCRIPTABLE void setFilePath(const QString& path);
Q_SCRIPTABLE void runPythonCommand(const QString& command) const;
Q_SCRIPTABLE QString getOutput() const;
Q_SCRIPTABLE QString getError() const;
private:
PyObject* m_pModule;
QString filePath;
};
#endif
......@@ -97,7 +97,7 @@ void PythonSession::login()
}
m_pIface->call(QString::fromLatin1("login"));
m_pIface->call(QString::fromLatin1("setFilePath"), worksheetPath);
if(integratePlots())
{
......@@ -213,14 +213,6 @@ void PythonSession::runExpression(PythonExpression* expr)
continue;
}
if(!PythonKeywords::instance()->keywords().contains(firstLineWord) && !command.contains(QLatin1String("=")) &&
!command.endsWith(QLatin1String(":")) && !command.startsWith(QLatin1String(" "))){
commandProcessing += QLatin1String("print(") + command + QLatin1String(")\n");
continue;
}
commandProcessing += command + QLatin1String("\n");
}
......@@ -233,16 +225,10 @@ void PythonSession::readExpressionOutput(const QString& commandProcessing)
readOutput(commandProcessing);
}
void PythonSession::runClassOutputPython() const
{
runPythonCommand(fromSource(QLatin1String(":py/init.py")));
}
void PythonSession::getPythonCommandOutput(const QString& commandProcessing)
{
qDebug() << "Running python command" << commandProcessing;
runClassOutputPython();
runPythonCommand(commandProcessing);
m_output = getOutput();
......@@ -463,3 +449,8 @@ QString PythonSession::getError() const
return reply.error().message();
}
void PythonSession::setWorksheetPath(const QString& path)
{
worksheetPath = path;
}
......@@ -51,6 +51,7 @@ class CANTOR_EXPORT PythonSession : public Cantor::Session
Cantor::CompletionObject* completionFor(const QString& command, int index=-1) override;
QSyntaxHighlighter* syntaxHighlighter(QObject* parent) override;
QAbstractItemModel* variableModel() override;
void setWorksheetPath(const QString& path) override;
virtual bool integratePlots() const = 0;
virtual QStringList autorunScripts() const = 0;
......@@ -68,6 +69,8 @@ class CANTOR_EXPORT PythonSession : public Cantor::Session
QString serverName;
QString DbusChannelName;
QString worksheetPath;
protected:
QString m_output;
QString m_error;
......@@ -88,7 +91,6 @@ class CANTOR_EXPORT PythonSession : public Cantor::Session
virtual void readExpressionOutput(const QString& commandProcessing);
protected:
void runClassOutputPython() const;
void updateOutput();
private Q_SLOTS:
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment