diff --git a/src/plugins/python/pythonsettings.cpp b/src/plugins/python/pythonsettings.cpp index e9fbff36b10..bc6eebc7885 100644 --- a/src/plugins/python/pythonsettings.cpp +++ b/src/plugins/python/pythonsettings.cpp @@ -855,11 +855,18 @@ QString PythonSettings::pylsConfiguration() return settingsInstance->m_pylsConfiguration; } +static void cacheVenvAndPipUsability(const Interpreter &interpreter) +{ + Utils::asyncRun(&venvIsUsable, interpreter.command); + Utils::asyncRun(&pipIsUsable, interpreter.command); +} + void PythonSettings::addInterpreter(const Interpreter &interpreter, bool isDefault) { if (Utils::anyOf(settingsInstance->m_interpreters, Utils::equal(&Interpreter::id, interpreter.id))) return; settingsInstance->m_interpreters.append(interpreter); + cacheVenvAndPipUsability(interpreter); if (isDefault) settingsInstance->m_defaultInterpreterId = interpreter.id; saveSettings(); @@ -1026,8 +1033,12 @@ void PythonSettings::initFromSettings(QtcSettings *settings) const auto [valid, outdatedInterpreters] = Utils::partition(m_interpreters, keepInterpreter); m_interpreters = valid; - if (!settings->value(kitsGeneratedKey, false).toBool()) { - for (const Interpreter &interpreter : m_interpreters) { + const bool kitsGenerated = settings->value(kitsGeneratedKey, false).toBool(); + if (kitsGenerated) + fixupPythonKits(); + for (const Interpreter &interpreter : std::as_const(m_interpreters)) { + cacheVenvAndPipUsability(interpreter); + if (!kitsGenerated) { if (interpreter.autoDetected) { const FilePath &cmd = interpreter.command; if (!cmd.isLocal() || cmd.parentDir().pathAppended("activate").exists()) @@ -1035,8 +1046,6 @@ void PythonSettings::initFromSettings(QtcSettings *settings) } addKitsForInterpreter(interpreter, false); } - } else { - fixupPythonKits(); } for (const Interpreter &outdated : outdatedInterpreters) diff --git a/src/plugins/python/pythonutils.cpp b/src/plugins/python/pythonutils.cpp index 04144a3e41b..efcfc4940a5 100644 --- a/src/plugins/python/pythonutils.cpp +++ b/src/plugins/python/pythonutils.cpp @@ -20,6 +20,7 @@ #include #include #include +#include #include @@ -192,31 +193,37 @@ bool isVenvPython(const FilePath &python) return python.parentDir().parentDir().pathAppended("pyvenv.cfg").exists(); } -static bool isUsableHelper(QHash *cache, const QString &keyString, - const QString &commandArg, const FilePath &python) +static bool isUsableHelper( + SynchronizedValue> *cache, + const QString &commandArg, + const FilePath &python) { - auto it = cache->find(python); - if (it == cache->end()) { - const Key key = keyFromString(keyString); - Process process; - process.setCommand({python, {"-m", commandArg, "-h"}}); - process.runBlocking(); - const bool usable = process.result() == ProcessResult::FinishedWithSuccess; - it = cache->insert(python, usable); - } - return *it; + std::optional result; + cache->read([&result, python](const QHash &cache) { + if (auto it = cache.find(python); it != cache.end()) + result = it.value(); + }); + if (result) + return *result; + + Process process; + process.setCommand({python, {"-m", commandArg, "-h"}}); + process.runBlocking(); + const bool usable = process.result() == ProcessResult::FinishedWithSuccess; + cache->writeLocked()->insert(python, usable); + return usable; } bool venvIsUsable(const FilePath &python) { - static QHash cache; - return isUsableHelper(&cache, "pyVenvIsUsable", "venv", python); + static SynchronizedValue> cache; + return isUsableHelper(&cache, "venv", python); } bool pipIsUsable(const FilePath &python) { - static QHash cache; - return isUsableHelper(&cache, "pyPipIsUsable", "pip", python); + static SynchronizedValue> cache; + return isUsableHelper(&cache, "pip", python); } QString pythonVersion(const FilePath &python)