uv_install_wheel/
lib.rs

1//! Takes a wheel and installs it into a venv.
2
3use std::io;
4use std::path::PathBuf;
5
6use owo_colors::OwoColorize;
7use thiserror::Error;
8
9use uv_fs::Simplified;
10use uv_normalize::PackageName;
11use uv_pep440::Version;
12use uv_pypi_types::Scheme;
13
14pub use install::install_wheel;
15pub use linker::{LinkMode, Locks};
16pub use uninstall::{Uninstall, uninstall_egg, uninstall_legacy_editable, uninstall_wheel};
17pub use wheel::{LibKind, WheelFile, read_record_file};
18
19mod install;
20mod linker;
21mod record;
22mod script;
23mod uninstall;
24mod wheel;
25
26/// The layout of the target environment into which a wheel can be installed.
27#[derive(Debug, Clone)]
28pub struct Layout {
29    /// The Python interpreter, as returned by `sys.executable`.
30    pub sys_executable: PathBuf,
31    /// The Python version, as returned by `sys.version_info`.
32    pub python_version: (u8, u8),
33    /// The `os.name` value for the current platform.
34    pub os_name: String,
35    /// The [`Scheme`] paths for the interpreter.
36    pub scheme: Scheme,
37}
38
39/// Note: The caller is responsible for adding the path of the wheel we're installing.
40#[derive(Error, Debug)]
41pub enum Error {
42    #[error(transparent)]
43    Io(#[from] io::Error),
44    /// Custom error type to add a path to error reading a file from a zip
45    #[error("Failed to reflink {} to {}", from.user_display(), to.user_display())]
46    Reflink {
47        from: PathBuf,
48        to: PathBuf,
49        #[source]
50        err: io::Error,
51    },
52    /// The wheel is broken
53    #[error("The wheel is invalid: {0}")]
54    InvalidWheel(String),
55    /// Doesn't follow file name schema
56    #[error("Failed to move data files")]
57    WalkDir(#[from] walkdir::Error),
58    #[error("RECORD file doesn't match wheel contents: {0}")]
59    RecordFile(String),
60    #[error("RECORD file is invalid")]
61    RecordCsv(#[from] csv::Error),
62    #[error("Broken virtual environment: {0}")]
63    BrokenVenv(String),
64    #[error(
65        "Unable to create Windows launcher for: {0} (only x86_64, x86, and arm64 are supported)"
66    )]
67    UnsupportedWindowsArch(&'static str),
68    #[error("Unable to create Windows launcher on non-Windows platform")]
69    NotWindows,
70    #[error("Invalid `direct_url.json`")]
71    DirectUrlJson(#[from] serde_json::Error),
72    #[error("Cannot uninstall package; `RECORD` file not found at: {}", _0.user_display())]
73    MissingRecord(PathBuf),
74    #[error("Cannot uninstall package; `top_level.txt` file not found at: {}", _0.user_display())]
75    MissingTopLevel(PathBuf),
76    #[error("Invalid package version")]
77    InvalidVersion(#[from] uv_pep440::VersionParseError),
78    #[error("Wheel package name does not match filename ({0} != {1}), which indicates a malformed wheel. If this is intentional, set `{env_var}`.", env_var = "UV_SKIP_WHEEL_FILENAME_CHECK=1".green())]
79    MismatchedName(PackageName, PackageName),
80    #[error("Wheel version does not match filename ({0} != {1}), which indicates a malformed wheel. If this is intentional, set `{env_var}`.", env_var = "UV_SKIP_WHEEL_FILENAME_CHECK=1".green())]
81    MismatchedVersion(Version, Version),
82    #[error("Invalid egg-link")]
83    InvalidEggLink(PathBuf),
84    #[error(transparent)]
85    LauncherError(#[from] uv_trampoline_builder::Error),
86    #[error("Scripts must not use the reserved name {0}")]
87    ReservedScriptName(String),
88}