From 5444fbd8fed6865e25546dcbf83dcf2d7b24af48 Mon Sep 17 00:00:00 2001 From: Piotr Osiewicz <24362066+osiewicz@users.noreply.github.com> Date: Wed, 27 Aug 2025 22:59:56 +0200 Subject: [PATCH] python: Look for local venvs in all directories between root of the worktree and current pyproject.toml (#37037) cc @michael-ud - if you can build Zed, I'd appreciate it if you could give this a go with your project. Otherwise I can provide a link to download of current nightly via an e-mail for you to try out (if you want). This change will land in Preview (if merged) on next Wednesday and then it'll be in Stable a week after that. Related to: #20402 Release Notes: - python: Zed now searches for virtual environments in intermediate directories between a root of the worktree and the location of pyproject.toml applicable to the currently focused file. --- crates/language/src/toolchain.rs | 2 +- crates/languages/src/python.rs | 18 ++++++++++-------- crates/project/src/project_tests.rs | 7 ++++--- crates/project/src/toolchain_store.rs | 7 +------ 4 files changed, 16 insertions(+), 18 deletions(-) diff --git a/crates/language/src/toolchain.rs b/crates/language/src/toolchain.rs index 73c142c8ca02c986b0602c1f19a8c479c041f6f7..66879e56da0a4a7cdac5b64acbce9e31313bf373 100644 --- a/crates/language/src/toolchain.rs +++ b/crates/language/src/toolchain.rs @@ -52,7 +52,7 @@ pub trait ToolchainLister: Send + Sync { async fn list( &self, worktree_root: PathBuf, - subroot_relative_path: Option>, + subroot_relative_path: Arc, project_env: Option>, ) -> ToolchainList; // Returns a term which we should use in UI to refer to a toolchain. diff --git a/crates/languages/src/python.rs b/crates/languages/src/python.rs index d21b5dabd34c311d6e08140b2bc7ed363f79f273..0f78d5c5dfaaf3f24a337cab32ed9656354ac911 100644 --- a/crates/languages/src/python.rs +++ b/crates/languages/src/python.rs @@ -759,7 +759,7 @@ impl ToolchainLister for PythonToolchainProvider { async fn list( &self, worktree_root: PathBuf, - subroot_relative_path: Option>, + subroot_relative_path: Arc, project_env: Option>, ) -> ToolchainList { let env = project_env.unwrap_or_default(); @@ -771,13 +771,15 @@ impl ToolchainLister for PythonToolchainProvider { ); let mut config = Configuration::default(); - let mut directories = vec![worktree_root.clone()]; - if let Some(subroot_relative_path) = subroot_relative_path { - debug_assert!(subroot_relative_path.is_relative()); - directories.push(worktree_root.join(subroot_relative_path)); - } - - config.workspace_directories = Some(directories); + debug_assert!(subroot_relative_path.is_relative()); + // `.ancestors()` will yield at least one path, so in case of empty `subroot_relative_path`, we'll just use + // worktree root as the workspace directory. + config.workspace_directories = Some( + subroot_relative_path + .ancestors() + .map(|ancestor| worktree_root.join(ancestor)) + .collect(), + ); for locator in locators.iter() { locator.configure(&config); } diff --git a/crates/project/src/project_tests.rs b/crates/project/src/project_tests.rs index ed15ba845ad815006d5f8de4368a0e61f77c7940..a8f911883d619214a35f3ef5d80f83d6dc1b3894 100644 --- a/crates/project/src/project_tests.rs +++ b/crates/project/src/project_tests.rs @@ -9189,13 +9189,14 @@ fn python_lang(fs: Arc) -> Arc { async fn list( &self, worktree_root: PathBuf, - subroot_relative_path: Option>, + subroot_relative_path: Arc, _: Option>, ) -> ToolchainList { // This lister will always return a path .venv directories within ancestors let ancestors = subroot_relative_path - .into_iter() - .flat_map(|path| path.ancestors().map(ToOwned::to_owned).collect::>()); + .ancestors() + .map(ToOwned::to_owned) + .collect::>(); let mut toolchains = vec![]; for ancestor in ancestors { let venv_path = worktree_root.join(ancestor).join(".venv"); diff --git a/crates/project/src/toolchain_store.rs b/crates/project/src/toolchain_store.rs index ac87e6424821a5d28dbf48b92b077183a21d8608..57d492e26fc7b59df02df0128ed6b9ade132c6d9 100644 --- a/crates/project/src/toolchain_store.rs +++ b/crates/project/src/toolchain_store.rs @@ -389,12 +389,7 @@ impl LocalToolchainStore { cx.background_spawn(async move { Some(( toolchains - .list( - worktree_root, - Some(relative_path.path.clone()) - .filter(|_| *relative_path.path != *Path::new("")), - project_env, - ) + .list(worktree_root, relative_path.path.clone(), project_env) .await, relative_path.path, ))