Skip to content

Commit

Permalink
feat: add settings for python venv creation (#3489)
Browse files Browse the repository at this point in the history
Fixes #1721
Fixes #1720
  • Loading branch information
jdx authored Dec 12, 2024
1 parent a4b6316 commit ed23343
Show file tree
Hide file tree
Showing 5 changed files with 132 additions and 9 deletions.
3 changes: 3 additions & 0 deletions docs/lang/python.md
Original file line number Diff line number Diff line change
Expand Up @@ -136,6 +136,9 @@ _.python.venv = ".venv" # relative to this file's directory
_.python.venv = "/root/.venv" # can be absolute
_.python.venv = "{{env.HOME}}/.cache/venv/myproj" # can use templates
_.python.venv = { path = ".venv", create = true } # create the venv if it doesn't exist
_.python.venv = { path = ".venv", create = true, python = "3.10" } # use a specific python version
_.python.venv = { path = ".venv", create = true, python_create_args = "--without-pip" } # pass args to python -m venv
_.python.venv = { path = ".venv", create = true, uv_create_args = "--system-site-packages" } # pass args to uv venv
```

The venv will need to be created manually with `python -m venv /path/to/venv` unless `create=true`.
Expand Down
20 changes: 20 additions & 0 deletions schema/mise.json
Original file line number Diff line number Diff line change
Expand Up @@ -77,6 +77,18 @@
"path": {
"description": "path to python virtual environment to use",
"type": "string"
},
"python": {
"description": "python version to use",
"type": "string"
},
"python_create_args": {
"description": "additional arguments to pass to python when creating a virtual environment",
"type": "string"
},
"uv_create_args": {
"description": "additional arguments to pass to uv when creating a virtual environment",
"type": "string"
}
},
"required": ["path"],
Expand Down Expand Up @@ -505,11 +517,19 @@
"description": "Integrate with uv to automatically create/source venvs if uv.lock is present.",
"type": "boolean"
},
"uv_venv_create_args": {
"description": "Arguments to pass to uv when creating a venv.",
"type": "string"
},
"venv_auto_create": {
"description": "Automatically create virtualenvs for python tools.",
"type": "boolean",
"deprecated": true
},
"venv_create_args": {
"description": "Arguments to pass to python when creating a venv. (not used for uv venv creation)",
"type": "string"
},
"venv_stdlib": {
"description": "Prefer to use venv from Python's standard library.",
"type": "boolean"
Expand Down
12 changes: 12 additions & 0 deletions settings.toml
Original file line number Diff line number Diff line change
Expand Up @@ -651,13 +651,25 @@ env = "MISE_PYTHON_UV_VENV_AUTO"
type = "Bool"
description = "Integrate with uv to automatically create/source venvs if uv.lock is present."

[python.uv_venv_create_args]
env = "MISE_PYTHON_UV_VENV_CREATE_ARGS"
type = "String"
optional = true
description = "Arguments to pass to uv when creating a venv."

[python.venv_auto_create]
env = "MISE_PYTHON_VENV_AUTO_CREATE"
type = "Bool"
hide = true
deprecated = "Use env._python.venv instead."
description = "Automatically create virtualenvs for python tools."

[python.venv_create_args]
env = "MISE_PYTHON_VENV_CREATE_ARGS"
type = "String"
optional = true
description = "Arguments to pass to python when creating a venv. (not used for uv venv creation)"

[python.venv_stdlib]
env = "MISE_VENV_STDLIB"
type = "Bool"
Expand Down
30 changes: 29 additions & 1 deletion src/config/config_file/mise_toml.rs
Original file line number Diff line number Diff line change
Expand Up @@ -692,6 +692,9 @@ impl<'de> de::Deserialize<'de> for EnvList {
struct EnvDirectivePythonVenv {
path: PathBuf,
create: bool,
python: Option<String>,
uv_create_args: Option<Vec<String>>,
python_create_args: Option<Vec<String>>,
}

#[derive(Deserialize, Default)]
Expand Down Expand Up @@ -739,6 +742,9 @@ impl<'de> de::Deserialize<'de> for EnvList {
Ok(EnvDirectivePythonVenv {
path: v.into(),
create: false,
python: None,
uv_create_args: None,
python_create_args: None,
})
}

Expand All @@ -751,6 +757,9 @@ impl<'de> de::Deserialize<'de> for EnvList {
{
let mut path = None;
let mut create = false;
let mut python = None;
let mut uv_create_args = None;
let mut python_create_args = None;
while let Some(key) = map.next_key::<String>()? {
match key.as_str() {
"path" => {
Expand All @@ -759,6 +768,16 @@ impl<'de> de::Deserialize<'de> for EnvList {
"create" => {
create = map.next_value()?;
}
"python" => {
python = Some(map.next_value()?);
}
"uv_create_args" => {
uv_create_args = Some(map.next_value()?);
}
"python_create_args" => {
python_create_args =
Some(map.next_value()?);
}
_ => {
return Err(de::Error::unknown_field(
&key,
Expand All @@ -769,7 +788,13 @@ impl<'de> de::Deserialize<'de> for EnvList {
}
let path = path
.ok_or_else(|| de::Error::missing_field("path"))?;
Ok(EnvDirectivePythonVenv { path, create })
Ok(EnvDirectivePythonVenv {
path,
create,
python,
uv_create_args,
python_create_args,
})
}
}

Expand Down Expand Up @@ -800,6 +825,9 @@ impl<'de> de::Deserialize<'de> for EnvList {
env.push(EnvDirective::PythonVenv {
path: venv.path,
create: venv.create,
python: venv.python,
uv_create_args: venv.uv_create_args,
python_create_args: venv.python_create_args,
});
}
}
Expand Down
76 changes: 68 additions & 8 deletions src/config/env_directive.rs
Original file line number Diff line number Diff line change
Expand Up @@ -87,6 +87,9 @@ pub enum EnvDirective {
PythonVenv {
path: PathBuf,
create: bool,
python: Option<String>,
uv_create_args: Option<Vec<String>>,
python_create_args: Option<Vec<String>>,
},
Module(String, toml::Value),
}
Expand All @@ -112,11 +115,26 @@ impl Display for EnvDirective {
EnvDirective::Path(path) => write!(f, "path_add {}", display_path(path)),
EnvDirective::Source(path) => write!(f, "source {}", display_path(path)),
EnvDirective::Module(name, _) => write!(f, "module {}", name),
EnvDirective::PythonVenv { path, create } => {
EnvDirective::PythonVenv {
path,
create,
python,
uv_create_args,
python_create_args,
} => {
write!(f, "python venv path={}", display_path(path))?;
if *create {
write!(f, " create")?;
}
if let Some(python) = python {
write!(f, " python={}", python)?;
}
if let Some(args) = uv_create_args {
write!(f, " uv_create_args={:?}", args)?;
}
if let Some(args) = python_create_args {
write!(f, " python_create_args={:?}", args)?;
}
Ok(())
}
}
Expand Down Expand Up @@ -251,7 +269,13 @@ impl EnvResults {
}
}
}
EnvDirective::PythonVenv { path, create } => {
EnvDirective::PythonVenv {
path,
create,
python,
uv_create_args,
python_create_args,
} => {
trace!("python venv: {} create={create}", display_path(&path));
trust_check(&source)?;
let venv = r.parse_template(&ctx, &source, path.to_string_lossy().as_ref())?;
Expand All @@ -278,14 +302,44 @@ impl EnvResults {
let use_uv = !SETTINGS.python.venv_stdlib && has_uv_bin;
let cmd = if use_uv {
info!("creating venv with uv at: {}", display_path(&venv));
CmdLineRunner::new("uv").args(["venv", &venv.to_string_lossy()])
let extra = SETTINGS
.python
.uv_venv_create_args
.as_ref()
.and_then(|a| match shell_words::split(a) {
Ok(a) => Some(a),
Err(err) => {
warn!("failed to split uv_venv_create_args: {}", err);
None
}
})
.or(uv_create_args)
.unwrap_or_default();
let mut cmd = CmdLineRunner::new("uv")
.args(["venv", &venv.to_string_lossy()]);
if let Some(python) = python {
cmd = cmd.args(["--python", &python]);
}
cmd.args(extra)
} else {
info!("creating venv with stdlib at: {}", display_path(&venv));
CmdLineRunner::new("python3").args([
"-m",
"venv",
&venv.to_string_lossy(),
])
let extra = SETTINGS
.python
.venv_create_args
.as_ref()
.and_then(|a| match shell_words::split(a) {
Ok(a) => Some(a),
Err(err) => {
warn!("failed to split venv_create_args: {}", err);
None
}
})
.or(python_create_args)
.unwrap_or_default();
let bin = format!("python{}", python.unwrap_or("3".into()));
CmdLineRunner::new(bin)
.args(["-m", "venv", &venv.to_string_lossy()])
.args(extra)
}
.envs(&env_vars)
.env(
Expand Down Expand Up @@ -460,13 +514,19 @@ mod tests {
EnvDirective::PythonVenv {
path: PathBuf::from("/"),
create: false,
python: None,
uv_create_args: None,
python_create_args: None,
},
Default::default(),
),
(
EnvDirective::PythonVenv {
path: PathBuf::from("./"),
create: false,
python: None,
uv_create_args: None,
python_create_args: None,
},
Default::default(),
),
Expand Down

0 comments on commit ed23343

Please sign in to comment.