-
Notifications
You must be signed in to change notification settings - Fork 959
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
allow centralized venv storage like pyenv-virtualenv #1578
Comments
I've been using a Maybe something like the following diff: diff --git a/crates/uv-interpreter/src/lib.rs b/crates/uv-interpreter/src/lib.rs
index 684c7f1..7c1caab 100644
--- a/crates/uv-interpreter/src/lib.rs
+++ b/crates/uv-interpreter/src/lib.rs
@@ -26,6 +26,8 @@ pub enum Error {
MissingPyVenvCfg(PathBuf),
#[error("Broken virtualenv `{0}`, it contains a pyvenv.cfg but no Python binary at `{1}`")]
BrokenVenv(PathBuf, PathBuf),
+ #[error("File `{0}` points to invalid location `{1}`")]
+ InvalidVenvFile(PathBuf, PathBuf),
#[error("Both VIRTUAL_ENV and CONDA_PREFIX are set. Please unset one of them.")]
Conflict,
#[error("No versions of Python could be found. Is Python installed?")]
diff --git a/crates/uv-interpreter/src/virtual_env.rs b/crates/uv-interpreter/src/virtual_env.rs
index 46c727c..a4b63a3 100644
--- a/crates/uv-interpreter/src/virtual_env.rs
+++ b/crates/uv-interpreter/src/virtual_env.rs
@@ -1,5 +1,6 @@
use std::env;
use std::env::consts::EXE_SUFFIX;
+use std::io::Read;
use std::path::{Path, PathBuf};
use tracing::debug;
@@ -116,21 +117,34 @@ pub(crate) fn detect_virtual_env(target: &PythonPlatform) -> Result<Option<PathB
}
};
- // Search for a `.venv` directory in the current or any parent directory.
+
+ // Search for `.venv` in the current or any parent directory.
let current_dir = env::current_dir().expect("Failed to detect current directory");
for dir in current_dir.ancestors() {
let dot_venv = dir.join(".venv");
- if dot_venv.is_dir() {
- if !dot_venv.join("pyvenv.cfg").is_file() {
- return Err(Error::MissingPyVenvCfg(dot_venv));
- }
- let python = target.venv_python(&dot_venv);
- if !python.is_file() {
- return Err(Error::BrokenVenv(dot_venv, python));
+
+ let venv_dir;
+ if dot_venv.is_file() {
+ let mut contents = String::new();
+ fs_err::File::open(&dot_venv)?.read_to_string(&mut contents)?;
+ venv_dir = PathBuf::from(contents.trim());
+ if !venv_dir.is_dir() {
+ return Err(Error::InvalidVenvFile(dot_venv, venv_dir));
}
- debug!("Found a virtualenv named .venv at: {}", dot_venv.display());
- return Ok(Some(dot_venv));
+ } else if dot_venv.is_dir() {
+ venv_dir = dot_venv;
+ } else {
+ continue;
+ }
+ if !venv_dir.join("pyvenv.cfg").is_file() {
+ return Err(Error::MissingPyVenvCfg(venv_dir));
+ }
+ let python = target.venv_python(&venv_dir);
+ if !python.is_file() {
+ return Err(Error::BrokenVenv(venv_dir, python));
}
+ debug!("Found a virtualenv at: {}", venv_dir.display());
+ return Ok(Some(venv_dir));
}
Ok(None) |
Basically a duplicate of #1526 |
For various reasons, I have a preference for out of tree virtual environments. Things just work if I symlink, but I don't know that this is guaranteed, so I thought I'd add a test for it. It looks like there's another code path that matters (`FoundInterpreter::discover -> PythonEnvironment::from_root`) for the higher level commands, but couldn't spot a good place to test that. Related discussion: #1495 (comment) / #1578 (comment)
May I suggest the PDM model? That is nice IMHO. Via a config variable you decide if you want venvs to be generally managed centrally or locally. When they are centrally managed, PDM sorts out things nicely in an almost automatic way. |
This provides a few handy features:
rm -rf
a folderTo identify which venv should be used in a folder, pyenv-virtualenv uses
.python-version
. I suggestuv
could use.uvenv
as follows:by invoking
uv venv
with a non-standard location, we know we'll want to keep track of that location, so I suggest storing it in.uvenv
right away without forcing the user to doecho "~/.venvs/myvenv" > .uvenv
.I can already use a script to auto-activate my venv from this remote location upon entering a folder (like an oh-my-zsh plugin):
but if this were built-in behavior defined in a central location equivalent to
PYENV_ROOT
then you could just give the name:uv venv local myvenv
pyenv blurb from https://github.com/pyenv/pyenv-virtualenv?tab=readme-ov-file#activate-virtualenv:
The text was updated successfully, but these errors were encountered: