debugger: Install debugpy into user's venv if there's one selected (#35617)
Closes #35388 Release Notes: - debugger: Fixed Python debug sessions failing to launch due to a missing debugpy installation. Debugpy is now installed into user's venv if there's one available.
This commit is contained in:
parent
182edbf526
commit
91bbdb7002
1 changed files with 40 additions and 21 deletions
|
@ -126,38 +126,42 @@ impl PythonDebugAdapter {
|
||||||
}
|
}
|
||||||
None
|
None
|
||||||
}
|
}
|
||||||
|
const BINARY_DIR: &str = if cfg!(target_os = "windows") {
|
||||||
|
"Scripts"
|
||||||
|
} else {
|
||||||
|
"bin"
|
||||||
|
};
|
||||||
async fn base_venv(&self, delegate: &dyn DapDelegate) -> Result<Arc<Path>, String> {
|
async fn base_venv(&self, delegate: &dyn DapDelegate) -> Result<Arc<Path>, String> {
|
||||||
const BINARY_DIR: &str = if cfg!(target_os = "windows") {
|
|
||||||
"Scripts"
|
|
||||||
} else {
|
|
||||||
"bin"
|
|
||||||
};
|
|
||||||
self.python_venv_base
|
self.python_venv_base
|
||||||
.get_or_init(move || async move {
|
.get_or_init(move || async move {
|
||||||
let venv_base = Self::ensure_venv(delegate)
|
let venv_base = Self::ensure_venv(delegate)
|
||||||
.await
|
.await
|
||||||
.map_err(|e| format!("{e}"))?;
|
.map_err(|e| format!("{e}"))?;
|
||||||
let pip_path = venv_base.join(BINARY_DIR).join("pip3");
|
Self::install_debugpy_into_venv(&venv_base).await?;
|
||||||
let installation_succeeded = util::command::new_smol_command(pip_path.as_path())
|
|
||||||
.arg("install")
|
|
||||||
.arg("debugpy")
|
|
||||||
.arg("-U")
|
|
||||||
.output()
|
|
||||||
.await
|
|
||||||
.map_err(|e| format!("{e}"))?
|
|
||||||
.status
|
|
||||||
.success();
|
|
||||||
if !installation_succeeded {
|
|
||||||
return Err("debugpy installation failed".into());
|
|
||||||
}
|
|
||||||
|
|
||||||
Ok(venv_base)
|
Ok(venv_base)
|
||||||
})
|
})
|
||||||
.await
|
.await
|
||||||
.clone()
|
.clone()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
async fn install_debugpy_into_venv(venv_path: &Path) -> Result<(), String> {
|
||||||
|
let pip_path = venv_path.join(Self::BINARY_DIR).join("pip3");
|
||||||
|
let installation_succeeded = util::command::new_smol_command(pip_path.as_path())
|
||||||
|
.arg("install")
|
||||||
|
.arg("debugpy")
|
||||||
|
.arg("-U")
|
||||||
|
.output()
|
||||||
|
.await
|
||||||
|
.map_err(|e| format!("{e}"))?
|
||||||
|
.status
|
||||||
|
.success();
|
||||||
|
if !installation_succeeded {
|
||||||
|
return Err("debugpy installation failed".into());
|
||||||
|
}
|
||||||
|
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
async fn get_installed_binary(
|
async fn get_installed_binary(
|
||||||
&self,
|
&self,
|
||||||
delegate: &Arc<dyn DapDelegate>,
|
delegate: &Arc<dyn DapDelegate>,
|
||||||
|
@ -629,11 +633,22 @@ impl DebugAdapter for PythonDebugAdapter {
|
||||||
.await;
|
.await;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
let base_path = config
|
||||||
|
.config
|
||||||
|
.get("cwd")
|
||||||
|
.and_then(|cwd| {
|
||||||
|
cwd.as_str()
|
||||||
|
.map(Path::new)?
|
||||||
|
.strip_prefix(delegate.worktree_root_path())
|
||||||
|
.ok()
|
||||||
|
})
|
||||||
|
.unwrap_or_else(|| "".as_ref())
|
||||||
|
.into();
|
||||||
let toolchain = delegate
|
let toolchain = delegate
|
||||||
.toolchain_store()
|
.toolchain_store()
|
||||||
.active_toolchain(
|
.active_toolchain(
|
||||||
delegate.worktree_id(),
|
delegate.worktree_id(),
|
||||||
Arc::from("".as_ref()),
|
base_path,
|
||||||
language::LanguageName::new(Self::LANGUAGE_NAME),
|
language::LanguageName::new(Self::LANGUAGE_NAME),
|
||||||
cx,
|
cx,
|
||||||
)
|
)
|
||||||
|
@ -641,6 +656,10 @@ impl DebugAdapter for PythonDebugAdapter {
|
||||||
|
|
||||||
if let Some(toolchain) = &toolchain {
|
if let Some(toolchain) = &toolchain {
|
||||||
if let Some(path) = Path::new(&toolchain.path.to_string()).parent() {
|
if let Some(path) = Path::new(&toolchain.path.to_string()).parent() {
|
||||||
|
if let Some(parent) = path.parent() {
|
||||||
|
Self::install_debugpy_into_venv(parent).await.ok();
|
||||||
|
}
|
||||||
|
|
||||||
let debugpy_path = path.join("debugpy");
|
let debugpy_path = path.join("debugpy");
|
||||||
if delegate.fs().is_file(&debugpy_path).await {
|
if delegate.fs().is_file(&debugpy_path).await {
|
||||||
log::debug!(
|
log::debug!(
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue