Skip to content

Commit

Permalink
feat: use uv to create python's venv by default
Browse files Browse the repository at this point in the history
  • Loading branch information
erickguan committed Oct 12, 2024
1 parent 2304839 commit 877d37c
Show file tree
Hide file tree
Showing 8 changed files with 83 additions and 11 deletions.
11 changes: 11 additions & 0 deletions docs/lang/python.md
Original file line number Diff line number Diff line change
Expand Up @@ -101,6 +101,17 @@ Packages list to install with pip after installing a Python version.

Automatically create a virtualenv in the directory specified by `_.python.venv` if it doesn't exist.

Deprecated note: Use `env._python.venv` instead.

### `python_venv_stdlib`

* Type: `bool`
* Env: `MISE_PYTHON_VENV_STDLIB`
* Default: `false`

Prefer to use venv from Python's standard library.
By default, mise will prioritize `uv` for the virtual environment if `uv` is in the `PATH`.

## Default Python packages

mise can automatically install a default set of Python packages with pip right after installing a
Expand Down
39 changes: 39 additions & 0 deletions e2e/plugins/core/test_python_uv_venv
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
#!/usr/bin/env bash

export MISE_PYTHON_DEFAULT_PACKAGES_FILE="$HOME/.default-python-packages"

cat >.mise.toml <<EOF
[env._.python]
venv = {path = "my_venv", create=true}
[tools]
python = "3.12.3"
uv = "0.3.4"
EOF

mise i
assert "mise x -- python --version" "Python 3.12.3"
assert "mise x -- uv --version" "uv 0.3.4"
assert "mise env -s bash | grep VIRTUAL_ENV" "export VIRTUAL_ENV=$PWD/my_venv"
assert "mise x -- which python" "$PWD/my_venv/bin/python"
assert "mise x -- uv pip list" "Package Version
------- -------
pip 24.0"

# Allows opt-out uv's venv
mkdir -p subdir
cat >subdir/.mise.toml <<EOF
[env._.python]
venv = {path = "my_subvenv", create=true}
[tools]
python = "3.12.3"
uv = "0.3.4"
[settings]
python_venv_stdlib = true
EOF

