forked from qt-creator/qt-creator
Python: detect pythons async
Change-Id: I74484a4f2c33c4fd7754f87bfbf3b9d711542741 Reviewed-by: Christian Stenger <christian.stenger@qt.io>
This commit is contained in:
@@ -21,13 +21,14 @@
|
||||
#include <texteditor/texteditor.h>
|
||||
|
||||
#include <utils/algorithm.h>
|
||||
#include <utils/qtcassert.h>
|
||||
#include <utils/async.h>
|
||||
#include <utils/detailswidget.h>
|
||||
#include <utils/environment.h>
|
||||
#include <utils/listmodel.h>
|
||||
#include <utils/layoutbuilder.h>
|
||||
#include <utils/listmodel.h>
|
||||
#include <utils/pathchooser.h>
|
||||
#include <utils/process.h>
|
||||
#include <utils/qtcassert.h>
|
||||
#include <utils/treemodel.h>
|
||||
#include <utils/utilsicons.h>
|
||||
|
||||
@@ -366,14 +367,6 @@ private:
|
||||
InterpreterOptionsWidget *m_widget = nullptr;
|
||||
};
|
||||
|
||||
static bool alreadyRegistered(const QList<Interpreter> &pythons, const FilePath &pythonExecutable)
|
||||
{
|
||||
return Utils::anyOf(pythons, [pythonExecutable](const Interpreter &interpreter) {
|
||||
return interpreter.command.toFileInfo().canonicalFilePath()
|
||||
== pythonExecutable.toFileInfo().canonicalFilePath();
|
||||
});
|
||||
}
|
||||
|
||||
static InterpreterOptionsPage &interpreterOptionsPage()
|
||||
{
|
||||
static InterpreterOptionsPage page;
|
||||
@@ -626,8 +619,9 @@ static void disableOutdatedPyls()
|
||||
}
|
||||
}
|
||||
|
||||
static void addPythonsFromRegistry(QList<Interpreter> &pythons)
|
||||
static QList<Interpreter> pythonsFromRegistry()
|
||||
{
|
||||
QList<Interpreter> pythons;
|
||||
QSettings pythonRegistry("HKEY_LOCAL_MACHINE\\SOFTWARE\\Python\\PythonCore",
|
||||
QSettings::NativeFormat);
|
||||
for (const QString &versionGroup : pythonRegistry.childGroups()) {
|
||||
@@ -636,7 +630,7 @@ static void addPythonsFromRegistry(QList<Interpreter> &pythons)
|
||||
QVariant regVal = pythonRegistry.value("InstallPath/ExecutablePath");
|
||||
if (regVal.isValid()) {
|
||||
const FilePath &executable = FilePath::fromUserInput(regVal.toString());
|
||||
if (executable.exists() && !alreadyRegistered(pythons, executable)) {
|
||||
if (executable.exists()) {
|
||||
pythons << Interpreter{QUuid::createUuid().toString(),
|
||||
name,
|
||||
FilePath::fromUserInput(regVal.toString())};
|
||||
@@ -645,7 +639,7 @@ static void addPythonsFromRegistry(QList<Interpreter> &pythons)
|
||||
regVal = pythonRegistry.value("InstallPath/WindowedExecutablePath");
|
||||
if (regVal.isValid()) {
|
||||
const FilePath &executable = FilePath::fromUserInput(regVal.toString());
|
||||
if (executable.exists() && !alreadyRegistered(pythons, executable)) {
|
||||
if (executable.exists()) {
|
||||
pythons << Interpreter{QUuid::createUuid().toString(),
|
||||
//: <python display name> (Windowed)
|
||||
Tr::tr("%1 (Windowed)").arg(name),
|
||||
@@ -656,28 +650,30 @@ static void addPythonsFromRegistry(QList<Interpreter> &pythons)
|
||||
if (regVal.isValid()) {
|
||||
const FilePath &path = FilePath::fromUserInput(regVal.toString());
|
||||
const FilePath python = path.pathAppended("python").withExecutableSuffix();
|
||||
if (python.exists() && !alreadyRegistered(pythons, python))
|
||||
if (python.exists())
|
||||
pythons << createInterpreter(python, "Python " + versionGroup);
|
||||
const FilePath pythonw = path.pathAppended("pythonw").withExecutableSuffix();
|
||||
if (pythonw.exists() && !alreadyRegistered(pythons, pythonw))
|
||||
if (pythonw.exists())
|
||||
pythons << createInterpreter(pythonw, "Python " + versionGroup, "(Windowed)");
|
||||
}
|
||||
pythonRegistry.endGroup();
|
||||
}
|
||||
return pythons;
|
||||
}
|
||||
|
||||
static void addPythonsFromPath(QList<Interpreter> &pythons)
|
||||
static QList<Interpreter> pythonsFromPath()
|
||||
{
|
||||
QList<Interpreter> pythons;
|
||||
if (HostOsInfo::isWindowsHost()) {
|
||||
for (const FilePath &executable : FilePath("python").searchAllInPath()) {
|
||||
// Windows creates empty redirector files that may interfere
|
||||
if (executable.toFileInfo().size() == 0)
|
||||
continue;
|
||||
if (executable.exists() && !alreadyRegistered(pythons, executable))
|
||||
if (executable.exists())
|
||||
pythons << createInterpreter(executable, "Python from Path");
|
||||
}
|
||||
for (const FilePath &executable : FilePath("pythonw").searchAllInPath()) {
|
||||
if (executable.exists() && !alreadyRegistered(pythons, executable))
|
||||
if (executable.exists())
|
||||
pythons << createInterpreter(executable, "Python from Path", "(Windowed)");
|
||||
}
|
||||
} else {
|
||||
@@ -690,11 +686,12 @@ static void addPythonsFromPath(QList<Interpreter> &pythons)
|
||||
const QDir dir(path.toString());
|
||||
for (const QFileInfo &fi : dir.entryInfoList(filters)) {
|
||||
const FilePath executable = Utils::FilePath::fromFileInfo(fi);
|
||||
if (executable.exists() && !alreadyRegistered(pythons, executable))
|
||||
if (executable.exists())
|
||||
pythons << createInterpreter(executable, "Python from Path");
|
||||
}
|
||||
}
|
||||
}
|
||||
return pythons;
|
||||
}
|
||||
|
||||
static QString idForPythonFromPath(const QList<Interpreter> &pythons)
|
||||
@@ -713,6 +710,51 @@ static QString idForPythonFromPath(const QList<Interpreter> &pythons)
|
||||
|
||||
static PythonSettings *settingsInstance = nullptr;
|
||||
|
||||
static bool alreadyRegistered(const Interpreter &candidate)
|
||||
{
|
||||
return Utils::anyOf(settingsInstance->interpreters(),
|
||||
[candidate = candidate.command](const Interpreter &interpreter) {
|
||||
return interpreter.command.isSameDevice(candidate)
|
||||
&& interpreter.command.resolveSymlinks()
|
||||
== candidate.resolveSymlinks();
|
||||
});
|
||||
}
|
||||
|
||||
static void scanPath()
|
||||
{
|
||||
auto watcher = new QFutureWatcher<QList<Interpreter>>();
|
||||
QObject::connect(watcher, &QFutureWatcher<QList<Interpreter>>::finished, [watcher]() {
|
||||
for (const Interpreter &interpreter : watcher->result()) {
|
||||
if (!alreadyRegistered(interpreter))
|
||||
settingsInstance->addInterpreter(interpreter);
|
||||
}
|
||||
watcher->deleteLater();
|
||||
});
|
||||
watcher->setFuture(Utils::asyncRun(pythonsFromPath));
|
||||
}
|
||||
|
||||
static void scanRegistry()
|
||||
{
|
||||
auto watcher = new QFutureWatcher<QList<Interpreter>>();
|
||||
QObject::connect(watcher, &QFutureWatcher<QList<Interpreter>>::finished, [watcher]() {
|
||||
for (const Interpreter &interpreter : watcher->result()) {
|
||||
if (!alreadyRegistered(interpreter))
|
||||
settingsInstance->addInterpreter(interpreter);
|
||||
}
|
||||
watcher->deleteLater();
|
||||
scanPath();
|
||||
});
|
||||
watcher->setFuture(Utils::asyncRun(pythonsFromRegistry));
|
||||
}
|
||||
|
||||
static void scanSystemForInterpreters()
|
||||
{
|
||||
if (Utils::HostOsInfo::isWindowsHost())
|
||||
scanRegistry();
|
||||
else
|
||||
scanPath();
|
||||
}
|
||||
|
||||
PythonSettings::PythonSettings()
|
||||
{
|
||||
QTC_ASSERT(!settingsInstance, return);
|
||||
@@ -723,9 +765,7 @@ PythonSettings::PythonSettings()
|
||||
|
||||
initFromSettings(Core::ICore::settings());
|
||||
|
||||
if (HostOsInfo::isWindowsHost())
|
||||
addPythonsFromRegistry(m_interpreters);
|
||||
addPythonsFromPath(m_interpreters);
|
||||
scanSystemForInterpreters();
|
||||
|
||||
if (m_defaultInterpreterId.isEmpty())
|
||||
m_defaultInterpreterId = idForPythonFromPath(m_interpreters);
|
||||
|
||||
Reference in New Issue
Block a user