mirror of
https://github.com/rizinorg/cutter.git
synced 2025-01-19 02:48:49 +00:00
Prepare IPyKernel communication
This commit is contained in:
parent
05be34ae6b
commit
926a9ffd1e
@ -102,7 +102,8 @@ SOURCES += \
|
||||
CutterApplication.cpp \
|
||||
utils/JupyterConnection.cpp \
|
||||
widgets/JupyterWidget.cpp \
|
||||
utils/PythonAPI.cpp
|
||||
utils/PythonAPI.cpp \
|
||||
utils/NestedIPyKernel.cpp
|
||||
|
||||
HEADERS += \
|
||||
cutter.h \
|
||||
@ -166,7 +167,8 @@ HEADERS += \
|
||||
widgets/VTablesWidget.h \
|
||||
utils/JupyterConnection.h \
|
||||
widgets/JupyterWidget.h \
|
||||
utils/PythonAPI.h
|
||||
utils/PythonAPI.h \
|
||||
utils/NestedIPyKernel.h
|
||||
|
||||
FORMS += \
|
||||
dialogs/AboutDialog.ui \
|
||||
|
@ -7,6 +7,9 @@ from ipykernel.ipkernel import IPythonKernel
|
||||
|
||||
# TODO: Make this behave like a Popen instance and pipe it to IPyKernelInterfaceJupyter!
|
||||
class IPyKernelInterfaceKernel:
|
||||
def kill(self):
|
||||
print("No!! Not into the pit! It burns!!!")
|
||||
|
||||
def poll(self):
|
||||
return None
|
||||
|
||||
|
@ -5,6 +5,12 @@ from notebook.notebookapp import *
|
||||
|
||||
# TODO: this must behave like a Popen instance and pipe to IPyKernelInterfaceKernel!
|
||||
class IPyKernelInterfaceJupyter:
|
||||
def __init__(self, id):
|
||||
self._id = id
|
||||
|
||||
def kill(self):
|
||||
print("DIE!! " + str(self._id))
|
||||
|
||||
def poll(self):
|
||||
return None
|
||||
|
||||
@ -45,8 +51,8 @@ class CutterInternalIPyKernelManager(IOLoopKernelManager):
|
||||
|
||||
# TODO: kernel_cmd including python executable and so on is currently used for argv. Make a clean version!
|
||||
import cutter_internal
|
||||
cutter_internal.launch_ipykernel(kernel_cmd, env=env, **kw)
|
||||
self.kernel = IPyKernelInterfaceJupyter()
|
||||
id = cutter_internal.launch_ipykernel(kernel_cmd, env=env, **kw)
|
||||
self.kernel = IPyKernelInterfaceJupyter(id)
|
||||
# self._launch_kernel(kernel_cmd, env=env,
|
||||
# **kw)
|
||||
|
||||
|
@ -9,6 +9,7 @@
|
||||
#include <QFile>
|
||||
|
||||
#include "JupyterConnection.h"
|
||||
#include "NestedIPyKernel.h"
|
||||
#include "PythonAPI.h"
|
||||
|
||||
Q_GLOBAL_STATIC(JupyterConnection, uniqueInstance)
|
||||
@ -123,4 +124,25 @@ QString JupyterConnection::getUrl()
|
||||
pyThreadState = PyEval_SaveThread();
|
||||
|
||||
return urlWithTokenString;
|
||||
}
|
||||
}
|
||||
|
||||
long JupyterConnection::startNestedIPyKernel(const QStringList &argv)
|
||||
{
|
||||
NestedIPyKernel *kernel = NestedIPyKernel::start(argv);
|
||||
|
||||
if (!kernel)
|
||||
{
|
||||
qWarning() << "Could not start nested IPyKernel.";
|
||||
return 0;
|
||||
}
|
||||
|
||||
long id = nextKernelId++;
|
||||
kernels.insert(id, kernel);
|
||||
|
||||
return id;
|
||||
}
|
||||
|
||||
NestedIPyKernel *JupyterConnection::getNestedIPyKernel(long id)
|
||||
{
|
||||
return kernels[id];
|
||||
}
|
||||
|
@ -3,6 +3,8 @@
|
||||
|
||||
#include <QProcess>
|
||||
|
||||
class NestedIPyKernel;
|
||||
|
||||
struct _object;
|
||||
typedef _object PyObject;
|
||||
|
||||
@ -22,6 +24,9 @@ public:
|
||||
void start();
|
||||
QString getUrl();
|
||||
|
||||
long startNestedIPyKernel(const QStringList &argv);
|
||||
NestedIPyKernel *getNestedIPyKernel(long id);
|
||||
|
||||
signals:
|
||||
void urlReceived(const QString &url);
|
||||
void creationFailed();
|
||||
@ -32,6 +37,9 @@ private:
|
||||
|
||||
PyThreadState *pyThreadState = nullptr;
|
||||
|
||||
QMap<long, NestedIPyKernel *> kernels;
|
||||
long nextKernelId = 1;
|
||||
|
||||
void initPython();
|
||||
void createCutterJupyterModule();
|
||||
};
|
||||
|
70
src/utils/NestedIPyKernel.cpp
Normal file
70
src/utils/NestedIPyKernel.cpp
Normal file
@ -0,0 +1,70 @@
|
||||
|
||||
#include <Python.h>
|
||||
|
||||
#include <QFile>
|
||||
|
||||
#include "cutter.h"
|
||||
#include "NestedIPyKernel.h"
|
||||
|
||||
NestedIPyKernel *NestedIPyKernel::start(const QStringList &argv)
|
||||
{
|
||||
PyThreadState *parentThreadState = PyThreadState_Get();
|
||||
|
||||
PyThreadState *threadState = Py_NewInterpreter();
|
||||
if (!threadState)
|
||||
{
|
||||
qWarning() << "Could not create subinterpreter.";
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
QFile moduleFile(":/python/cutter_ipykernel.py");
|
||||
moduleFile.open(QIODevice::ReadOnly);
|
||||
QByteArray moduleCode = moduleFile.readAll();
|
||||
moduleFile.close();
|
||||
|
||||
auto moduleCodeObject = Py_CompileString(moduleCode.constData(), "cutter_ipykernel.py", Py_file_input);
|
||||
if (!moduleCodeObject)
|
||||
{
|
||||
qWarning() << "Could not compile cutter_ipykernel.";
|
||||
return nullptr;
|
||||
}
|
||||
auto cutterIPykernelModule = PyImport_ExecCodeModule("cutter_ipykernel", moduleCodeObject);
|
||||
Py_DECREF(moduleCodeObject);
|
||||
if (!cutterIPykernelModule)
|
||||
{
|
||||
qWarning() << "Could not import cutter_ipykernel.";
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
auto kernel = new NestedIPyKernel(cutterIPykernelModule, argv);
|
||||
|
||||
PyThreadState_Swap(parentThreadState);
|
||||
|
||||
return kernel;
|
||||
}
|
||||
|
||||
NestedIPyKernel::NestedIPyKernel(PyObject *cutterIPykernelModule, const QStringList &argv)
|
||||
{
|
||||
auto launchFunc = PyObject_GetAttrString(cutterIPykernelModule, "launch_ipykernel");
|
||||
|
||||
PyObject *argvListObject = PyList_New(argv.size());
|
||||
for (int i = 0; i < argv.size(); i++)
|
||||
{
|
||||
QString s = argv[i];
|
||||
PyList_SetItem(argvListObject, i, PyUnicode_DecodeUTF8(s.toUtf8().constData(), s.length(), nullptr));
|
||||
}
|
||||
|
||||
kernel = PyObject_CallFunction(launchFunc, "O", argvListObject);
|
||||
}
|
||||
|
||||
NestedIPyKernel::~NestedIPyKernel()
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
void NestedIPyKernel::kill()
|
||||
{
|
||||
auto parentThreadState = PyThreadState_Swap(threadState);
|
||||
PyObject_CallMethod(kernel, "kill", nullptr);
|
||||
PyThreadState_Swap(parentThreadState);
|
||||
}
|
29
src/utils/NestedIPyKernel.h
Normal file
29
src/utils/NestedIPyKernel.h
Normal file
@ -0,0 +1,29 @@
|
||||
|
||||
|
||||
#ifndef NESTEDIPYKERNEL_H
|
||||
#define NESTEDIPYKERNEL_H
|
||||
|
||||
#include <QStringList>
|
||||
|
||||
struct _object;
|
||||
typedef _object PyObject;
|
||||
|
||||
struct _ts;
|
||||
typedef _ts PyThreadState;
|
||||
|
||||
class NestedIPyKernel
|
||||
{
|
||||
public:
|
||||
static NestedIPyKernel *start(const QStringList &argv);
|
||||
~NestedIPyKernel();
|
||||
|
||||
void kill();
|
||||
|
||||
private:
|
||||
NestedIPyKernel(PyObject *cutterIPykernelModule, const QStringList &argv);
|
||||
|
||||
PyThreadState *threadState;
|
||||
PyObject *kernel;
|
||||
};
|
||||
|
||||
#endif //NESTEDIPYKERNEL_H
|
@ -1,6 +1,8 @@
|
||||
|
||||
#include "PythonAPI.h"
|
||||
#include "cutter.h"
|
||||
#include "JupyterConnection.h"
|
||||
#include "NestedIPyKernel.h"
|
||||
|
||||
#include <QFile>
|
||||
|
||||
@ -67,47 +69,30 @@ PyObject *api_internal_launch_ipykernel(PyObject *self, PyObject *args, PyObject
|
||||
argv.append(s);
|
||||
}
|
||||
|
||||
PyThreadState *parentThreadState = PyThreadState_Get();
|
||||
long id = Jupyter()->startNestedIPyKernel(argv);
|
||||
|
||||
QFile moduleFile(":/python/cutter_ipykernel.py");
|
||||
moduleFile.open(QIODevice::ReadOnly);
|
||||
QByteArray moduleCode = moduleFile.readAll();
|
||||
moduleFile.close();
|
||||
return PyLong_FromLong(id);
|
||||
}
|
||||
|
||||
auto moduleCodeObject = Py_CompileString(moduleCode.constData(), "cutter_ipykernel.py", Py_file_input);
|
||||
if (!moduleCodeObject)
|
||||
PyObject *api_internal_kernel_interface_kill(PyObject *, PyObject *args)
|
||||
{
|
||||
long id;
|
||||
|
||||
if (!PyArg_ParseTuple(args, "l", &id))
|
||||
{
|
||||
qWarning() << "Could not compile cutter_ipykernel.";
|
||||
return nullptr;
|
||||
}
|
||||
auto cutterIPykernelModule = PyImport_ExecCodeModule("cutter_ipykernel", moduleCodeObject);
|
||||
Py_DECREF(moduleCodeObject);
|
||||
if (!cutterIPykernelModule)
|
||||
{
|
||||
qWarning() << "Could not import cutter_ipykernel.";
|
||||
qWarning() << "Invalid args passed to api_internal_kernel_interface_kill().";
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
auto launchFunc = PyObject_GetAttrString(cutterIPykernelModule, "launch_ipykernel");
|
||||
Jupyter()->getNestedIPyKernel(id)->kill();
|
||||
|
||||
argvListObject = PyList_New(argv.size());
|
||||
for (int i = 0; i < argv.size(); i++)
|
||||
{
|
||||
QString s = argv[i];
|
||||
PyList_SetItem(argvListObject, i, PyUnicode_DecodeUTF8(s.toUtf8().constData(), s.length(), nullptr));
|
||||
}
|
||||
|
||||
auto ipyKernel = PyObject_CallFunction(launchFunc, "O", argvListObject);
|
||||
Q_UNUSED(ipyKernel);
|
||||
|
||||
PyThreadState_Swap(parentThreadState);
|
||||
|
||||
return PyLong_FromLong(42);
|
||||
Py_RETURN_NONE;
|
||||
}
|
||||
|
||||
PyMethodDef CutterInternalMethods[] = {
|
||||
{"launch_ipykernel", (PyCFunction)api_internal_launch_ipykernel, METH_VARARGS | METH_KEYWORDS,
|
||||
"Launch an IPython Kernel in a subinterpreter"},
|
||||
{"kernel_interface_kill", (PyCFunction)api_internal_kernel_interface_kill, METH_VARARGS, ""},
|
||||
{NULL, NULL, 0, NULL}
|
||||
};
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user