Move everything Jupyter related out of PythonManager

Fix importing cutter in Python
This commit is contained in:
Florian Märkl 2019-02-03 12:31:59 +01:00
parent b9c859bc0c
commit 74a201ecba
5 changed files with 71 additions and 49 deletions

View File

@ -5,6 +5,7 @@
#include "JupyterConnection.h" #include "JupyterConnection.h"
#include "NestedIPyKernel.h" #include "NestedIPyKernel.h"
#include "PythonManager.h" #include "PythonManager.h"
#include "QtResImporter.h"
#include <QVariant> #include <QVariant>
#include <QDebug> #include <QDebug>
@ -18,6 +19,7 @@ JupyterConnection *JupyterConnection::getInstance()
JupyterConnection::JupyterConnection(QObject *parent) : QObject(parent) JupyterConnection::JupyterConnection(QObject *parent) : QObject(parent)
{ {
connect(Python(), &PythonManager::willShutDown, this, &JupyterConnection::stop);
} }
JupyterConnection::~JupyterConnection() JupyterConnection::~JupyterConnection()
@ -31,18 +33,29 @@ void JupyterConnection::start()
return; return;
} }
notebookInstanceExists = Python()->startJupyterNotebook(); notebookInstanceExists = startJupyterNotebook();
emit urlReceived(getUrl()); emit urlReceived(getUrl());
} }
void JupyterConnection::stop()
{
if (cutterNotebookAppInstance) {
Python()->restoreThread();
auto stopFunc = PyObject_GetAttrString(cutterNotebookAppInstance, "stop");
PyObject_CallObject(stopFunc, nullptr);
Py_DECREF(cutterNotebookAppInstance);
Python()->saveThread();
}
}
QString JupyterConnection::getUrl() QString JupyterConnection::getUrl()
{ {
if (!notebookInstanceExists) { if (!notebookInstanceExists) {
return nullptr; return nullptr;
} }
QString url = Python()->getJupyterUrl(); QString url = getJupyterUrl();
return url; return url;
} }
@ -94,4 +107,39 @@ QVariant JupyterConnection::pollNestedIPyKernel(long id)
return v; return v;
} }
bool JupyterConnection::startJupyterNotebook()
{
Python()->restoreThread();
if (!cutterJupyterModule) {
cutterJupyterModule = QtResImport("cutter_jupyter");
}
PyObject* startFunc = PyObject_GetAttrString(cutterJupyterModule, "start_jupyter");
if (!startFunc) {
qWarning() << "Couldn't get attribute start_jupyter.";
return false;
}
cutterNotebookAppInstance = PyObject_CallObject(startFunc, nullptr);
Python()->saveThread();
return cutterNotebookAppInstance != nullptr;
}
QString JupyterConnection::getJupyterUrl()
{
Python()->restoreThread();
auto urlWithToken = PyObject_GetAttrString(cutterNotebookAppInstance, "url_with_token");
auto asciiBytes = PyUnicode_AsASCIIString(urlWithToken);
auto urlWithTokenString = QString::fromUtf8(PyBytes_AsString(asciiBytes));
Py_DECREF(asciiBytes);
Py_DECREF(urlWithToken);
Python()->saveThread();
return urlWithTokenString;
}
#endif #endif

View File

@ -7,6 +7,7 @@
#include <QMap> #include <QMap>
class NestedIPyKernel; class NestedIPyKernel;
typedef struct _object PyObject;
class JupyterConnection : public QObject class JupyterConnection : public QObject
{ {
@ -25,6 +26,9 @@ public:
NestedIPyKernel *getNestedIPyKernel(long id); NestedIPyKernel *getNestedIPyKernel(long id);
QVariant pollNestedIPyKernel(long id); QVariant pollNestedIPyKernel(long id);
public slots:
void stop();
signals: signals:
void urlReceived(const QString &url); void urlReceived(const QString &url);
void creationFailed(); void creationFailed();
@ -34,6 +38,12 @@ private:
long nextKernelId = 1; long nextKernelId = 1;
bool notebookInstanceExists = false; bool notebookInstanceExists = false;
PyObject *cutterJupyterModule = nullptr;
PyObject *cutterNotebookAppInstance = nullptr;
bool startJupyterNotebook();
QString getJupyterUrl();
}; };

View File

