Debugger: install debugpy package into user resource dir

This avoids the need to install the package into every python and
virtual environment.

Change-Id: I0b7735c7ccef8bcd7c969c40c71f0a3d5a301a10
Reviewed-by: Artem Sokolovskii <artem.sokolovskii@qt.io>
Reviewed-by: <github-actions-qt-creator@cristianadam.eu>
This commit is contained in:
David Schulz
2023-11-29 13:08:56 +01:00
parent 91050d376f
commit 9ccf019896

View File

@@ -38,20 +38,18 @@ namespace Debugger::Internal {
const char installDebugPyInfoBarId[] = "Python::InstallDebugPy"; const char installDebugPyInfoBarId[] = "Python::InstallDebugPy";
static bool missingPySideInstallation(const FilePath &pythonPath, const QString &packageName) static FilePath packageDir(const FilePath &python, const QString &packageName)
{
expected_str<FilePath> baseDir = python.needsDevice() ? python.tmpDir()
: Core::ICore::userResourcePath();
return baseDir ? baseDir->pathAppended("debugpy") : FilePath();
}
static bool missingModuleInstallation(const FilePath &python, const QString &packageName)
{ {
QTC_ASSERT(!packageName.isEmpty(), return false); QTC_ASSERT(!packageName.isEmpty(), return false);
static QMap<FilePath, QSet<QString>> pythonWithPyside; const FilePath dir = packageDir(python, packageName);
if (pythonWithPyside[pythonPath].contains(packageName)) return !dir.isEmpty() && !dir.exists();
return false;
Process pythonProcess;
pythonProcess.setCommand({pythonPath, {"-c", "import " + packageName}});
pythonProcess.runBlocking();
const bool missing = pythonProcess.result() != ProcessResult::FinishedWithSuccess;
if (!missing)
pythonWithPyside[pythonPath].insert(packageName);
return missing;
} }
class TcpSocketDataProvider : public IDataProvider class TcpSocketDataProvider : public IDataProvider
@@ -82,7 +80,15 @@ public:
void start() override void start() override
{ {
m_proc.setEnvironment(m_runParameters.debugger.environment); Environment env = m_runParameters.debugger.environment;
const FilePath debugPyDir = packageDir(m_cmd.executable(), "debugpy");
if (QTC_GUARD(debugPyDir.isSameDevice(m_cmd.executable()))) {
env.appendOrSet("PYTHONPATH",
debugPyDir.needsDevice() ? debugPyDir.path() : debugPyDir.toUserOutput(),
OsSpecificAspects::pathListSeparator(debugPyDir.osType()));
}
m_proc.setEnvironment(env);
m_proc.setCommand(m_cmd); m_proc.setCommand(m_cmd);
// Workaround to have output for Python // Workaround to have output for Python
m_proc.setTerminalMode(TerminalMode::Run); m_proc.setTerminalMode(TerminalMode::Run);
@@ -221,7 +227,7 @@ void PyDapEngine::setupEngine()
return; return;
} }
if (missingPySideInstallation(interpreter, "debugpy")) { if (missingModuleInstallation(interpreter, "debugpy")) {
Utils::InfoBarEntry Utils::InfoBarEntry
info(installDebugPyInfoBarId, info(installDebugPyInfoBarId,
Tr::tr( Tr::tr(
@@ -230,9 +236,17 @@ void PyDapEngine::setupEngine()
info.addCustomButton(Tr::tr("Install debugpy"), [this] { info.addCustomButton(Tr::tr("Install debugpy"), [this] {
Core::ICore::infoBar()->removeInfo(installDebugPyInfoBarId); Core::ICore::infoBar()->removeInfo(installDebugPyInfoBarId);
Core::ICore::infoBar()->globallySuppressInfo(installDebugPyInfoBarId); Core::ICore::infoBar()->globallySuppressInfo(installDebugPyInfoBarId);
const FilePath target = packageDir(runParameters().interpreter, "dubugpy");
QTC_ASSERT(target.isSameDevice(runParameters().interpreter), return);
m_installProcess.reset(new Process); m_installProcess.reset(new Process);
m_installProcess->setCommand({runParameters().interpreter, m_installProcess->setCommand(
{"-m", "pip", "install", "debugpy"}}); {runParameters().interpreter,
{"-m",
"pip",
"install",
"-t",
target.needsDevice() ? target.path() : target.toUserOutput(),
"debugpy"}});
m_installProcess->setTerminalMode(TerminalMode::Run); m_installProcess->setTerminalMode(TerminalMode::Run);
m_installProcess->start(); m_installProcess->start();
}); });