Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

🔧 add --install-dir arg to uv python commands #7920

Merged
merged 7 commits into from
Dec 10, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
14 changes: 14 additions & 0 deletions crates/uv-cli/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4250,6 +4250,16 @@ pub struct PythonDirArgs {
#[derive(Args)]
#[allow(clippy::struct_excessive_bools)]
pub struct PythonInstallArgs {
/// The directory to store the Python installation in.
///
/// If provided, `UV_PYTHON_INSTALL_DIR` will need to be set for subsequent operations for
/// uv to discover the Python installation.
///
/// See `uv python dir` to view the current Python installation directory. Defaults to
/// `~/.local/share/uv/python`.
#[arg(long, short, env = "UV_PYTHON_INSTALL_DIR")]
pub install_dir: Option<PathBuf>,

/// The Python version(s) to install.
///
/// If not provided, the requested Python version(s) will be read from the
Expand Down Expand Up @@ -4310,6 +4320,10 @@ pub struct PythonInstallArgs {
#[derive(Args)]
#[allow(clippy::struct_excessive_bools)]
pub struct PythonUninstallArgs {
/// The directory where the Python was installed.
#[arg(long, short, env = "UV_PYTHON_INSTALL_DIR")]
pub install_dir: Option<PathBuf>,

/// The Python version(s) to uninstall.
///
/// See `uv help python` to view supported request formats.
Expand Down
2 changes: 1 addition & 1 deletion crates/uv-python/src/discovery.rs
Original file line number Diff line number Diff line change
Expand Up @@ -302,7 +302,7 @@ fn python_executables_from_installed<'a>(
preference: PythonPreference,
) -> Box<dyn Iterator<Item = Result<(PythonSource, PathBuf), Error>> + 'a> {
let from_managed_installations = std::iter::once_with(move || {
ManagedPythonInstallations::from_settings()
ManagedPythonInstallations::from_settings(None)
.map_err(Error::from)
.and_then(|installed_installations| {
debug!(
Expand Down
2 changes: 1 addition & 1 deletion crates/uv-python/src/installation.rs
Original file line number Diff line number Diff line change
Expand Up @@ -135,7 +135,7 @@ impl PythonInstallation {
python_install_mirror: Option<&str>,
pypy_install_mirror: Option<&str>,
) -> Result<Self, Error> {
let installations = ManagedPythonInstallations::from_settings()?.init()?;
let installations = ManagedPythonInstallations::from_settings(None)?.init()?;
let installations_dir = installations.root();
let scratch_dir = installations.scratch();
let _lock = installations.lock().await?;
Expand Down
16 changes: 10 additions & 6 deletions crates/uv-python/src/managed.rs
Original file line number Diff line number Diff line change
Expand Up @@ -107,11 +107,15 @@ impl ManagedPythonInstallations {
}

/// Prefer, in order:
/// 1. The specific Python directory specified by the user, i.e., `UV_PYTHON_INSTALL_DIR`
/// 2. A directory in the system-appropriate user-level data directory, e.g., `~/.local/uv/python`
/// 3. A directory in the local data directory, e.g., `./.uv/python`
pub fn from_settings() -> Result<Self, Error> {
if let Some(install_dir) = std::env::var_os(EnvVars::UV_PYTHON_INSTALL_DIR) {
///
/// 1. The specific Python directory passed via the `install_dir` argument.
/// 2. The specific Python directory specified with the `UV_PYTHON_INSTALL_DIR` environment variable.
/// 3. A directory in the system-appropriate user-level data directory, e.g., `~/.local/uv/python`.
/// 4. A directory in the local data directory, e.g., `./.uv/python`.
pub fn from_settings(install_dir: Option<PathBuf>) -> Result<Self, Error> {
if let Some(install_dir) = install_dir {
Ok(Self::from_path(install_dir))
} else if let Some(install_dir) = std::env::var_os(EnvVars::UV_PYTHON_INSTALL_DIR) {
Ok(Self::from_path(install_dir))
} else {
Ok(Self::from_path(
Expand Down Expand Up @@ -227,7 +231,7 @@ impl ManagedPythonInstallations {
) -> Result<impl DoubleEndedIterator<Item = ManagedPythonInstallation>, Error> {
let platform_key = platform_key_from_env()?;

let iter = ManagedPythonInstallations::from_settings()?
let iter = ManagedPythonInstallations::from_settings(None)?
.find_all()?
.filter(move |installation| {
installation
Expand Down
2 changes: 1 addition & 1 deletion crates/uv/src/commands/python/dir.rs
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ pub(crate) fn dir(bin: bool) -> anyhow::Result<()> {
let bin = python_executable_dir()?;
println!("{}", bin.simplified_display().cyan());
} else {
let installed_toolchains = ManagedPythonInstallations::from_settings()
let installed_toolchains = ManagedPythonInstallations::from_settings(None)
.context("Failed to initialize toolchain settings")?;
println!(
"{}",
Expand Down
3 changes: 2 additions & 1 deletion crates/uv/src/commands/python/install.rs
Original file line number Diff line number Diff line change
Expand Up @@ -121,6 +121,7 @@ impl Changelog {
#[allow(clippy::fn_params_excessive_bools)]
pub(crate) async fn install(
project_dir: &Path,
install_dir: Option<PathBuf>,
targets: Vec<String>,
reinstall: bool,
force: bool,
Expand Down Expand Up @@ -178,7 +179,7 @@ pub(crate) async fn install(
};

// Read the existing installations, lock the directory for the duration
let installations = ManagedPythonInstallations::from_settings()?.init()?;
let installations = ManagedPythonInstallations::from_settings(install_dir)?.init()?;
let installations_dir = installations.root();
let scratch_dir = installations.scratch();
let _lock = installations.lock().await?;
Expand Down
4 changes: 3 additions & 1 deletion crates/uv/src/commands/python/uninstall.rs
Original file line number Diff line number Diff line change
Expand Up @@ -22,12 +22,14 @@ use crate::printer::Printer;

/// Uninstall managed Python versions.
pub(crate) async fn uninstall(
install_dir: Option<PathBuf>,
targets: Vec<String>,
all: bool,

printer: Printer,
) -> Result<ExitStatus> {
let installations = ManagedPythonInstallations::from_settings()?.init()?;
let installations = ManagedPythonInstallations::from_settings(install_dir)?.init()?;

let _lock = installations.lock().await?;

// Perform the uninstallation.
Expand Down
3 changes: 2 additions & 1 deletion crates/uv/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1104,6 +1104,7 @@ async fn run(mut cli: Cli) -> Result<ExitStatus> {

commands::python_install(
&project_dir,
args.install_dir,
args.targets,
args.reinstall,
args.force,
Expand All @@ -1127,7 +1128,7 @@ async fn run(mut cli: Cli) -> Result<ExitStatus> {
let args = settings::PythonUninstallSettings::resolve(args, filesystem);
show_settings!(args);

commands::python_uninstall(args.targets, args.all, printer).await
commands::python_uninstall(args.install_dir, args.targets, args.all, printer).await
}
Commands::Python(PythonNamespace {
command: PythonCommand::Find(args),
Expand Down
16 changes: 14 additions & 2 deletions crates/uv/src/settings.rs
Original file line number Diff line number Diff line change
Expand Up @@ -760,6 +760,7 @@ impl PythonDirSettings {
#[allow(clippy::struct_excessive_bools)]
#[derive(Debug, Clone)]
pub(crate) struct PythonInstallSettings {
pub(crate) install_dir: Option<PathBuf>,
pub(crate) targets: Vec<String>,
pub(crate) reinstall: bool,
pub(crate) force: bool,
Expand All @@ -784,6 +785,7 @@ impl PythonInstallSettings {
let pypy_mirror = args.pypy_mirror.or(pypy_mirror);

let PythonInstallArgs {
install_dir,
targets,
reinstall,
force,
Expand All @@ -793,6 +795,7 @@ impl PythonInstallSettings {
} = args;

Self {
install_dir,
targets,
reinstall,
force,
Expand All @@ -807,6 +810,7 @@ impl PythonInstallSettings {
#[allow(clippy::struct_excessive_bools)]
#[derive(Debug, Clone)]
pub(crate) struct PythonUninstallSettings {
pub(crate) install_dir: Option<PathBuf>,
pub(crate) targets: Vec<String>,
pub(crate) all: bool,
}
Expand All @@ -818,9 +822,17 @@ impl PythonUninstallSettings {
args: PythonUninstallArgs,
_filesystem: Option<FilesystemOptions>,
) -> Self {
let PythonUninstallArgs { targets, all } = args;
let PythonUninstallArgs {
install_dir,
targets,
all,
} = args;

Self { targets, all }
Self {
install_dir,
targets,
all,
}
}
}

Expand Down
2 changes: 1 addition & 1 deletion crates/uv/tests/it/common/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1075,7 +1075,7 @@ pub fn venv_to_interpreter(venv: &Path) -> PathBuf {

/// Get the path to the python interpreter for a specific python version.
pub fn get_python(version: &PythonVersion) -> PathBuf {
ManagedPythonInstallations::from_settings()
ManagedPythonInstallations::from_settings(None)
.map(|installed_pythons| {
installed_pythons
.find_version(version)
Expand Down
17 changes: 15 additions & 2 deletions crates/uv/tests/it/help.rs
Original file line number Diff line number Diff line change
Expand Up @@ -450,7 +450,7 @@ fn help_subcommand() {
fn help_subsubcommand() {
let context = TestContext::new_with_versions(&[]);

uv_snapshot!(context.filters(), context.help().arg("python").arg("install"), @r##"
uv_snapshot!(context.filters(), context.help().arg("python").arg("install"), @r###"
success: true
exit_code: 0
----- stdout -----
Expand Down Expand Up @@ -483,6 +483,17 @@ fn help_subsubcommand() {
See `uv help python` to view supported request formats.

Options:
-i, --install-dir <INSTALL_DIR>
The directory to store the Python installation in.

If provided, `UV_PYTHON_INSTALL_DIR` will need to be set for subsequent operations for uv
to discover the Python installation.

See `uv python dir` to view the current Python installation directory. Defaults to
`~/.local/share/uv/python`.

[env: UV_PYTHON_INSTALL_DIR=]

--mirror <MIRROR>
Set the URL to use as the source for downloading Python installations.

Expand Down Expand Up @@ -673,7 +684,7 @@ fn help_subsubcommand() {


----- stderr -----
"##);
"###);
}

#[test]
Expand Down Expand Up @@ -759,6 +770,8 @@ fn help_flag_subsubcommand() {
[TARGETS]... The Python version(s) to install

Options:
-i, --install-dir <INSTALL_DIR> The directory to store the Python installation in [env:
UV_PYTHON_INSTALL_DIR=]
--mirror <MIRROR> Set the URL to use as the source for downloading Python
installations [env: UV_PYTHON_INSTALL_MIRROR=]
--pypy-mirror <PYPY_MIRROR> Set the URL to use as the source for downloading PyPy
Expand Down
4 changes: 2 additions & 2 deletions crates/uv/tests/it/python_install.rs
Original file line number Diff line number Diff line change
Expand Up @@ -74,7 +74,7 @@ fn python_install() {
error: the following required arguments were not provided:
<TARGETS>...

Usage: uv python uninstall <TARGETS>...
Usage: uv python uninstall --install-dir <INSTALL_DIR> <TARGETS>...

For more information, try '--help'.
"###);
Expand Down Expand Up @@ -209,7 +209,7 @@ fn python_install_preview() {
error: the following required arguments were not provided:
<TARGETS>...

Usage: uv python uninstall <TARGETS>...
Usage: uv python uninstall --install-dir <INSTALL_DIR> <TARGETS>...

For more information, try '--help'.
"###);
Expand Down
10 changes: 10 additions & 0 deletions docs/reference/cli.md
Original file line number Diff line number Diff line change
Expand Up @@ -4553,6 +4553,13 @@ uv python install [OPTIONS] [TARGETS]...

</dd><dt><code>--help</code>, <code>-h</code></dt><dd><p>Display the concise help for this command</p>

</dd><dt><code>--install-dir</code>, <code>-i</code> <i>install-dir</i></dt><dd><p>The directory to store the Python installation in.</p>

<p>If provided, <code>UV_PYTHON_INSTALL_DIR</code> will need to be set for subsequent operations for uv to discover the Python installation.</p>

<p>See <code>uv python dir</code> to view the current Python installation directory. Defaults to <code>~/.local/share/uv/python</code>.</p>

<p>May also be set with the <code>UV_PYTHON_INSTALL_DIR</code> environment variable.</p>
</dd><dt><code>--mirror</code> <i>mirror</i></dt><dd><p>Set the URL to use as the source for downloading Python installations.</p>

<p>The provided URL will replace <code>https://github.com/indygreg/python-build-standalone/releases/download</code> in, e.g., <code>https://github.com/indygreg/python-build-standalone/releases/download/20240713/cpython-3.12.4%2B20240713-aarch64-apple-darwin-install_only.tar.gz</code>.</p>
Expand Down Expand Up @@ -5114,6 +5121,9 @@ uv python uninstall [OPTIONS] <TARGETS>...

</dd><dt><code>--help</code>, <code>-h</code></dt><dd><p>Display the concise help for this command</p>

</dd><dt><code>--install-dir</code>, <code>-i</code> <i>install-dir</i></dt><dd><p>The directory where the Python was installed</p>

<p>May also be set with the <code>UV_PYTHON_INSTALL_DIR</code> environment variable.</p>
</dd><dt><code>--native-tls</code></dt><dd><p>Whether to load TLS certificates from the platform&#8217;s native certificate store.</p>

<p>By default, uv loads certificates from the bundled <code>webpki-roots</code> crate. The <code>webpki-roots</code> are a reliable set of trust roots from Mozilla, and including them in uv improves portability and performance (especially on macOS).</p>
Expand Down
Loading