Jupyter refactoring and cleanup

This commit is contained in:
Florian Märkl 2018-02-22 20:56:15 +01:00 committed by xarkes
parent 3b8bdb6995
commit 05be34ae6b
5 changed files with 75 additions and 10 deletions

View File

@ -28,7 +28,7 @@ def launch_ipykernel(argv):
def run_kernel(): def run_kernel():
app = CutterIPKernelApp.instance() app = CutterIPKernelApp.instance()
app.kernel_class = CutterIPythonKernel app.kernel_class = CutterIPythonKernel
app.log_level = logging.DEBUG #app.log_level = logging.DEBUG
app.initialize(argv[3:]) app.initialize(argv[3:])
app.start() app.start()

View File

@ -11,6 +11,13 @@
#include "JupyterConnection.h" #include "JupyterConnection.h"
#include "PythonAPI.h" #include "PythonAPI.h"
Q_GLOBAL_STATIC(JupyterConnection, uniqueInstance)
JupyterConnection *JupyterConnection::getInstance()
{
return uniqueInstance;
}
JupyterConnection::JupyterConnection(QObject *parent) : QObject(parent) JupyterConnection::JupyterConnection(QObject *parent) : QObject(parent)
{ {
} }
@ -24,18 +31,29 @@ JupyterConnection::~JupyterConnection()
auto stopFunc = PyObject_GetAttrString(cutterNotebookAppInstance, "stop"); auto stopFunc = PyObject_GetAttrString(cutterNotebookAppInstance, "stop");
PyObject_CallObject(stopFunc, nullptr); PyObject_CallObject(stopFunc, nullptr);
Py_DECREF(cutterNotebookAppInstance); Py_DECREF(cutterNotebookAppInstance);
}
if (Py_IsInitialized())
{
Py_FinalizeEx(); Py_FinalizeEx();
} }
} }
void JupyterConnection::start()
void JupyterConnection::initPython()
{ {
PyImport_AppendInittab("cutter", &PyInit_api); PyImport_AppendInittab("cutter", &PyInit_api);
PyImport_AppendInittab("cutter_internal", &PyInit_api_internal); PyImport_AppendInittab("cutter_internal", &PyInit_api_internal);
Py_Initialize(); Py_Initialize();
PyEval_InitThreads(); PyEval_InitThreads();
pyThreadState = PyEval_SaveThread();
}
void JupyterConnection::createCutterJupyterModule()
{
PyEval_RestoreThread(pyThreadState);
QFile moduleFile(":/python/cutter_jupyter.py"); QFile moduleFile(":/python/cutter_jupyter.py");
moduleFile.open(QIODevice::ReadOnly); moduleFile.open(QIODevice::ReadOnly);
QByteArray moduleCode = moduleFile.readAll(); QByteArray moduleCode = moduleFile.readAll();
@ -46,6 +64,7 @@ void JupyterConnection::start()
{ {
qWarning() << "Could not compile cutter_jupyter."; qWarning() << "Could not compile cutter_jupyter.";
emit creationFailed(); emit creationFailed();
pyThreadState = PyEval_SaveThread();
return; return;
} }
cutterJupyterModule = PyImport_ExecCodeModule("cutter_jupyter", moduleCodeObject); cutterJupyterModule = PyImport_ExecCodeModule("cutter_jupyter", moduleCodeObject);
@ -54,16 +73,54 @@ void JupyterConnection::start()
{ {
qWarning() << "Could not import cutter_jupyter."; qWarning() << "Could not import cutter_jupyter.";
emit creationFailed(); emit creationFailed();
pyThreadState = PyEval_SaveThread();
return; return;
} }
pyThreadState = PyEval_SaveThread();
}
void JupyterConnection::start()
{
if (cutterNotebookAppInstance)
{
return;
}
if (!Py_IsInitialized())
{
initPython();
}
if (!cutterJupyterModule)
{
createCutterJupyterModule();
}
PyEval_RestoreThread(pyThreadState);
auto startFunc = PyObject_GetAttrString(cutterJupyterModule, "start_jupyter"); auto startFunc = PyObject_GetAttrString(cutterJupyterModule, "start_jupyter");
cutterNotebookAppInstance = PyObject_CallObject(startFunc, nullptr); cutterNotebookAppInstance = PyObject_CallObject(startFunc, nullptr);
pyThreadState = PyEval_SaveThread();
emit urlReceived(getUrl());
}
QString JupyterConnection::getUrl()
{
if (!cutterNotebookAppInstance)
{
return nullptr;
}
PyEval_RestoreThread(pyThreadState);
auto urlWithToken = PyObject_GetAttrString(cutterNotebookAppInstance, "url_with_token"); auto urlWithToken = PyObject_GetAttrString(cutterNotebookAppInstance, "url_with_token");
auto asciiBytes = PyUnicode_AsASCIIString(urlWithToken); auto asciiBytes = PyUnicode_AsASCIIString(urlWithToken);
emit urlReceived(QString::fromUtf8(PyBytes_AsString(asciiBytes))); auto urlWithTokenString = QString::fromUtf8(PyBytes_AsString(asciiBytes));
Py_DECREF(asciiBytes); Py_DECREF(asciiBytes);
Py_DECREF(urlWithToken); Py_DECREF(urlWithToken);
pyThreadState = PyEval_SaveThread(); pyThreadState = PyEval_SaveThread();
return urlWithTokenString;
} }

