1use std::io;
2use std::path::{Path, PathBuf};
3
4use thiserror::Error;
5
6use uv_python::{Interpreter, PythonEnvironment};
7
8pub use virtualenv::{OnExisting, RemovalReason, remove_virtualenv};
9
10mod virtualenv;
11
12#[derive(Debug, Error)]
13pub enum Error {
14 #[error(transparent)]
15 Io(#[from] io::Error),
16 #[error(
17 "Could not find a suitable Python executable for the virtual environment based on the interpreter: {0}"
18 )]
19 NotFound(String),
20 #[error(transparent)]
21 Python(#[from] uv_python::managed::Error),
22 #[error("A {name} already exists at `{}`. Use `--clear` to replace it", path.display())]
23 Exists {
24 name: &'static str,
26 path: PathBuf,
28 },
29}
30
31#[derive(Debug)]
33pub enum Prompt {
34 CurrentDirectoryName,
36 Static(String),
38 None,
41}
42
43impl Prompt {
44 pub fn from_args(prompt: Option<String>) -> Self {
46 match prompt {
47 Some(prompt) if prompt == "." => Self::CurrentDirectoryName,
48 Some(prompt) => Self::Static(prompt),
49 None => Self::None,
50 }
51 }
52}
53
54#[expect(clippy::fn_params_excessive_bools)]
56pub fn create_venv(
57 location: &Path,
58 interpreter: Interpreter,
59 prompt: Prompt,
60 system_site_packages: bool,
61 on_existing: OnExisting,
62 relocatable: bool,
63 seed: bool,
64 upgradeable: bool,
65) -> Result<PythonEnvironment, Error> {
66 let virtualenv = virtualenv::create(
68 location,
69 &interpreter,
70 prompt,
71 system_site_packages,
72 on_existing,
73 relocatable,
74 seed,
75 upgradeable,
76 )?;
77
78 let interpreter = interpreter.with_virtualenv(virtualenv);
80 Ok(PythonEnvironment::from_interpreter(interpreter))
81}