forked from qt-creator/qt-creator
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:
@@ -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;
|
||||||
|
|||||||
@@ -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
|
||||||
|
|||||||
@@ -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
|
||||||
|
|||||||
@@ -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
|
||||||
|
|||||||
Reference in New Issue
Block a user