@ -66,7 +66,7 @@ PyMethodDef CutterMethods[] = {
"Refresh Cutter widgets" "Refresh Cutter widgets"
}, },
{ {
"message", (PyCFunction) api_message, METH_VARARGS | METH_KEYWORDS, "message", (PyCFunction)(void *)/* don't remove this double cast! */api_message, METH_VARARGS | METH_KEYWORDS,
"Print message" "Print message"
}, },
{NULL, NULL, 0, NULL} {NULL, NULL, 0, NULL}

View File

@ -32,11 +32,7 @@ PythonManager::~PythonManager()
restoreThread(); restoreThread();
if (cutterNotebookAppInstance) { emit willShutDown();
auto stopFunc = PyObject_GetAttrString(cutterNotebookAppInstance, "stop");
PyObject_CallObject(stopFunc, nullptr);
Py_DECREF(cutterNotebookAppInstance);
}
Py_Finalize(); Py_Finalize();
@ -81,8 +77,9 @@ void PythonManager::initialize()
Py_Initialize(); Py_Initialize();
PyEval_InitThreads(); PyEval_InitThreads();
RegQtResImporter();
// Import other modules // Import other modules
cutterJupyterModule = QtResImport("cutter_jupyter");
cutterPluginModule = QtResImport("cutter_plugin"); cutterPluginModule = QtResImport("cutter_plugin");
saveThread(); saveThread();
@ -108,36 +105,6 @@ void PythonManager::addPythonPath(char *path) {
saveThread(); saveThread();
} }
bool PythonManager::startJupyterNotebook()
{
restoreThread();
PyObject* startFunc = PyObject_GetAttrString(cutterJupyterModule, "start_jupyter");
if (!startFunc) {
qWarning() << "Couldn't get attribute start_jupyter.";
return false;
}
cutterNotebookAppInstance = PyObject_CallObject(startFunc, nullptr);
saveThread();
return cutterNotebookAppInstance != nullptr;
}
QString PythonManager::getJupyterUrl()
{
restoreThread();
auto urlWithToken = PyObject_GetAttrString(cutterNotebookAppInstance, "url_with_token");
auto asciiBytes = PyUnicode_AsASCIIString(urlWithToken);
auto urlWithTokenString = QString::fromUtf8(PyBytes_AsString(asciiBytes));
Py_DECREF(asciiBytes);
Py_DECREF(urlWithToken);
saveThread();
return urlWithTokenString;
}
CutterPythonPlugin* PythonManager::loadPlugin(const char *pluginName) { CutterPythonPlugin* PythonManager::loadPlugin(const char *pluginName) {
CutterPythonPlugin *plugin = nullptr; CutterPythonPlugin *plugin = nullptr;

View File

@ -7,40 +7,37 @@ class CutterPythonPlugin;
typedef struct _ts PyThreadState; typedef struct _ts PyThreadState;
typedef struct _object PyObject; typedef struct _object PyObject;
class PythonManager class PythonManager: public QObject
{ {
Q_OBJECT
public: public:
static PythonManager *getInstance(); static PythonManager *getInstance();
PythonManager(); PythonManager();
~PythonManager(); ~PythonManager();
void setPythonHome(const QString pythonHome) void setPythonHome(const QString &pythonHome) { customPythonHome = pythonHome; }
{
customPythonHome = pythonHome;
}
void initPythonHome(); void initPythonHome();
void initialize(); void initialize();
void addPythonPath(char *path); void addPythonPath(char *path);
bool startJupyterNotebook();
QString getJupyterUrl();
PyObject *createModule(QString module);
CutterPythonPlugin *loadPlugin(const char *pluginName); CutterPythonPlugin *loadPlugin(const char *pluginName);
void restoreThread(); void restoreThread();
void saveThread(); void saveThread();
signals:
void willShutDown();
private: private:
QString customPythonHome; QString customPythonHome;
wchar_t *pythonHome = nullptr; wchar_t *pythonHome = nullptr;
PyThreadState *pyThreadState = nullptr; PyThreadState *pyThreadState = nullptr;
PyObject *cutterJupyterModule;
PyObject *cutterPluginModule; PyObject *cutterPluginModule;
PyObject *cutterNotebookAppInstance = nullptr;
}; };
#define Python() (PythonManager::getInstance()) #define Python() (PythonManager::getInstance())