cutter/src/utils/JupyterConnection.cpp

126 lines
2.9 KiB
C++
Raw Normal View History

2017-12-13 17:36:00 +00:00
2018-02-09 15:48:02 +00:00
#include <Python.h>
2017-12-13 17:36:00 +00:00
#include <QJsonDocument>
#include <QJsonArray>
#include <QJsonObject>
#include <QDebug>
#include <QThread>
#include <QFile>
2017-12-13 17:36:00 +00:00
#include "JupyterConnection.h"
2018-02-11 17:59:23 +00:00
#include "PythonAPI.h"
2017-12-13 17:36:00 +00:00
2018-02-22 19:56:15 +00:00
Q_GLOBAL_STATIC(JupyterConnection, uniqueInstance)
JupyterConnection *JupyterConnection::getInstance()
{
return uniqueInstance;
}
2017-12-13 17:36:00 +00:00
JupyterConnection::JupyterConnection(QObject *parent) : QObject(parent)
{
}
JupyterConnection::~JupyterConnection()
{
2018-02-09 15:48:02 +00:00
if (cutterNotebookAppInstance)
{
PyEval_RestoreThread(pyThreadState);
auto stopFunc = PyObject_GetAttrString(cutterNotebookAppInstance, "stop");
PyObject_CallObject(stopFunc, nullptr);
Py_DECREF(cutterNotebookAppInstance);
2018-02-22 19:56:15 +00:00
}
2018-02-09 15:48:02 +00:00
2018-02-22 19:56:15 +00:00
if (Py_IsInitialized())
{
2018-02-09 15:48:02 +00:00
Py_FinalizeEx();
}
2017-12-13 17:36:00 +00:00
}
2018-02-22 19:56:15 +00:00
void JupyterConnection::initPython()
2017-12-13 17:36:00 +00:00
{
2018-02-11 17:59:23 +00:00
PyImport_AppendInittab("cutter", &PyInit_api);
PyImport_AppendInittab("cutter_internal", &PyInit_api_internal);
2018-02-09 15:48:02 +00:00
Py_Initialize();
PyEval_InitThreads();
2018-02-22 19:56:15 +00:00
pyThreadState = PyEval_SaveThread();
}
void JupyterConnection::createCutterJupyterModule()
{
PyEval_RestoreThread(pyThreadState);
QFile moduleFile(":/python/cutter_jupyter.py");
moduleFile.open(QIODevice::ReadOnly);
QByteArray moduleCode = moduleFile.readAll();
moduleFile.close();
auto moduleCodeObject = Py_CompileString(moduleCode.constData(), "cutter_jupyter.py", Py_file_input);
if (!moduleCodeObject)
{
qWarning() << "Could not compile cutter_jupyter.";
2018-02-22 18:39:20 +00:00
emit creationFailed();
2018-02-22 19:56:15 +00:00
pyThreadState = PyEval_SaveThread();
return;
}
cutterJupyterModule = PyImport_ExecCodeModule("cutter_jupyter", moduleCodeObject);
Py_DECREF(moduleCodeObject);
2018-02-11 11:40:50 +00:00
if (!cutterJupyterModule)
{
qWarning() << "Could not import cutter_jupyter.";
2018-02-22 18:39:20 +00:00
emit creationFailed();
2018-02-22 19:56:15 +00:00
pyThreadState = PyEval_SaveThread();
2018-02-11 11:40:50 +00:00
return;
}
2018-02-22 19:56:15 +00:00
pyThreadState = PyEval_SaveThread();
}
void JupyterConnection::start()
{
if (cutterNotebookAppInstance)
{
return;
}
if (!Py_IsInitialized())
{
initPython();
}
if (!cutterJupyterModule)
{
createCutterJupyterModule();
}
PyEval_RestoreThread(pyThreadState);
2018-02-09 15:48:02 +00:00
auto startFunc = PyObject_GetAttrString(cutterJupyterModule, "start_jupyter");
cutterNotebookAppInstance = PyObject_CallObject(startFunc, nullptr);
2018-02-22 19:56:15 +00:00
pyThreadState = PyEval_SaveThread();
emit urlReceived(getUrl());
}
QString JupyterConnection::getUrl()
{
if (!cutterNotebookAppInstance)
{
return nullptr;
}
PyEval_RestoreThread(pyThreadState);
2018-02-09 15:48:02 +00:00
auto urlWithToken = PyObject_GetAttrString(cutterNotebookAppInstance, "url_with_token");
auto asciiBytes = PyUnicode_AsASCIIString(urlWithToken);
2018-02-22 19:56:15 +00:00
auto urlWithTokenString = QString::fromUtf8(PyBytes_AsString(asciiBytes));
2018-02-09 15:48:02 +00:00
Py_DECREF(asciiBytes);
Py_DECREF(urlWithToken);
pyThreadState = PyEval_SaveThread();
2018-02-22 19:56:15 +00:00
return urlWithTokenString;
}