diff options
Diffstat (limited to 'plugins')
-rw-r--r-- | plugins/pythonextensions/bindingheaders/pythonextensions_extension.h | 0 | ||||
-rw-r--r-- | plugins/pythonextensions/pythonextensions.pro | 3 | ||||
-rw-r--r-- | plugins/pythonextensions/pythonextensionsplugin.cpp | 96 | ||||
-rw-r--r-- | plugins/pythonextensions/pythonextensionsplugin.h | 14 | ||||
-rw-r--r-- | plugins/pythonextensions/pyutil.cpp | 11 | ||||
-rw-r--r-- | plugins/pythonextensions/pyutil.h | 4 | ||||
-rw-r--r-- | plugins/pythonextensions/typesystem_qtcreator.xml | 3 |
7 files changed, 84 insertions, 47 deletions
diff --git a/plugins/pythonextensions/bindingheaders/pythonextensions_extension.h b/plugins/pythonextensions/bindingheaders/pythonextensions_extension.h new file mode 100644 index 0000000..e69de29 --- /dev/null +++ b/plugins/pythonextensions/bindingheaders/pythonextensions_extension.h diff --git a/plugins/pythonextensions/pythonextensions.pro b/plugins/pythonextensions/pythonextensions.pro index c8fe73d..334e029 100644 --- a/plugins/pythonextensions/pythonextensions.pro +++ b/plugins/pythonextensions/pythonextensions.pro @@ -24,7 +24,7 @@ include($$IDE_SOURCE_TREE/src/qtcreatorplugin.pri) # Qt Creator Core bindings WRAPPED_HEADER = $$PWD/wrappedclasses.h -WRAPPER_DIR = $$OUT_PWD/PythonExtension/QtCreator +WRAPPER_DIR = $$OUT_PWD/QtCreator TYPESYSTEM_FILE = typesystem_qtcreator.xml TYPESYSTEM_NAME = qtcreator SHIBOKEN_QT = core gui widgets @@ -36,6 +36,7 @@ WRAPPED_CLASSES = \ bindingheaders/pythonextensions.h \ bindingheaders/pythonextensions_internal.h \ bindingheaders/pythonextensions_internal_pythonextensionsplugin.h \ + bindingheaders/pythonextensions_extension.h \ bindingheaders/core.h \ bindingheaders/core_actioncontainer.h \ bindingheaders/core_actionmanager.h \ diff --git a/plugins/pythonextensions/pythonextensionsplugin.cpp b/plugins/pythonextensions/pythonextensionsplugin.cpp index 3547a59..59b32a1 100644 --- a/plugins/pythonextensions/pythonextensionsplugin.cpp +++ b/plugins/pythonextensions/pythonextensionsplugin.cpp @@ -39,6 +39,8 @@ #include <extensionsystem/pluginmanager.h> #include <extensionsystem/pluginspec.h> +#include <utils/algorithm.h> + #include <QDir> #include <QIODevice> #include <QFile> @@ -131,23 +133,39 @@ QDir PythonExtensionsPlugin::extensionDir() return extension_dir; } -QStringList PythonExtensionsPlugin::extensionList(const bool loadedOnly) +static QVector<Extension> getExtensionList(const QDir &directory) { - if (loadedOnly) - return m_loadedExtensions; - - QDir extension_dir = extensionDir(); - if (!extension_dir.exists()) - return QStringList(); + if (!directory.exists()) + return {}; + + QStringList entries = directory.entryList(QDir::AllDirs | QDir::NoDotAndDotDot); + entries.removeAll("site-packages"); + entries.removeAll("__pycache__"); + const QVector<Extension> packageExtensions + = Utils::transform<QVector>(entries, [](const QString &entry) { + return Extension({entry, false}); + }); + const QStringList fileEntries = directory.entryList({"*.py"}, QDir::Files); + const QVector<Extension> fileExtensions + = Utils::transform<QVector>(fileEntries, [](const QString &entry) { + return Extension({entry.left(entry.size() - 3), false}); + }); + return packageExtensions + fileExtensions; +} - QStringList extension_list = extension_dir.entryList(QDir::AllDirs | QDir::NoDotAndDotDot); - extension_list.removeOne("site-packages"); - return extension_list; +QVector<Extension> PythonExtensionsPlugin::extensionList() +{ + return extensionListRef(); } -void PythonExtensionsPlugin::flagAsLoaded(const QString &extension) +QVector<Extension> &PythonExtensionsPlugin::extensionListRef() { - m_loadedExtensions << extension; + static bool initialized = false; + if (!initialized) { + m_extensions = getExtensionList(extensionDir()); + initialized = true; + } + return m_extensions; } QString PythonExtensionsPlugin::pythonPackagePath() @@ -162,18 +180,21 @@ QString PythonExtensionsPlugin::pythonPackagePath() void PythonExtensionsPlugin::initializePythonBindings() { // Add our custom module directory - if (extensionDir().exists()) { + if (extensionDir().exists()) PyUtil::addToSysPath(extensionDir().path().toStdString()); - PyUtil::addToSysPath(pythonPackagePath().toStdString()); - } + // Add directory for local python packages that are installed as requirements of extensions + // Need to create it first if it doesn't exist, otherwise python will ignore the path + if (!QFile::exists(pythonPackagePath())) + QDir().mkpath(pythonPackagePath()); + PyUtil::addToSysPath(pythonPackagePath().toStdString()); // Initialize the Python context and register global Qt Creator variable - if (!PyUtil::bindShibokenModuleObject("PythonExtension", "QtCreator")) { + if (!PyUtil::bindCoreModules()) { qWarning() << "Python bindings could not be initialized"; Core::MessageManager::write(Constants::MESSAGE_MANAGER_PREFIX + tr("Python bindings could not be initialized")); return; } // Bind the plugin instance - PyUtil::bindObject("PythonExtension", "PluginInstance", PyUtil::PythonExtensionsPluginType, this); + PyUtil::bindObject("QtCreator", "PythonExtensions", PyUtil::PythonExtensionsPluginType, this); } void PythonExtensionsPlugin::initializeOptionalBindings() @@ -208,16 +229,18 @@ void PythonExtensionsPlugin::installRequirements() if (!extension_dir.exists()) return; - QStringList extension_list = extensionList(); - for (const QString &extension : extension_list) { - QString extension_requirements(extension_dir.absolutePath() + "/" + extension + "/requirements.txt"); - if (QFileInfo::exists(extension_requirements) && !QFileInfo::exists(extension_requirements + ".installed")) { - if (!PyUtil::pipInstallRequirements( - extension_requirements.toStdString(), - pythonPackagePath().toStdString() - )) { - qWarning() << "Failed to install requirements for extension" << extension; - Core::MessageManager::write(Constants::MESSAGE_MANAGER_PREFIX + tr("Failed to install requirements for extension ") + extension); + QVector<Extension> extension_list = extensionListRef(); + for (const Extension &extension : extension_list) { + QString extension_requirements(extension_dir.absolutePath() + "/" + extension.name + + "/requirements.txt"); + if (QFileInfo::exists(extension_requirements) + && !QFileInfo::exists(extension_requirements + ".installed")) { + if (!PyUtil::pipInstallRequirements(extension_requirements.toStdString(), + pythonPackagePath().toStdString())) { + qWarning() << "Failed to install requirements for extension" << extension.name; + Core::MessageManager::write(Constants::MESSAGE_MANAGER_PREFIX + + tr("Failed to install requirements for extension ") + + extension.name); } } } @@ -235,22 +258,25 @@ void PythonExtensionsPlugin::initializePythonExtensions() qDebug() << "Found Python extension directory at location" << extension_dir.absolutePath(); - QStringList extension_list = extensionList(); + QVector<Extension> &extension_list = extensionListRef(); qDebug() << "Number of Python extensions found:" << extension_list.size(); + int loadedCount = 0; // Run the extension initialization code - for (const QString &extension : extension_list) { - qDebug() << "Trying to initialize extension" << extension; - if (!PyUtil::runScript("import " + extension.toStdString())) { - qWarning() << "Failed to initialize extension" << extension; - Core::MessageManager::write(Constants::MESSAGE_MANAGER_PREFIX + tr("Failed to initialize extension ") + extension); + for (Extension &extension : extension_list) { + qDebug() << "Trying to initialize extension" << extension.name; + if (PyUtil::runScript("import " + extension.name.toStdString())) { + extension.loaded = true; + ++loadedCount; } else { - m_loadedExtensions << extension; + qWarning() << "Failed to initialize extension" << extension.name; + Core::MessageManager::write(Constants::MESSAGE_MANAGER_PREFIX + + tr("Failed to initialize extension ") + extension.name); } } - qDebug() << "Number of Python extensions loaded:" << m_loadedExtensions.size(); + qDebug() << "Number of Python extensions loaded:" << loadedCount; } } // namespace Internal diff --git a/plugins/pythonextensions/pythonextensionsplugin.h b/plugins/pythonextensions/pythonextensionsplugin.h index 29010d4..1a4bce3 100644 --- a/plugins/pythonextensions/pythonextensionsplugin.h +++ b/plugins/pythonextensions/pythonextensionsplugin.h @@ -33,6 +33,13 @@ #include <QStringList> namespace PythonExtensions { + +class Extension { +public: + QString name; + bool loaded; +}; + namespace Internal { class PythonExtensionsPlugin : public ExtensionSystem::IPlugin @@ -50,15 +57,16 @@ public: ShutdownFlag aboutToShutdown() final; QDir extensionDir(); - QStringList extensionList(const bool loadedOnly = false); - void flagAsLoaded(const QString &extension); + QVector<Extension> extensionList(); QString pythonPackagePath(); + private: - QStringList m_loadedExtensions; void initializePythonBindings(); void initializeOptionalBindings(); void installRequirements(); void initializePythonExtensions(); + QVector<Extension> &extensionListRef(); + QVector<Extension> m_extensions; }; // Util functions diff --git a/plugins/pythonextensions/pyutil.cpp b/plugins/pythonextensions/pyutil.cpp index b563c55..b992e36 100644 --- a/plugins/pythonextensions/pyutil.cpp +++ b/plugins/pythonextensions/pyutil.cpp @@ -56,10 +56,10 @@ extern "C" void initQtCreator(); // These variables store all Python types exported by QtCreators bindings, // as well as the types exported for QtWidgets. -extern PyTypeObject **SbkPythonExtension_QtCreatorTypes; +extern PyTypeObject **SbkQtCreatorTypes; // This variable stores the Python module generated by Shiboken -extern PyObject *SbkPythonExtension_QtCreatorModuleObject; +extern PyObject *SbkQtCreatorModuleObject; namespace PyUtil { @@ -157,7 +157,7 @@ bool bindObject(const QString &moduleName, const QString &name, int index, void return false; // Generate the type - PyTypeObject *typeObject = SbkPythonExtension_QtCreatorTypes[index]; + PyTypeObject *typeObject = SbkQtCreatorTypes[index]; PyObject *po = Shiboken::Conversions::pointerToPython(reinterpret_cast<SbkObjectType *>(typeObject), o); if (!po) { @@ -169,9 +169,10 @@ bool bindObject(const QString &moduleName, const QString &name, int index, void return bindPyObject(moduleName, name, po); } -bool bindShibokenModuleObject(const QString &moduleName, const QString &name) +bool bindCoreModules() { - return bindPyObject(moduleName, name, SbkPythonExtension_QtCreatorModuleObject); + return bindSubPyObject("QtCreator", "Utils", SbkQtCreatorModuleObject) + && bindSubPyObject("QtCreator", "Core", SbkQtCreatorModuleObject); } bool bindPyObject(const QString &moduleName, const QString &name, void *obj) diff --git a/plugins/pythonextensions/pyutil.h b/plugins/pythonextensions/pyutil.h index 62a1622..ca58f6e 100644 --- a/plugins/pythonextensions/pyutil.h +++ b/plugins/pythonextensions/pyutil.h @@ -37,7 +37,7 @@ namespace PyUtil { // Note: If modifying the bindings, check these types still align enum QtCreatorTypes { - PythonExtensionsPluginType = 33, // SBK_PYTHONEXTENSIONS_INTERNAL_PYTHONEXTENSIONSPLUGIN_IDX + PythonExtensionsPluginType = 34, // SBK_PYTHONEXTENSIONS_INTERNAL_PYTHONEXTENSIONSPLUGIN_IDX }; enum State @@ -53,7 +53,7 @@ PYTHONEXTENSIONSSHARED_EXPORT bool createModule(const std::string &moduleName); bool bindObject(const QString &moduleName, const QString &name, int index, void *o); -bool bindShibokenModuleObject(const QString &moduleName, const QString &name); +bool bindCoreModules(); PYTHONEXTENSIONSSHARED_EXPORT bool bindPyObject(const QString &moduleName, const QString &name, void *obj); diff --git a/plugins/pythonextensions/typesystem_qtcreator.xml b/plugins/pythonextensions/typesystem_qtcreator.xml index 736fe44..69f051e 100644 --- a/plugins/pythonextensions/typesystem_qtcreator.xml +++ b/plugins/pythonextensions/typesystem_qtcreator.xml @@ -41,12 +41,13 @@ --> <!-- Typesystem for Qt Creator Python host plugin --> -<typesystem package="PythonExtension.QtCreator"> +<typesystem package="QtCreator"> <!-- Load PySide QtWidgets typesystem (is this correct? yup) --> <load-typesystem name="typesystem_widgets.xml" generate="no"/> <namespace-type name="PythonExtensions"> + <value-type name="Extension"/> <namespace-type name="Internal"> <object-type name="PythonExtensionsPlugin"/> </namespace-type> |