diff options
author | Eike Ziller <eike.ziller@qt.io> | 2018-09-21 13:15:47 +0200 |
---|---|---|
committer | Eike Ziller <eike.ziller@qt.io> | 2018-09-21 11:54:38 +0000 |
commit | 9ebe20ca27fbce2ca2934e40dfd1a7a21aaa6658 (patch) | |
tree | 03effab1e69b9213210ee63c7ad32c37418b42ab | |
parent | 4d6487e753b8838f460769ff9758ac6c82a88a35 (diff) |
Avoid scanning extension directory over and over again
And get rid of separate management of a list of loaded extensions.
Instead save the name and state of an extension in a separate class.
It will probably get more information about the extension, like its
location. The extension manager UI now can also iterate over that list
once.
Change-Id: I4872e55d621837a7d476e69b919f06aeb491ff03
Reviewed-by: Eike Ziller <eike.ziller@qt.io>
-rw-r--r-- | docs/extensions.md | 5 | ||||
-rw-r--r-- | plugins/pythonextensions/bindingheaders/pythonextensions_extension.h | 0 | ||||
-rw-r--r-- | plugins/pythonextensions/pythonextensions.pro | 1 | ||||
-rw-r--r-- | plugins/pythonextensions/pythonextensionsplugin.cpp | 76 | ||||
-rw-r--r-- | plugins/pythonextensions/pythonextensionsplugin.h | 13 | ||||
-rw-r--r-- | plugins/pythonextensions/pyutil.h | 2 | ||||
-rw-r--r-- | plugins/pythonextensions/typesystem_qtcreator.xml | 1 | ||||
-rw-r--r-- | python/extensionmanager/actions.py | 4 | ||||
-rw-r--r-- | python/extensionmanager/list.py | 6 |
9 files changed, 69 insertions, 39 deletions
diff --git a/docs/extensions.md b/docs/extensions.md index ae5cb5c..709acff 100644 --- a/docs/extensions.md +++ b/docs/extensions.md @@ -21,9 +21,8 @@ from PythonExtension import PluginInstance as inst inst.extensionDir() # Returns a list with the names of all Python extensions -# If loaded only is supplied as True, only extensions that -# where loaded successfully are returned -inst.extensionList(loadedOnly = False) +# Each extension has properties 'name' and 'loaded' +inst.extensionList() # Returns the path of the custom location to # where missing dependencies should be pip installed 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..e28b860 100644 --- a/plugins/pythonextensions/pythonextensions.pro +++ b/plugins/pythonextensions/pythonextensions.pro @@ -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 3136bbc..b3730b4 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,19 +133,32 @@ QDir PythonExtensionsPlugin::extensionDir() return extension_dir; } -QStringList PythonExtensionsPlugin::extensionList(const bool loadedOnly) +static QVector<Extension> getExtensionList(const QDir &directory) { - if (loadedOnly) - return m_loadedExtensions; + if (!directory.exists()) + return {}; + + QStringList entries = directory.entryList(QDir::AllDirs | QDir::NoDotAndDotDot); + entries.removeAll("site-packages"); + entries.removeAll("__pycache__"); + return Utils::transform<QVector>(entries, [](const QString &entry) { + return Extension({entry, false}); + }); +} - QDir extension_dir = extensionDir(); - if (!extension_dir.exists()) - return QStringList(); +QVector<Extension> PythonExtensionsPlugin::extensionList() +{ + return extensionListRef(); +} - QStringList extension_list = extension_dir.entryList(QDir::AllDirs | QDir::NoDotAndDotDot); - extension_list.removeAll("site-packages"); - extension_list.removeAll("__pycache__"); - return extension_list; +QVector<Extension> &PythonExtensionsPlugin::extensionListRef() +{ + static bool initialized = false; + if (!initialized) { + m_extensions = getExtensionList(extensionDir()); + initialized = true; + } + return m_extensions; } QString PythonExtensionsPlugin::pythonPackagePath() @@ -207,16 +222,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); } } } @@ -234,22 +251,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 106ee63..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,14 +57,16 @@ public: ShutdownFlag aboutToShutdown() final; QDir extensionDir(); - QStringList extensionList(const bool loadedOnly = false); + 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.h b/plugins/pythonextensions/pyutil.h index 62a1622..23fdb37 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 diff --git a/plugins/pythonextensions/typesystem_qtcreator.xml b/plugins/pythonextensions/typesystem_qtcreator.xml index 736fe44..49dd794 100644 --- a/plugins/pythonextensions/typesystem_qtcreator.xml +++ b/plugins/pythonextensions/typesystem_qtcreator.xml @@ -47,6 +47,7 @@ <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> diff --git a/python/extensionmanager/actions.py b/python/extensionmanager/actions.py index 29d64cc..7f05e77 100644 --- a/python/extensionmanager/actions.py +++ b/python/extensionmanager/actions.py @@ -60,8 +60,8 @@ def install(path): # Make sure the extension manager does not overwrite # extensions that are already installed for ext in instance.extensionList(): - if extName == ext: - return "The extension \"{}\" is already installed. Uninstall it before trying again.".format(ext) + if extName == ext.name: + return "The extension \"{}\" is already installed. Uninstall it before trying again.".format(extName) extZip.extractall(instance.extensionDir().absolutePath()) extZip.close() except Exception as e: diff --git a/python/extensionmanager/list.py b/python/extensionmanager/list.py index d213c35..32002b1 100644 --- a/python/extensionmanager/list.py +++ b/python/extensionmanager/list.py @@ -58,11 +58,11 @@ class ExtensionList(QtWidgets.QListWidget): i = 0 for ext in instance.extensionList(): item = QtWidgets.QListWidgetItem(self) - if not ext in instance.extensionList(True): - item.setText(ext + " [did not load]") + if not ext.loaded: + item.setText(ext.name + " [did not load]") item.setIcon(QtGui.QIcon.fromTheme("dialog-error")) else: - item.setText(ext) + item.setText(ext.name) item.setIcon(QtGui.QIcon.fromTheme("applications-development")) if i % 2 == 1: item.setBackground(QtGui.QBrush(QtGui.QColor.fromRgb(240, 240, 240))) |