2018-02-21 16:37:46 +00:00
|
|
|
|
2018-02-11 17:59:23 +00:00
|
|
|
#include "PythonAPI.h"
|
|
|
|
#include "cutter.h"
|
2018-02-22 21:08:06 +00:00
|
|
|
#include "JupyterConnection.h"
|
|
|
|
#include "NestedIPyKernel.h"
|
2018-02-11 17:59:23 +00:00
|
|
|
|
2018-02-21 16:37:46 +00:00
|
|
|
#include <QFile>
|
|
|
|
|
2018-02-11 17:59:23 +00:00
|
|
|
PyObject *api_version(PyObject *self, PyObject *null)
|
|
|
|
{
|
|
|
|
Q_UNUSED(self)
|
|
|
|
Q_UNUSED(null)
|
|
|
|
return PyUnicode_FromString("Cutter version " CUTTER_VERSION);
|
|
|
|
}
|
|
|
|
|
|
|
|
PyObject *api_cmd(PyObject *self, PyObject *args)
|
|
|
|
{
|
|
|
|
Q_UNUSED(self);
|
|
|
|
char *command;
|
|
|
|
char *result = (char*) "";
|
|
|
|
if (PyArg_ParseTuple(args, "s:command", &command))
|
|
|
|
{
|
|
|
|
result = Core()->cmd(command).toUtf8().data();
|
|
|
|
}
|
|
|
|
return PyUnicode_FromString(result);
|
|
|
|
}
|
|
|
|
|
2018-02-28 22:00:24 +00:00
|
|
|
PyObject *api_cmdj(PyObject *self, PyObject *args)
|
|
|
|
{
|
|
|
|
Q_UNUSED(self);
|
|
|
|
char *command;
|
|
|
|
char *result = (char*) "";
|
|
|
|
if (PyArg_ParseTuple(args, "s:command", &command))
|
|
|
|
{
|
|
|
|
result = Core()->cmd(command).toUtf8().data();
|
|
|
|
PyObject *jsonModule = PyImport_ImportModule("json");
|
|
|
|
PyObject *loadsFunc = PyObject_GetAttrString(jsonModule, "loads");
|
|
|
|
if (!PyCallable_Check(loadsFunc)) {
|
|
|
|
PyErr_SetString(PyExc_SystemError, "Could not parse JSON.");
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
return PyEval_CallFunction(loadsFunc, "(s)", result);
|
|
|
|
}
|
|
|
|
return Py_None;
|
|
|
|
}
|
|
|
|
|
2018-02-11 17:59:23 +00:00
|
|
|
PyMethodDef CutterMethods[] = {
|
|
|
|
{"version", api_version, METH_NOARGS,
|
|
|
|
"Returns Cutter current version"},
|
|
|
|
{"cmd", api_cmd, METH_VARARGS,
|
|
|
|
"Execute a command inside Cutter"},
|
2018-02-28 22:00:24 +00:00
|
|
|
{"cmdj", api_cmdj, METH_VARARGS,
|
|
|
|
"Execute a JSON command and return the result as a dictionnary"},
|
2018-02-11 17:59:23 +00:00
|
|
|
{NULL, NULL, 0, NULL}
|
|
|
|
};
|
|
|
|
|
|
|
|
PyModuleDef CutterModule = {
|
|
|
|
PyModuleDef_HEAD_INIT, "cutter", NULL, -1, CutterMethods,
|
|
|
|
NULL, NULL, NULL, NULL
|
|
|
|
};
|
|
|
|
|
|
|
|
PyObject *PyInit_api()
|
|
|
|
{
|
|
|
|
return PyModule_Create(&CutterModule);
|
|
|
|
}
|
2018-02-21 16:37:46 +00:00
|
|
|
|
|
|
|
|
|
|
|
// -----------------------------
|
|
|
|
|
|
|
|
|
|
|
|
PyObject *api_internal_launch_ipykernel(PyObject *self, PyObject *args, PyObject *kw)
|
|
|
|
{
|
2018-02-22 18:51:02 +00:00
|
|
|
Q_UNUSED(self);
|
|
|
|
Q_UNUSED(kw);
|
|
|
|
|
2018-02-21 16:37:46 +00:00
|
|
|
QStringList argv;
|
2018-02-22 18:51:02 +00:00
|
|
|
PyObject *argvListObject;
|
2018-02-21 16:37:46 +00:00
|
|
|
|
2018-02-22 18:51:02 +00:00
|
|
|
if (!PyArg_ParseTuple(args, "O", &argvListObject)
|
|
|
|
|| !PyList_Check(argvListObject))
|
2018-02-21 16:37:46 +00:00
|
|
|
{
|
2018-02-23 15:38:32 +00:00
|
|
|
const char *msg = "Invalid args passed to api_internal_launch_ipykernel().";
|
|
|
|
qWarning() << msg;
|
|
|
|
PyErr_SetString(PyExc_RuntimeError, msg);
|
2018-02-22 18:51:02 +00:00
|
|
|
return nullptr;
|
2018-02-21 16:37:46 +00:00
|
|
|
}
|
|
|
|
|
2018-02-22 18:51:02 +00:00
|
|
|
for (int i = 0; i < PyList_Size(argvListObject); i++)
|
|
|
|
{
|
|
|
|
PyObject *o = PyList_GetItem(argvListObject, i);
|
|
|
|
QString s = QString::fromUtf8(PyUnicode_AsUTF8(o));
|
|
|
|
argv.append(s);
|
|
|
|
}
|
2018-02-21 16:37:46 +00:00
|
|
|
|
2018-02-22 21:08:06 +00:00
|
|
|
long id = Jupyter()->startNestedIPyKernel(argv);
|
2018-02-21 16:37:46 +00:00
|
|
|
|
2018-02-22 21:08:06 +00:00
|
|
|
return PyLong_FromLong(id);
|
|
|
|
}
|
2018-02-21 16:37:46 +00:00
|
|
|
|
2018-02-23 12:04:53 +00:00
|
|
|
PyObject *api_internal_kernel_interface_send_signal(PyObject *, PyObject *args)
|
2018-02-22 21:08:06 +00:00
|
|
|
{
|
|
|
|
long id;
|
2018-02-23 12:04:53 +00:00
|
|
|
long signum;
|
2018-02-21 16:37:46 +00:00
|
|
|
|
2018-02-23 12:04:53 +00:00
|
|
|
if (!PyArg_ParseTuple(args, "ll", &id, &signum))
|
2018-02-21 16:37:46 +00:00
|
|
|
{
|
2018-02-23 15:38:32 +00:00
|
|
|
const char *msg = "Invalid args passed to api_internal_kernel_interface_send_signal().";
|
|
|
|
qWarning() << msg;
|
|
|
|
PyErr_SetString(PyExc_RuntimeError, msg);
|
2018-02-22 21:08:06 +00:00
|
|
|
return nullptr;
|
2018-02-21 16:37:46 +00:00
|
|
|
}
|
|
|
|
|
2018-02-23 12:04:53 +00:00
|
|
|
NestedIPyKernel *kernel = Jupyter()->getNestedIPyKernel(id);
|
|
|
|
if(kernel)
|
|
|
|
{
|
|
|
|
kernel->sendSignal(signum);
|
|
|
|
}
|
2018-02-21 16:37:46 +00:00
|
|
|
|
2018-02-22 21:08:06 +00:00
|
|
|
Py_RETURN_NONE;
|
2018-02-21 16:37:46 +00:00
|
|
|
}
|
|
|
|
|
2018-02-23 12:04:53 +00:00
|
|
|
PyObject *api_internal_kernel_interface_poll(PyObject *, PyObject *args)
|
|
|
|
{
|
|
|
|
long id;
|
|
|
|
|
|
|
|
if (!PyArg_ParseTuple(args, "l", &id))
|
|
|
|
{
|
2018-02-23 15:38:32 +00:00
|
|
|
const char *msg = "Invalid args passed to api_internal_kernel_interface_poll().";
|
|
|
|
qWarning() << msg;
|
|
|
|
PyErr_SetString(PyExc_RuntimeError, msg);
|
2018-02-23 12:04:53 +00:00
|
|
|
return nullptr;
|
|
|
|
}
|
|
|
|
|
2018-02-23 16:42:54 +00:00
|
|
|
QVariant v = Jupyter()->pollNestedIPyKernel(id);
|
2018-02-23 12:04:53 +00:00
|
|
|
bool ok;
|
|
|
|
auto ret = static_cast<long>(v.toLongLong(&ok));
|
|
|
|
if(ok)
|
|
|
|
{
|
|
|
|
return PyLong_FromLong(ret);
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
Py_RETURN_NONE;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2018-02-23 15:24:19 +00:00
|
|
|
PyObject *api_internal_thread_set_async_exc(PyObject *, PyObject *args)
|
|
|
|
{
|
|
|
|
long id;
|
|
|
|
PyObject *exc;
|
|
|
|
|
|
|
|
if (!PyArg_ParseTuple(args, "lO", &id, &exc))
|
|
|
|
{
|
2018-02-23 15:38:32 +00:00
|
|
|
const char *msg = "Invalid args passed to api_internal_thread_set_async_exc().";
|
|
|
|
qWarning() << msg;
|
|
|
|
PyErr_SetString(PyExc_RuntimeError, msg);
|
2018-02-23 15:24:19 +00:00
|
|
|
return nullptr;
|
|
|
|
}
|
|
|
|
|
|
|
|
int ret = PyThreadState_SetAsyncExc(id, exc);
|
|
|
|
return PyLong_FromLong(ret);
|
|
|
|
}
|
|
|
|
|
2018-02-21 16:37:46 +00:00
|
|
|
PyMethodDef CutterInternalMethods[] = {
|
|
|
|
{"launch_ipykernel", (PyCFunction)api_internal_launch_ipykernel, METH_VARARGS | METH_KEYWORDS,
|
|
|
|
"Launch an IPython Kernel in a subinterpreter"},
|
2018-02-23 12:04:53 +00:00
|
|
|
{"kernel_interface_send_signal", (PyCFunction)api_internal_kernel_interface_send_signal, METH_VARARGS, ""},
|
|
|
|
{"kernel_interface_poll", (PyCFunction)api_internal_kernel_interface_poll, METH_VARARGS, ""},
|
2018-02-23 15:24:19 +00:00
|
|
|
{"thread_set_async_exc", (PyCFunction)api_internal_thread_set_async_exc, METH_VARARGS, ""},
|
2018-02-21 16:37:46 +00:00
|
|
|
{NULL, NULL, 0, NULL}
|
|
|
|
};
|
|
|
|
|
|
|
|
PyModuleDef CutterInternalModule = {
|
|
|
|
PyModuleDef_HEAD_INIT, "cutter_internal", NULL, -1, CutterInternalMethods,
|
|
|
|
NULL, NULL, NULL, NULL
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
PyObject *PyInit_api_internal()
|
|
|
|
{
|
|
|
|
return PyModule_Create(&CutterInternalModule);
|
|
|
|
}
|
|
|
|
|