From c0bfba85c5a948a8af7c2f6bef221e4a0700488f Mon Sep 17 00:00:00 2001 From: "Joseph T. Lyons" Date: Fri, 16 Jan 2026 17:22:38 -0500 Subject: [PATCH] ty: Add support for using venv-installed binary (#47029) This aligns ty's behavior with ruff by checking for binaries in the following order: 1. venv (from the Python toolchain's bin directory) 2. PATH 3. Zed-installed Release Notes: - ty: Added support for using venv-installed binary --- crates/languages/src/python.rs | 31 ++++++++++++++++++++++--------- 1 file changed, 22 insertions(+), 9 deletions(-) diff --git a/crates/languages/src/python.rs b/crates/languages/src/python.rs index 8195ea554b537cf723904b440b77efc1a659ac01..0babfb7b11bbe8957c670fb9d6e7d009f779051c 100644 --- a/crates/languages/src/python.rs +++ b/crates/languages/src/python.rs @@ -300,18 +300,31 @@ impl LspInstaller for TyLspAdapter { async fn check_if_user_installed( &self, delegate: &dyn LspAdapterDelegate, - _: Option, + toolchain: Option, _: &AsyncApp, ) -> Option { - let Some(ty_bin) = delegate.which(Self::SERVER_NAME.as_ref()).await else { - return None; + let ty_in_venv = if let Some(toolchain) = toolchain + && toolchain.language_name.as_ref() == "Python" + { + Path::new(toolchain.path.as_str()) + .parent() + .map(|path| path.join("ty")) + } else { + None }; - let env = delegate.shell_env().await; - Some(LanguageServerBinary { - path: ty_bin, - env: Some(env), - arguments: vec!["server".into()], - }) + + for path in ty_in_venv.into_iter().chain(["ty".into()]) { + if let Some(ty_bin) = delegate.which(path.as_os_str()).await { + let env = delegate.shell_env().await; + return Some(LanguageServerBinary { + path: ty_bin, + env: Some(env), + arguments: vec!["server".into()], + }); + } + } + + None } async fn fetch_server_binary(