cd subdir || exit
mise i
assert "mise x -- python --version" "Python 3.12.3"
assert "mise env -s bash | grep VIRTUAL_ENV" "export VIRTUAL_ENV=$PWD/my_subvenv"
assert "mise x -- which python" "$PWD/my_subvenv/bin/python"
assert_contains "ls $PWD/my_subvenv/" "include" # stdlib virtual venv has an "include" folder while uv doesn't
4 changes: 4 additions & 0 deletions schema/mise.json
Original file line number Diff line number Diff line change
Expand Up @@ -340,6 +340,10 @@
"deprecated": "Use env._python.venv instead.",
"type": "boolean"
},
"python_venv_stdlib": {
"description": "Prefer to use venv from Python's standard library.",
"type": "boolean"
},
"quiet": {
"description": "Suppress all output except errors.",
"type": "boolean"
Expand Down
5 changes: 5 additions & 0 deletions settings.toml
Original file line number Diff line number Diff line change
Expand Up @@ -374,6 +374,11 @@ hide = true
deprecated = "Use env._python.venv instead."
description = "Automatically create virtualenvs for python tools."

[python_venv_stdlib]
env = "MISE_VENV_STDLIB"
type = "bool"
description = "Use venv from Python's standard library."

[quiet]
env = "MISE_QUIET"
type = "bool"
Expand Down
2 changes: 2 additions & 0 deletions src/cli/settings/ls.rs
Original file line number Diff line number Diff line change
Expand Up @@ -90,6 +90,7 @@ mod tests {
plugin_autoupdate_last_check_duration = "20m"
python_default_packages_file = "~/.default-python-packages"
python_pyenv_repo = "https://github.com/pyenv/pyenv.git"
python_venv_stdlib = false
quiet = false
raw = false
trusted_config_paths = []
Expand Down Expand Up @@ -149,6 +150,7 @@ mod tests {
plugin_autoupdate_last_check_duration
python_default_packages_file
python_pyenv_repo
python_venv_stdlib
quiet
raw
ruby
Expand Down
1 change: 1 addition & 0 deletions src/cli/settings/set.rs
Original file line number Diff line number Diff line change
Expand Up @@ -178,6 +178,7 @@ pub mod tests {
plugin_autoupdate_last_check_duration = "1"
python_default_packages_file = "~/.default-python-packages"
python_pyenv_repo = "https://github.com/pyenv/pyenv.git"
python_venv_stdlib = false
quiet = false
raw = false
trusted_config_paths = []
Expand Down
1 change: 1 addition & 0 deletions src/cli/settings/unset.rs
Original file line number Diff line number Diff line change
Expand Up @@ -81,6 +81,7 @@ mod tests {
plugin_autoupdate_last_check_duration = "20m"
python_default_packages_file = "~/.default-python-packages"
python_pyenv_repo = "https://github.com/pyenv/pyenv.git"
python_venv_stdlib = false
quiet = false
raw = false
trusted_config_paths = []
Expand Down
31 changes: 20 additions & 11 deletions src/config/env_directive.rs
Original file line number Diff line number Diff line change
Expand Up @@ -9,10 +9,11 @@ use serde::{Deserialize, Deserializer};

use crate::cmd::CmdLineRunner;
use crate::config::config_file::trust_check;
use crate::config::{Config, Settings};
use crate::config::settings::SETTINGS;
use crate::config::Config;
use crate::env::PATH_KEY;
use crate::env_diff::{EnvDiff, EnvDiffOperation};
use crate::file::display_path;
use crate::file::{display_path, which_non_pristine};
use crate::tera::{get_tera, BASE_CONTEXT};
use crate::toolset::ToolsetBuilder;
use crate::{dirs, env};
Expand Down Expand Up @@ -133,7 +134,6 @@ impl EnvResults {
initial: &HashMap<String, String>,
input: Vec<(EnvDirective, PathBuf)>,
) -> eyre::Result<Self> {
let settings = Settings::get();
let mut ctx = BASE_CONTEXT.clone();
trace!("resolve: input: {:#?}", &input);
let mut env = initial
Expand Down Expand Up @@ -224,7 +224,7 @@ impl EnvResults {
}
}
EnvDirective::Source(input) => {
settings.ensure_experimental("env._.source")?;
SETTINGS.ensure_experimental("env._.source")?;
trust_check(&source)?;
let s = r.parse_template(&ctx, &source, input.to_string_lossy().as_ref())?;
for p in xx::file::glob(normalize_path(&config_root, s.into()))? {
Expand Down Expand Up @@ -258,20 +258,29 @@ impl EnvResults {
.into_iter()
.chain(env::split_paths(&env_vars[&*PATH_KEY]))
.collect::<Vec<_>>();
let cmd = CmdLineRunner::new("python3")
.args(["-m", "venv", &venv.to_string_lossy()])
.envs(&env_vars)
.env(
PATH_KEY.to_string(),
env::join_paths(&path)?.to_string_lossy().to_string(),
);
if ts
.list_missing_versions()
.iter()
.any(|tv| tv.backend.name == "python")
{
debug!("python not installed, skipping venv creation");
} else {
let cmd = if let (false, Some(_uv_in_path)) =
(SETTINGS.python_venv_stdlib, which_non_pristine("uv"))
{
CmdLineRunner::new("uv").args(["venv", &venv.to_string_lossy()])
} else {
CmdLineRunner::new("python3").args([
"-m",
"venv",
&venv.to_string_lossy(),
])
}
.envs(&env_vars)
.env(
PATH_KEY.to_string(),
env::join_paths(&path)?.to_string_lossy().to_string(),
);
info!("creating venv at: {}", display_path(&venv));
cmd.execute()?;
}
Expand Down

0 comments on commit 877d37c

Please sign in to comment.