Python: Allow installing multiple pip packages in one task

Change-Id: If6cc1373cd38c07b29ac48fa51bf0ed35d6f104b
Reviewed-by: Christian Stenger <christian.stenger@qt.io>
This commit is contained in:
David Schulz
2023-01-24 11:28:28 +01:00
parent 4b73de5580
commit f5c41a7f83
4 changed files with 32 additions and 16 deletions

View File

@@ -35,23 +35,31 @@ PipInstallTask::PipInstallTask(const FilePath &python)
m_watcher.setFuture(m_future.future()); m_watcher.setFuture(m_future.future());
} }
void PipInstallTask::setPackage(const PipPackage &package) void PipInstallTask::addPackage(const PipPackage &package)
{ {
m_package = package; m_packages << package;
}
void PipInstallTask::setPackages(const QList<PipPackage> &packages)
{
m_packages = packages;
} }
void PipInstallTask::run() void PipInstallTask::run()
{ {
if (m_package.packageName.isEmpty()) { if (m_packages.isEmpty()) {
emit finished(false); emit finished(false);
return; return;
} }
const QString taskTitle = Tr::tr("Install %1").arg(m_package.displayName); const QString taskTitle = Tr::tr("Install Python Packages");
Core::ProgressManager::addTask(m_future.future(), taskTitle, pipInstallTaskId); Core::ProgressManager::addTask(m_future.future(), taskTitle, pipInstallTaskId);
QString package = m_package.packageName; QStringList arguments = {"-m", "pip", "install"};
if (!m_package.version.isEmpty()) for (const PipPackage &package : m_packages) {
package += "==" + m_package.version; QString pipPackage = package.packageName;
QStringList arguments = {"-m", "pip", "install", package}; if (!package.version.isEmpty())
pipPackage += "==" + package.version;
arguments << pipPackage;
}
// add --user to global pythons, but skip it for venv pythons // add --user to global pythons, but skip it for venv pythons
if (!QDir(m_python.parentDir().toString()).exists("activate")) if (!QDir(m_python.parentDir().toString()).exists("activate"))
@@ -62,7 +70,7 @@ void PipInstallTask::run()
Core::MessageManager::writeDisrupting( Core::MessageManager::writeDisrupting(
Tr::tr("Running \"%1\" to install %2.") Tr::tr("Running \"%1\" to install %2.")
.arg(m_process.commandLine().toUserOutput(), m_package.displayName)); .arg(m_process.commandLine().toUserOutput(), packagesDisplayName()));
m_killTimer.setSingleShot(true); m_killTimer.setSingleShot(true);
m_killTimer.start(5 /*minutes*/ * 60 * 1000); m_killTimer.start(5 /*minutes*/ * 60 * 1000);
@@ -74,7 +82,7 @@ void PipInstallTask::cancel()
m_process.waitForFinished(); m_process.waitForFinished();
Core::MessageManager::writeFlashing( Core::MessageManager::writeFlashing(
Tr::tr("The %1 installation was canceled by %2.") Tr::tr("The %1 installation was canceled by %2.")
.arg(m_package.displayName, m_killTimer.isActive() ? Tr::tr("user") : Tr::tr("time out"))); .arg(packagesDisplayName(), m_killTimer.isActive() ? Tr::tr("user") : Tr::tr("time out")));
} }
void PipInstallTask::handleDone() void PipInstallTask::handleDone()
@@ -82,8 +90,8 @@ void PipInstallTask::handleDone()
m_future.reportFinished(); m_future.reportFinished();
const bool success = m_process.result() == ProcessResult::FinishedWithSuccess; const bool success = m_process.result() == ProcessResult::FinishedWithSuccess;
if (!success) { if (!success) {
Core::MessageManager::writeFlashing(Tr::tr("Installing the %1 failed with exit code %2") Core::MessageManager::writeFlashing(Tr::tr("Installing %1 failed with exit code %2")
.arg(m_package.displayName).arg(m_process.exitCode())); .arg(packagesDisplayName()).arg(m_process.exitCode()));
} }
emit finished(success); emit finished(success);
} }
@@ -102,6 +110,11 @@ void PipInstallTask::handleError()
Core::MessageManager::writeSilently(stdErr); Core::MessageManager::writeSilently(stdErr);
} }
QString PipInstallTask::packagesDisplayName() const
{
return Utils::transform(m_packages, &PipPackage::displayName).join(", ");
}
void PipPackageInfo::parseField(const QString &field, const QStringList &data) void PipPackageInfo::parseField(const QString &field, const QStringList &data)
{ {
if (field.isEmpty()) if (field.isEmpty())

View File

@@ -66,7 +66,8 @@ class PipInstallTask : public QObject
Q_OBJECT Q_OBJECT
public: public:
explicit PipInstallTask(const Utils::FilePath &python); explicit PipInstallTask(const Utils::FilePath &python);
void setPackage(const PipPackage &package); void addPackage(const PipPackage &package);
void setPackages(const QList<PipPackage> &packages);
void run(); void run();
signals: signals:
@@ -78,8 +79,10 @@ private:
void handleOutput(); void handleOutput();
void handleError(); void handleError();
QString packagesDisplayName() const;
const Utils::FilePath m_python; const Utils::FilePath m_python;
PipPackage m_package; QList<PipPackage> m_packages;
Utils::QtcProcess m_process; Utils::QtcProcess m_process;
QFutureInterface<void> m_future; QFutureInterface<void> m_future;
QFutureWatcher<void> m_watcher; QFutureWatcher<void> m_watcher;

View File

@@ -88,7 +88,7 @@ void PySideInstaller::installPyside(const FilePath &python,
if (success) if (success)
emit pySideInstalled(python, pySide); emit pySideInstalled(python, pySide);
}); });
install->setPackage(PipPackage(pySide)); install->setPackages({PipPackage(pySide)});
install->run(); install->run();
} }

View File

@@ -305,7 +305,7 @@ void PyLSConfigureAssistant::installPythonLanguageServer(const FilePath &python,
install->deleteLater(); install->deleteLater();
}); });
install->setPackage(PipPackage{"python-lsp-server[all]", "Python Language Server"}); install->setPackages({PipPackage{"python-lsp-server[all]", "Python Language Server"}});
install->run(); install->run();
} }