Python: show warnings if pip or venv is missing

Change-Id: Ib38c1eb3b0f31d6988d3a5f084ac6eda08ec0619
Reviewed-by: Qt CI Bot <qt_ci_bot@qt-project.org>
Reviewed-by: Christian Stenger <christian.stenger@qt.io>
This commit is contained in:
David Schulz
2023-11-22 11:09:41 +01:00
parent 67b7835c25
commit f4bf7c5b00
4 changed files with 51 additions and 13 deletions

View File

@@ -391,7 +391,7 @@ PythonBuildConfigurationFactory::PythonBuildConfigurationFactory()
base.typeName = Tr::tr("Global Python"); base.typeName = Tr::tr("Global Python");
base.showBuildDirConfigWidget = false; base.showBuildDirConfigWidget = false;
if (isVenvPython(python->command)) if (isVenvPython(python->command) || !venvIsUsable(python->command))
return QList<BuildInfo>{base}; return QList<BuildInfo>{base};
base.enabledByDefault = false; base.enabledByDefault = false;

View File

@@ -6,11 +6,13 @@
#include "pythonconstants.h" #include "pythonconstants.h"
#include "pythonsettings.h" #include "pythonsettings.h"
#include "pythontr.h" #include "pythontr.h"
#include "pythonutils.h"
#include <projectexplorer/kitmanager.h> #include <projectexplorer/kitmanager.h>
#include <utils/guard.h> #include <utils/guard.h>
#include <utils/layoutbuilder.h> #include <utils/layoutbuilder.h>
#include <utils/process.h>
#include <QComboBox> #include <QComboBox>
@@ -90,23 +92,41 @@ public:
Tasks validate(const Kit *k) const override Tasks validate(const Kit *k) const override
{ {
Tasks result;
const std::optional<Interpreter> python = PythonKitAspect::python(k); const std::optional<Interpreter> python = PythonKitAspect::python(k);
if (!python) if (!python)
return {}; return result;
const FilePath path = python->command; const FilePath path = python->command;
if (path.needsDevice()) if (path.needsDevice())
return {}; return result;
if (path.isEmpty()) if (path.isEmpty()) {
return {BuildSystemTask(Task::Error, Tr::tr("No Python setup."))}; result << BuildSystemTask(Task::Error, Tr::tr("No Python setup."));
if (!path.exists()) { } else if (!path.exists()) {
return {BuildSystemTask(Task::Error, result << BuildSystemTask(Task::Error,
Tr::tr("Python %1 not found.").arg(path.toUserOutput()))}; Tr::tr("Python %1 not found.").arg(path.toUserOutput()));
} else if (!path.isExecutableFile()) {
result << BuildSystemTask(Task::Error,
Tr::tr("Python %1 not executable.").arg(path.toUserOutput()));
} else {
if (!pipIsUsable(path)) {
result << BuildSystemTask(
Task::Warning,
Tr::tr("Python %1 does not contain a usable pip. Pip is used to install python "
"packages from the Python Package Index, like PySide and the python "
"language server. If you want to use any of that functionality "
"ensure pip is installed for that python.")
.arg(path.toUserOutput()));
} }
if (!path.isExecutableFile()) { if (!venvIsUsable(path)) {
return {BuildSystemTask{Task::Error, result << BuildSystemTask(
Tr::tr("Python %1 not executable.").arg(path.toUserOutput())}}; Task::Warning,
Tr::tr("Python %1 does not contain a usable venv. venv is the recommended way "
"to isolate a development environment for a project from the globally "
"installed python.")
.arg(path.toUserOutput()));
} }
return {}; }
return result;
} }
ItemList toUserOutput(const Kit *k) const override ItemList toUserOutput(const Kit *k) const override

View File

@@ -192,4 +192,20 @@ bool isVenvPython(const Utils::FilePath &python)
return python.parentDir().parentDir().contains("pyvenv.cfg"); return python.parentDir().parentDir().contains("pyvenv.cfg");
} }
bool venvIsUsable(const Utils::FilePath &python)
{
Process process;
process.setCommand({python, QStringList{"-m", "venv", "-h"}});
process.runBlocking();
return process.result() == ProcessResult::FinishedWithSuccess;
}
bool pipIsUsable(const Utils::FilePath &python)
{
Process process;
process.setCommand({python, QStringList{"-m", "pip", "-V"}});
process.runBlocking();
return process.result() == ProcessResult::FinishedWithSuccess;
}
} // Python::Internal } // Python::Internal

View File

@@ -21,5 +21,7 @@ void createVenv(const Utils::FilePath &python,
const std::function<void(bool)> &callback); const std::function<void(bool)> &callback);
bool isVenvPython(const Utils::FilePath &python); bool isVenvPython(const Utils::FilePath &python);
bool venvIsUsable(const Utils::FilePath &python);
bool pipIsUsable(const Utils::FilePath &python);
} // Python::Internal } // Python::Internal