View File

@ -14,10 +14,13 @@ class JupyterConnection : public QObject
Q_OBJECT Q_OBJECT
public: public:
static JupyterConnection* getInstance();
JupyterConnection(QObject *parent = nullptr); JupyterConnection(QObject *parent = nullptr);
~JupyterConnection(); ~JupyterConnection();
void start(); void start();
QString getUrl();
signals: signals:
void urlReceived(const QString &url); void urlReceived(const QString &url);
@ -28,6 +31,13 @@ private:
PyObject *cutterNotebookAppInstance = nullptr; PyObject *cutterNotebookAppInstance = nullptr;
PyThreadState *pyThreadState = nullptr; PyThreadState *pyThreadState = nullptr;
void initPython();
void createCutterJupyterModule();
}; };
#define Jupyter() (JupyterConnection::getInstance())
#endif //JUPYTERCONNECTION_H #endif //JUPYTERCONNECTION_H

View File

@ -14,10 +14,9 @@ JupyterWidget::JupyterWidget(QWidget *parent, Qt::WindowFlags flags) :
{ {
ui->setupUi(this); ui->setupUi(this);
jupyter = new JupyterConnection(this); connect(Jupyter(), &JupyterConnection::urlReceived, this, &JupyterWidget::urlReceived);
connect(jupyter, &JupyterConnection::urlReceived, this, &JupyterWidget::urlReceived); connect(Jupyter(), &JupyterConnection::creationFailed, this, &JupyterWidget::creationFailed);
connect(jupyter, &JupyterConnection::creationFailed, this, &JupyterWidget::creationFailed); Jupyter()->start();
jupyter->start();
} }
JupyterWidget::~JupyterWidget() JupyterWidget::~JupyterWidget()
@ -48,6 +47,7 @@ void JupyterWidget::creationFailed()
ui->tabWidget->addTab(failPage, tr("Error")); ui->tabWidget->addTab(failPage, tr("Error"));
} }
JupyterWebView::JupyterWebView(JupyterWidget *mainWidget, QWidget *parent) : QWebEngineView(parent) JupyterWebView::JupyterWebView(JupyterWidget *mainWidget, QWidget *parent) : QWebEngineView(parent)
{ {
this->mainWidget = mainWidget; this->mainWidget = mainWidget;

View File

@ -32,8 +32,6 @@ private slots:
private: private:
std::unique_ptr<Ui::JupyterWidget> ui; std::unique_ptr<Ui::JupyterWidget> ui;
JupyterConnection *jupyter;
}; };