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

Rewrite Python2 to Dbus server and move common code beatween Python2 and...

Rewrite Python2 to Dbus server and move common code beatween Python2 and Python3 backends to common files

BUG: 363606
FIXED-IN: 18.12

Differential Revision: https://phabricator.kde.org/D14680
parent 6b722430
......@@ -17,7 +17,8 @@ target_link_libraries(cantor_pythonbackend
cantorlibs
KF5::KIOCore
KF5::ConfigCore
KF5::ConfigGui)
KF5::ConfigGui
Qt5::DBus)
install(TARGETS cantor_pythonbackend DESTINATION ${KDE_INSTALL_TARGETS_DEFAULT_ARGS})
#install(DIRECTORY . DESTINATION ${KDE_INSTALL_DATADIR}/cantor/pythonbackend FILES_MATCHING PATTERN "*.py")
......@@ -18,11 +18,11 @@
Copyright (C) 2015 Minh Ngo <minh@fedoraproject.org>
*/
#include "python3server.h"
#include "pythonserver.h"
#include <Python.h>
Python3Server::Python3Server(QObject* parent)
PythonServer::PythonServer(QObject* parent)
: QObject(parent)
{
}
......@@ -31,22 +31,28 @@ namespace
{
QString pyObjectToQString(PyObject* obj)
{
#if PY_MAJOR_VERSION == 3
return QString::fromUtf8(PyUnicode_AsUTF8(obj));
#elif PY_MAJOR_VERSION == 2
return QString::fromLocal8Bit(PyString_AsString(obj));
#else
#warning Unknown Python version
#endif
}
}
void Python3Server::login()
void PythonServer::login()
{
Py_Initialize();
m_pModule = PyImport_AddModule("__main__");
}
void Python3Server::runPythonCommand(const QString& command) const
void PythonServer::runPythonCommand(const QString& command) const
{
PyRun_SimpleString(command.toStdString().c_str());
}
QString Python3Server::getError() const
QString PythonServer::getError() const
{
PyObject *errorPython = PyObject_GetAttrString(m_pModule, "errorPythonBackend");
PyObject *error = PyObject_GetAttrString(errorPython, "value");
......@@ -54,7 +60,7 @@ QString Python3Server::getError() const
return pyObjectToQString(error);
}
QString Python3Server::getOutput() const
QString PythonServer::getOutput() const
{
PyObject *outputPython = PyObject_GetAttrString(m_pModule, "outputPythonBackend");
PyObject *output = PyObject_GetAttrString(outputPython, "value");
......
......@@ -18,19 +18,19 @@
Copyright (C) 2015 Minh Ngo <minh@fedoraproject.org>
*/
#ifndef _PYTHON3SERVER_H
#define _PYTHON3SERVER_H
#ifndef _PYTHONSERVER_H
#define _PYTHONSERVER_H
#include <QObject>
#include <QString>
struct _object;
typedef _object PyObject;
class Python3Server : public QObject
class PythonServer : public QObject
{
Q_OBJECT
public:
Python3Server(QObject* parent = nullptr);
PythonServer(QObject* parent = nullptr);
public Q_SLOTS:
Q_SCRIPTABLE void login();
......
......@@ -29,13 +29,25 @@
#include <QDebug>
#include <QDir>
#include <QStandardPaths>
#include <QDBusConnection>
#include <QDBusInterface>
#include <QDBusReply>
#include <KProcess>
#include <KDirWatch>
#include <defaultvariablemodel.h>
PythonSession::PythonSession(Cantor::Backend* backend) : Session(backend),
m_variableModel(new Cantor::DefaultVariableModel(this))
PythonSession::PythonSession(Cantor::Backend* backend, const QString serverName, const QString DbusChannelName)
: Session(backend)
, m_variableModel(new Cantor::DefaultVariableModel(this))
, m_pIface(nullptr)
, m_pProcess(nullptr)
, serverName(serverName)
, DbusChannelName(DbusChannelName)
{
}
......@@ -48,6 +60,49 @@ void PythonSession::login()
qDebug()<<"login";
emit loginStarted();
// TODO: T6113, T6114
if (m_pProcess)
m_pProcess->deleteLater();
m_pProcess = new KProcess(this);
m_pProcess->setOutputChannelMode(KProcess::SeparateChannels);
(*m_pProcess) << QStandardPaths::findExecutable(serverName);
m_pProcess->start();
m_pProcess->waitForStarted();
m_pProcess->waitForReadyRead();
QTextStream stream(m_pProcess->readAllStandardOutput());
const QString& readyStatus = QString::fromLatin1("ready");
while (m_pProcess->state() == QProcess::Running)
{
const QString& rl = stream.readLine();
if (rl == readyStatus)
break;
}
if (!QDBusConnection::sessionBus().isConnected())
{
qWarning() << "Can't connect to the D-Bus session bus.\n"
"To start it, run: eval `dbus-launch --auto-syntax`";
return;
}
const QString& serviceName = DbusChannelName + QString::fromLatin1("-%1").arg(m_pProcess->pid());
m_pIface = new QDBusInterface(serviceName,
QString::fromLatin1("/"), QString(), QDBusConnection::sessionBus());
if (!m_pIface->isValid())
{
qWarning() << QDBusConnection::sessionBus().lastError().message();
return;
}
m_pIface->call(QString::fromLatin1("login"));
if(integratePlots())
{
qDebug() << "integratePlots";
......@@ -89,6 +144,9 @@ void PythonSession::login()
void PythonSession::logout()
{
// TODO: T6113, T6114
m_pProcess->terminate();
qDebug()<<"logout";
QDir removePlotFigures;
......@@ -101,6 +159,10 @@ void PythonSession::logout()
void PythonSession::interrupt()
{
// TODO: T6113, T6114
if (m_pProcess->pid())
m_pProcess->kill();
qDebug()<<"interrupt";
foreach(Cantor::Expression* e, m_runningExpressions)
......@@ -385,3 +447,29 @@ QAbstractItemModel* PythonSession::variableModel()
{
return m_variableModel;
}
void PythonSession::runPythonCommand(const QString& command) const
{
// TODO: T6113, T6114
m_pIface->call(QString::fromLatin1("runPythonCommand"), command);
}
QString PythonSession::getOutput() const
{
// TODO: T6113, T6114
const QDBusReply<QString>& reply = m_pIface->call(QString::fromLatin1("getOutput"));
if (reply.isValid())
return reply.value();
return reply.error().message();
}
QString PythonSession::getError() const
{
// TODO: T6113, T6114
const QDBusReply<QString>& reply = m_pIface->call(QString::fromLatin1("getError"));
if (reply.isValid())
return reply.value();
return reply.error().message();
}
\ No newline at end of file
......@@ -31,12 +31,14 @@ class DefaultVariableModel;
class PythonExpression;
class KDirWatch;
class QDBusInterface;
class KProcess;
class CANTOR_EXPORT PythonSession : public Cantor::Session
{
Q_OBJECT
public:
PythonSession(Cantor::Backend* backend);
PythonSession(Cantor::Backend* backend, const QString serverName, const QString DbusChannelName);
~PythonSession() override;
void login() Q_DECL_OVERRIDE;
......@@ -61,6 +63,11 @@ class CANTOR_EXPORT PythonSession : public Cantor::Session
QList<PythonExpression*> m_runningExpressions;
PythonExpression* m_currentExpression;
QDBusInterface* m_pIface;
KProcess* m_pProcess;
QString serverName;
QString DbusChannelName;
protected:
QString m_output;
QString m_error;
......@@ -74,9 +81,9 @@ class CANTOR_EXPORT PythonSession : public Cantor::Session
QString identifyVariableModule(const QString& command) const;
bool identifyKeywords(const QString& command);
virtual void runPythonCommand(const QString& command) const = 0;
virtual QString getOutput() const = 0;
virtual QString getError() const = 0;
void runPythonCommand(const QString& command) const;
QString getOutput() const;
QString getError() const;
virtual void readExpressionOutput(const QString& commandProcessing);
......
......@@ -29,3 +29,5 @@ endif()
install(FILES cantor_python2.knsrc DESTINATION ${KDE_INSTALL_CONFDIR})
install(FILES python2backend.kcfg DESTINATION ${KDE_INSTALL_KCFGDIR})
add_subdirectory(python2server)
\ No newline at end of file
include_directories(${PYTHON_INCLUDE_DIR})
set(Python2Server_SRCS
main.cpp
../../python/pythonserver.cpp
)
add_executable(cantor_python2server ${Python2Server_SRCS})
set_target_properties(cantor_python2server PROPERTIES INSTALL_RPATH_USE_LINK_PATH false)
target_link_libraries(cantor_python2server
${PYTHON_LIBRARIES}
Qt5::Widgets
Qt5::DBus)
install(TARGETS cantor_python2server ${KDE_INSTALL_TARGETS_DEFAULT_ARGS})
/*
This program is free software; you can redistribute it and/or
modify it under the terms of the GNU General Public License
as published by the Free Software Foundation; either version 2
of the License, or (at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 51 Franklin Street, Fifth Floor,
Boston, MA 02110-1301, USA.
---
Copyright (C) 2015 Minh Ngo <minh@fedoraproject.org>
*/
#include <QDebug>
#include <QApplication>
#include <QDBusError>
#include <QDBusConnection>
#include <QTextStream>
#include "../../python/pythonserver.h"
int main(int argc, char *argv[])
{
QCoreApplication app(argc, argv);
if (!QDBusConnection::sessionBus().isConnected())
{
qDebug() << "Can't connect to the D-Bus session bus.\n"
"To start it, run: eval `dbus-launch --auto-syntax`";
return 1;
}
const QString& serviceName = QString::fromLatin1("org.kde.Cantor.Python2-%1").arg(app.applicationPid());
if (!QDBusConnection::sessionBus().registerService(serviceName))
{
qDebug() << QDBusConnection::sessionBus().lastError().message();
return 2;
}
PythonServer server;
QDBusConnection::sessionBus().registerObject(QString::fromLatin1("/"), &server, QDBusConnection::ExportAllSlots);
QTextStream(stdout) << "ready" << endl;
return app.exec();
}
......@@ -20,47 +20,18 @@
#include "python2session.h"
#include "settings.h"
#include "../python/pythonexpression.h"
#include <Python.h>
#include <QDebug>
#include <QDBusConnection>
#include <QDBusInterface>
#include <QDBusReply>
Python2Session::Python2Session(Cantor::Backend* backend)
: PythonSession(backend)
, m_pModule(nullptr)
{
}
void Python2Session::runPythonCommand(const QString& command) const
{
PyRun_SimpleString(command.toStdString().c_str());
}
void Python2Session::login()
{
Py_Initialize();
m_pModule = PyImport_AddModule("__main__");
PythonSession::login();
}
#include <KProcess>
QString Python2Session::getOutput() const
{
PyObject *outputPython = PyObject_GetAttrString(m_pModule, "outputPythonBackend");
PyObject *output = PyObject_GetAttrString(outputPython, "value");
return pyObjectToQString(output);
}
QString Python2Session::getError() const
{
PyObject *errorPython = PyObject_GetAttrString(m_pModule, "errorPythonBackend");
PyObject *error = PyObject_GetAttrString(errorPython, "value");
return pyObjectToQString(error);
}
QString Python2Session::pyObjectToQString(PyObject* obj) const
Python2Session::Python2Session(Cantor::Backend* backend)
: PythonSession(backend, QLatin1String("cantor_python2server"), QLatin1String("org.kde.Cantor.Python2"))
{
return QString::fromLocal8Bit(PyString_AsString(obj));
}
bool Python2Session::integratePlots() const
......
......@@ -23,28 +23,13 @@
#include "../python/pythonsession.h"
struct _object;
typedef _object PyObject;
class Python2Session : public PythonSession
{
public:
Python2Session(Cantor::Backend* backend);
void login() Q_DECL_OVERRIDE;
bool integratePlots() const Q_DECL_OVERRIDE;
QStringList autorunScripts() const Q_DECL_OVERRIDE;
private:
void runPythonCommand(const QString& command) const Q_DECL_OVERRIDE;
QString getOutput() const Q_DECL_OVERRIDE;
QString getError() const Q_DECL_OVERRIDE;
QString pyObjectToQString(PyObject* obj) const;
private:
PyObject *m_pModule;
};
#endif
include_directories(${PYTHONLIBS3_INCLUDE_DIRS})
set(Python3Server_SRCS
python3server.cpp
main.cpp
../../python/pythonserver.cpp
)
add_executable(cantor_python3server ${Python3Server_SRCS})
......
......@@ -24,7 +24,7 @@
#include <QDBusConnection>
#include <QTextStream>
#include "python3server.h"
#include "../../python/pythonserver.h"
int main(int argc, char *argv[])
{
......@@ -45,7 +45,7 @@ int main(int argc, char *argv[])
return 2;
}
Python3Server server;
PythonServer server;
QDBusConnection::sessionBus().registerObject(QString::fromLatin1("/"), &server, QDBusConnection::ExportAllSlots);
QTextStream(stdout) << "ready" << endl;
......
......@@ -20,113 +20,10 @@
#include "python3session.h"
#include "settings.h"
#include "../python/pythonexpression.h"
#include <QDebug>
#include <QDBusConnection>
#include <QDBusInterface>
#include <QDBusReply>
#include <KProcess>
Python3Session::Python3Session(Cantor::Backend* backend)
: PythonSession(backend)
, m_pIface(nullptr)
, m_pProcess(nullptr)
{
}
void Python3Session::login()
: PythonSession(backend, QLatin1String("cantor_python3server"), QLatin1String("org.kde.Cantor.Python3"))
{
if (m_pProcess)
m_pProcess->deleteLater();
m_pProcess = new KProcess(this);
m_pProcess->setOutputChannelMode(KProcess::SeparateChannels);
(*m_pProcess) << QStandardPaths::findExecutable(QLatin1String("cantor_python3server"));
m_pProcess->start();
m_pProcess->waitForStarted();
m_pProcess->waitForReadyRead();
QTextStream stream(m_pProcess->readAllStandardOutput());
const QString& readyStatus = QString::fromLatin1("ready");
while (m_pProcess->state() == QProcess::Running)
{
const QString& rl = stream.readLine();
if (rl == readyStatus)
break;
}
if (!QDBusConnection::sessionBus().isConnected())
{
qWarning() << "Can't connect to the D-Bus session bus.\n"
"To start it, run: eval `dbus-launch --auto-syntax`";
return;
}
const QString& serviceName = QString::fromLatin1("org.kde.Cantor.Python3-%1").arg(m_pProcess->pid());
m_pIface = new QDBusInterface(serviceName,
QString::fromLatin1("/"), QString(), QDBusConnection::sessionBus());
if (!m_pIface->isValid())
{
qWarning() << QDBusConnection::sessionBus().lastError().message();
return;
}
m_pIface->call(QString::fromLatin1("login"));
PythonSession::login();
}
void Python3Session::logout()
{
m_pProcess->terminate();
PythonSession::logout();
}
void Python3Session::interrupt()
{
if (m_pProcess->pid())
m_pProcess->kill();
PythonSession::interrupt();
}
void Python3Session::runPythonCommand(const QString& command) const
{
m_pIface->call(QString::fromLatin1("runPythonCommand"), command);
}
void Python3Session::readExpressionOutput(const QString& commandProcessing)
{
runClassOutputPython();
runPythonCommand(commandProcessing);
m_output = getOutput();
m_error = getError();
updateOutput();
}
QString Python3Session::getOutput() const
{
const QDBusReply<QString>& reply = m_pIface->call(QString::fromLatin1("getOutput"));
if (reply.isValid())
return reply.value();
return reply.error().message();
}
QString Python3Session::getError() const
{
const QDBusReply<QString>& reply = m_pIface->call(QString::fromLatin1("getError"));
if (reply.isValid())
return reply.value();
return reply.error().message();
}
bool Python3Session::integratePlots() const
......
......@@ -23,34 +23,13 @@
#include "../python/pythonsession.h"
class QDBusInterface;
class KProcess;
class Python3Session : public PythonSession
{
Q_OBJECT
public:
Python3Session(Cantor::Backend* backend);
void login() override;
void logout() override;
void interrupt() override;
bool integratePlots() const override;
QStringList autorunScripts() const override;
private:
void runPythonCommand(const QString& command) const override;
void readExpressionOutput(const QString& commandProcessing) override;
QString getOutput() const override;
QString getError() const override;
private:
QDBusInterface* m_pIface;
KProcess* m_pProcess;
Q_SIGNALS:
void updateHighlighter();
};
#endif
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