Calling setupPlugin from python

This commit is contained in:
xarkes 2018-06-24 11:51:16 +02:00 committed by Florian Märkl
parent a1110ee2ac
commit 9c2de3e23d
7 changed files with 94 additions and 41 deletions

View File

@ -224,7 +224,8 @@ void CutterApplication::loadPlugins()
foreach (QString fileName, pluginsDir.entryList(QDir::Files)) {
if (fileName.endsWith(".py")) {
// Load python plugins
cutterPlugin = Python()->loadPlugin(fileName.toLatin1().data());
QStringList l = fileName.split(".py");
cutterPlugin = (CutterPlugin*) Python()->loadPlugin(l.at(0).toLatin1().constData());
} else {
// Load C++ plugins
QPluginLoader pluginLoader(pluginsDir.absoluteFilePath(fileName));

View File

@ -2,6 +2,7 @@
#include "PythonManager.h"
#include <marshal.h>
#include <QDebug>
#include <QFile>
#include <QDebug>
@ -30,6 +31,8 @@ PythonManager::~PythonManager()
Py_DECREF(cutterNotebookAppInstance);
}
// TODO PyDECREF plugins
Py_Finalize();
}
@ -78,13 +81,11 @@ void PythonManager::initialize()
cutterJupyterModule = QtResImport("cutter_jupyter");
cutterPluginModule = QtResImport("cutter_plugin");
pyThreadState = PyEval_SaveThread();
saveThread();
}
void PythonManager::addPythonPath(char *path) {
if (pyThreadState) {
PyEval_RestoreThread(pyThreadState);
}
restoreThread();
PyObject *sysModule = PyImport_ImportModule("sys");
if (!sysModule) {
@ -100,12 +101,12 @@ void PythonManager::addPythonPath(char *path) {
}
PyEval_CallFunction(append, "(s)", path);
pyThreadState = PyEval_SaveThread();
saveThread();
}
bool PythonManager::startJupyterNotebook()
{
PyEval_RestoreThread(pyThreadState);
restoreThread();
PyObject* startFunc = PyObject_GetAttrString(cutterJupyterModule, "start_jupyter");
if (!startFunc) {
@ -114,14 +115,14 @@ bool PythonManager::startJupyterNotebook()
}
cutterNotebookAppInstance = PyObject_CallObject(startFunc, nullptr);
pyThreadState = PyEval_SaveThread();
saveThread();
return cutterNotebookAppInstance != nullptr;
}
QString PythonManager::getJupyterUrl()
{
PyEval_RestoreThread(pyThreadState);
restoreThread();
auto urlWithToken = PyObject_GetAttrString(cutterNotebookAppInstance, "url_with_token");
auto asciiBytes = PyUnicode_AsASCIIString(urlWithToken);
@ -129,42 +130,39 @@ QString PythonManager::getJupyterUrl()
Py_DECREF(asciiBytes);
Py_DECREF(urlWithToken);
pyThreadState = PyEval_SaveThread();
saveThread();
return urlWithTokenString;
}
CutterPythonPlugin* PythonManager::loadPlugin(char *pluginName) {
CutterPythonPlugin* PythonManager::loadPlugin(const char *pluginName) {
CutterPythonPlugin *plugin = nullptr;
if (!cutterPluginModule) {
return plugin;
}
if (pyThreadState) {
PyEval_RestoreThread(pyThreadState);
}
restoreThread();
PyObject *pluginModule = PyImport_ImportModule(pluginName);
if (!pluginModule) {
qWarning() << "Couldn't import the plugin" << QString(pluginName);
PyErr_PrintEx(10);
} else {
plugin = new CutterPythonPlugin(pluginModule);
//Py_DECREF(pluginModule);
}
plugin = new CutterPythonPlugin(pluginModule);
pyThreadState = PyEval_SaveThread();
saveThread();
return plugin;
}
PyObject *PythonManager::getAttrStringSafe(PyObject *object, const char* attribute)
void PythonManager::restoreThread()
{
PyObject *result = nullptr;
if (pyThreadState) {
PyEval_RestoreThread(pyThreadState);
}
result = PyObject_GetAttrString(object, attribute);
pyThreadState = PyEval_SaveThread();
return result;
}
void PythonManager::saveThread()
{
pyThreadState = PyEval_SaveThread();
}

View File

@ -29,9 +29,11 @@ public:
bool startJupyterNotebook();
QString getJupyterUrl();
CutterPythonPlugin *loadPlugin(char *pluginName);
PyObject *createModule(QString module);
CutterPythonPlugin *loadPlugin(const char *pluginName);
PyObject *getAttrStringSafe(PyObject *object, const char* attribute);
void restoreThread();
void saveThread();
private:
QString customPythonHome;

View File

@ -12,19 +12,57 @@ void CutterPythonPlugin::setupPlugin(CutterCore *core)
{
Q_UNUSED(core)
//PyObject *pInstance = PyObject_GetAttrString(pluginModule, "plugin");
PyObject *pInstance = Python()->getAttrStringSafe(pluginModule, "plugin");
if (!pInstance) {
qWarning() << "Cannot find plugin instance.";
if (!pluginModule) {
qWarning() << "Could not find plugin module.";
return;
}
PyObject *pName = PyObject_GetAttrString(pInstance, "name");
qDebug() << "pname" << pName;
if (pName) {
this->name = QString(PyUnicode_AS_DATA(pName));
qDebug() << "OK COOL" << this->name;
Python()->restoreThread();
PyObject *pInstance = PyObject_GetAttrString(pluginModule, "plugin");
if (!pInstance) {
qWarning() << "Cannot find plugin instance.";
Python()->saveThread();
return;
}
// Check setupPlugin method exists
PyObject *setupPlugin = PyObject_GetAttrString(pInstance, "setupPlugin");
if (!setupPlugin) {
qWarning() << "Cannot find setupPlugin method.";
Py_DECREF(pInstance);
Python()->saveThread();
return;
}
Py_DECREF(setupPlugin);
// Call that method
PyObject *result = PyObject_CallMethod(pInstance, "setupPlugin", nullptr);
if (!result) {
qWarning() << "Error in setupPlugin().";
Py_DECREF(pInstance);
Python()->saveThread();
}
Py_DECREF(result);
this->name = getAttributeFromPython(pInstance, "name");
this->description = getAttributeFromPython(pInstance, "description");
this->version = getAttributeFromPython(pInstance, "version");
this->author = getAttributeFromPython(pInstance, "author");
Py_DECREF(pInstance);
Python()->saveThread();
}
QString CutterPythonPlugin::getAttributeFromPython(PyObject *object, const char *attribute)
{
QString result;
PyObject *pName = PyObject_GetAttrString(object, attribute);
if (pName) {
result = QString(PyUnicode_AsUTF8(pName));
}
Py_DECREF(pName);
return result;
}
CutterDockWidget* CutterPythonPlugin::setupInterface(MainWindow *main, QAction *action)

View File

@ -13,6 +13,7 @@ public:
private:
PyObject *pluginModule;
QString getAttributeFromPython(PyObject *object, const char *attribute);
};
#endif // CUTTERPYTHONPLUGIN_H

View File

@ -0,0 +1,17 @@
import cutter
from cutter_plugin import CutterPlugin
class CutterSamplePlugin(CutterPlugin):
def setupPlugin(self):
self.name = 'SamplePlugin'
self.description = 'A sample plugin written in python.'
self.version = '1.0'
self.author = 'xarkes'
def setupInterface(self, main, action):
print('TODO')
# Instantiate our plugin
plugin = CutterSamplePlugin()

View File

@ -8,10 +8,6 @@ class CutterPlugin(ABC):
core = None
dockable = None
@abstractmethod
def __init__(self):
pass
@abstractmethod
def setupPlugin(self):
pass