Python: collect pip package info in another thread

Change-Id: I70a9066fddf812ce9bde5467913bb2bad98e2d0e
Reviewed-by: Christian Stenger <christian.stenger@qt.io>
This commit is contained in:
David Schulz
2023-01-25 12:29:08 +01:00
parent b05a34b81e
commit 471e67d1a6
4 changed files with 164 additions and 78 deletions

View File

@@ -3,6 +3,7 @@
#include "pipsupport.h"
#include "pythonplugin.h"
#include "pythontr.h"
#include <coreplugin/messagemanager.h>
@@ -15,6 +16,7 @@
#include <utils/algorithm.h>
#include <utils/mimeutils.h>
#include <utils/qtcprocess.h>
#include <utils/runextensions.h>
using namespace Utils;
@@ -100,36 +102,6 @@ void PipInstallTask::handleError()
Core::MessageManager::writeSilently(stdErr);
}
PipPackageInfo PipPackage::info(const FilePath &python) const
{
PipPackageInfo result;
QtcProcess pip;
pip.setCommand(CommandLine(python, {"-m", "pip", "show", "-f", packageName}));
pip.runBlocking();
QString fieldName;
QStringList data;
const QString pipOutput = pip.allOutput();
for (const QString &line : pipOutput.split('\n')) {
if (line.isEmpty())
continue;
if (line.front().isSpace()) {
data.append(line.trimmed());
} else {
result.parseField(fieldName, data);
if (auto colonPos = line.indexOf(':'); colonPos >= 0) {
fieldName = line.left(colonPos);
data = QStringList(line.mid(colonPos + 1).trimmed());
} else {
fieldName.clear();
data.clear();
}
}
}
result.parseField(fieldName, data);
return result;
}
void PipPackageInfo::parseField(const QString &field, const QStringList &data)
{
if (field.isEmpty())
@@ -162,4 +134,55 @@ void PipPackageInfo::parseField(const QString &field, const QStringList &data)
}
}
Pip *Pip::instance(const FilePath &python)
{
static QMap<FilePath, Pip *> pips;
auto it = pips.find(python);
if (it == pips.end())
it = pips.insert(python, new Pip(python));
return it.value();
}
QFuture<PipPackageInfo> Pip::info(const PipPackage &package)
{
return Utils::runAsync(&Pip::infoImpl, this, package);
}
PipPackageInfo Pip::infoImpl(const PipPackage &package)
{
PipPackageInfo result;
QtcProcess pip;
pip.setCommand(CommandLine(m_python, {"-m", "pip", "show", "-f", package.packageName}));
m_lock.lock();
pip.runBlocking();
m_lock.unlock();
QString fieldName;
QStringList data;
const QString pipOutput = pip.allOutput();
for (const QString &line : pipOutput.split('\n')) {
if (line.isEmpty())
continue;
if (line.front().isSpace()) {
data.append(line.trimmed());
} else {
result.parseField(fieldName, data);
if (auto colonPos = line.indexOf(':'); colonPos >= 0) {
fieldName = line.left(colonPos);
data = QStringList(line.mid(colonPos + 1).trimmed());
} else {
fieldName.clear();
data.clear();
}
}
}
result.parseField(fieldName, data);
return result;
}
Pip::Pip(const Utils::FilePath &python)
: QObject(PythonPlugin::instance())
, m_python(python)
{}
} // Python::Internal