Skip to main content

uv_virtualenv/
lib.rs

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        /// The type of environment (e.g., "virtual environment").
25        name: &'static str,
26        /// The path to the existing environment.
27        path: PathBuf,
28    },
29}
30
31/// The value to use for the shell prompt when inside a virtual environment.
32#[derive(Debug)]
33pub enum Prompt {
34    /// Use the current directory name as the prompt.
35    CurrentDirectoryName,
36    /// Use the fixed string as the prompt.
37    Static(String),
38    /// Default to no prompt. The prompt is then set by the activator script
39    /// to the virtual environment's directory name.
40    None,
41}
42
43impl Prompt {
44    /// Determine the prompt value to be used from the command line arguments.
45    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/// Create a virtualenv.
55#[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    // Create the virtualenv at the given location.
67    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    // Create the corresponding `PythonEnvironment`.
79    let interpreter = interpreter.with_virtualenv(virtualenv);
80    Ok(PythonEnvironment::from_interpreter(interpreter))
81}