Skip to content

Commit

Permalink
Add uv (astral-sh#657)
Browse files Browse the repository at this point in the history
  • Loading branch information
mitsuhiko authored and j178 committed Feb 18, 2024
1 parent c18a467 commit fd1d4be
Show file tree
Hide file tree
Showing 8 changed files with 217 additions and 97 deletions.
2 changes: 2 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,8 @@ _Unreleased_

- Added new `rye list` command and deprecated `rye show --installed-deps` which it replaces. #656

- Added experimental support for `uv`.

<!-- released start -->

## 0.23.0
Expand Down
3 changes: 2 additions & 1 deletion rye/src/bootstrap.rs
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,7 @@ pub const SELF_PYTHON_TARGET_VERSION: PythonVersionRequest = PythonVersionReques
suffix: None,
};

const SELF_VERSION: u64 = 10;
const SELF_VERSION: u64 = 11;

const SELF_REQUIREMENTS: &str = r#"
build==1.0.3
Expand All @@ -57,6 +57,7 @@ unearth==0.14.0
urllib3==2.0.7
virtualenv==20.25.0
ruff==0.1.14
uv==0.1.0
"#;

static FORCED_TO_UPDATE: AtomicBool = AtomicBool::new(false);
Expand Down
23 changes: 16 additions & 7 deletions rye/src/cli/list.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ use anyhow::{bail, Error};
use clap::Parser;

use crate::bootstrap::ensure_self_venv;
use crate::config::Config;
use crate::consts::VENV_BIN;
use crate::pyproject::PyProject;
use crate::utils::{get_venv_python_bin, CommandOutput};
Expand All @@ -25,13 +26,21 @@ pub fn execute(cmd: Args) -> Result<(), Error> {
}
let self_venv = ensure_self_venv(CommandOutput::Normal)?;

let status = Command::new(self_venv.join(VENV_BIN).join("pip"))
.arg("--python")
.arg(&python)
.arg("freeze")
.env("PYTHONWARNINGS", "ignore")
.env("PIP_DISABLE_PIP_VERSION_CHECK", "1")
.status()?;
let status = if Config::current().use_uf() {
Command::new(self_venv.join(VENV_BIN).join("uv"))
.arg("pip")
.arg("freeze")
.env("VIRTUAL_ENV", project.venv_path().as_os_str())
.status()?
} else {
Command::new(self_venv.join(VENV_BIN).join("pip"))
.arg("--python")
.arg(&python)
.arg("freeze")
.env("PYTHONWARNINGS", "ignore")
.env("PIP_DISABLE_PIP_VERSION_CHECK", "1")
.status()?
};

if !status.success() {
bail!("failed to print dependencies via pip");
Expand Down
17 changes: 17 additions & 0 deletions rye/src/cli/rye.rs
Original file line number Diff line number Diff line change
Expand Up @@ -441,6 +441,23 @@ fn perform_install(
return Err(QuietExit(1).into());
}

// Use uv?
if config_doc
.get("behavior")
.and_then(|x| x.get("use-uv"))
.is_none()
&& (matches!(mode, InstallMode::NoPrompts)
|| dialoguer::Select::with_theme(tui_theme())
.with_prompt("Select the preferred package installer")
.item("pip-tools (slow but stable)")
.item("uv (quick but experimental)")
.default(0)
.interact()?
== 1)
{
toml::ensure_table(config_doc, "behavior")["use-uv"] = toml_edit::value(true);
}

// If the global-python flag is not in the settings, ask the user if they want to turn
// on global shims upon installation.
if config_doc
Expand Down
16 changes: 16 additions & 0 deletions rye/src/config.rs
Original file line number Diff line number Diff line change
Expand Up @@ -246,4 +246,20 @@ impl Config {

Ok(rv)
}

/// Indicates if the experimental uv support should be used.
pub fn use_uf(&self) -> bool {
let yes = self
.doc
.get("behavior")
.and_then(|x| x.get("use-uv"))
.and_then(|x| x.as_bool())
.unwrap_or(false);
if yes && cfg!(windows) {
warn!("uv enabled in config but not supported on windows");
false
} else {
yes
}
}
}
24 changes: 17 additions & 7 deletions rye/src/installer.rs
Original file line number Diff line number Diff line change
Expand Up @@ -127,14 +127,24 @@ pub fn install(
requirement.name.as_str(),
)?;

let mut cmd = Command::new(self_venv.join(VENV_BIN).join("pip"));
cmd.arg("--python")
.arg(&py)
.arg("install")
.env("PYTHONWARNINGS", "ignore")
.env("PIP_DISABLE_PIP_VERSION_CHECK", "1");
sources.add_as_pip_args(&mut cmd);
let mut cmd = if Config::current().use_uf() {
let mut cmd = Command::new(self_venv.join(VENV_BIN).join("uv"));
cmd.arg("pip")
.arg("install")
.env("VIRTUAL_ENV", &target_venv_path)
.env("PYTHONWARNINGS", "ignore");
cmd
} else {
let mut cmd = Command::new(self_venv.join(VENV_BIN).join("pip"));
cmd.arg("--python")
.arg(&py)
.arg("install")
.env("PYTHONWARNINGS", "ignore")
.env("PIP_DISABLE_PIP_VERSION_CHECK", "1");
cmd
};

sources.add_as_pip_args(&mut cmd);
if output == CommandOutput::Verbose {
cmd.arg("--verbose");
} else {
Expand Down
77 changes: 50 additions & 27 deletions rye/src/lock.rs
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,9 @@ use serde::Serialize;
use tempfile::NamedTempFile;
use url::Url;

use crate::bootstrap::ensure_self_venv;
use crate::config::Config;
use crate::consts::VENV_BIN;
use crate::piptools::{get_pip_compile, get_pip_tools_version, PipToolsVersion};
use crate::pyproject::{
normalize_package_name, DependencyKind, ExpandedSources, PyProject, Workspace,
Expand Down Expand Up @@ -134,7 +137,7 @@ pub fn update_workspace_lockfile(
sources,
lock_options,
&exclusions,
&["--pip-args=--no-deps"],
true,
)?;

Ok(())
Expand Down Expand Up @@ -287,7 +290,7 @@ pub fn update_single_project_lockfile(
sources,
lock_options,
&exclusions,
&[],
false,
)?;

Ok(())
Expand All @@ -303,7 +306,7 @@ fn generate_lockfile(
sources: &ExpandedSources,
lock_options: &LockOptions,
exclusions: &HashSet<Requirement>,
extra_args: &[&str],
no_deps: bool,
) -> Result<(), Error> {
let scratch = tempfile::tempdir()?;
let requirements_file = scratch.path().join("requirements.txt");
Expand All @@ -313,36 +316,55 @@ fn generate_lockfile(
fs::write(&requirements_file, b"")?;
}

let pip_compile = get_pip_compile(py_ver, output)?;
let mut cmd = Command::new(pip_compile);

// legacy pip tools requires some extra parameters
if get_pip_tools_version(py_ver) == PipToolsVersion::Legacy {
cmd.arg("--resolver=backtracking");
}
let mut cmd = if Config::current().use_uf() {
let self_venv = ensure_self_venv(output)?;
let mut cmd = Command::new(self_venv.join(VENV_BIN).join("uv"));
cmd.arg("pip")
.arg("compile")
.arg("--no-header")
.arg(format!(
"--python-version={}.{}.{}",
py_ver.major, py_ver.minor, py_ver.patch
));
if output == CommandOutput::Verbose {
cmd.arg("--verbose");
} else if output == CommandOutput::Quiet {
cmd.arg("-q");
}
cmd
} else {
let mut cmd = Command::new(get_pip_compile(py_ver, output)?);
// legacy pip tools requires some extra parameters
if get_pip_tools_version(py_ver) == PipToolsVersion::Legacy {
cmd.arg("--resolver=backtracking");
}
cmd.arg("--strip-extras")
.arg("--allow-unsafe")
.arg("--no-header")
.arg("--annotate")
.arg("--pip-args")
.arg(format!(
"--python-version=\"{}.{}.{}\"{}",
py_ver.major,
py_ver.minor,
py_ver.patch,
if no_deps { " --no-deps" } else { "" }
))
.arg(if output == CommandOutput::Verbose {
"--verbose"
} else {
"-q"
});
cmd
};

cmd.arg("--no-annotate")
.arg("--strip-extras")
.arg("--allow-unsafe")
.arg("--no-header")
.arg("--annotate")
.arg("--pip-args")
.arg(format!(
"--python-version=\"{}.{}\"",
py_ver.major, py_ver.minor
))
.arg("-o")
cmd.arg("-o")
.arg(&requirements_file)
.arg(requirements_file_in)
.current_dir(workspace_path)
.env("PYTHONWARNINGS", "ignore")
.env("PROJECT_ROOT", make_project_root_fragment(workspace_path));

if output == CommandOutput::Verbose {
cmd.arg("--verbose");
} else {
cmd.arg("-q");
}
for pkg in &lock_options.update {
cmd.arg("--upgrade-package");
cmd.arg(pkg);
Expand All @@ -354,7 +376,6 @@ fn generate_lockfile(
cmd.arg("--pre");
}
sources.add_as_pip_args(&mut cmd);
cmd.args(extra_args);
set_proxy_variables(&mut cmd);
let status = cmd.status().context("unable to run pip-compile")?;
if !status.success() {
Expand Down Expand Up @@ -427,6 +448,8 @@ fn finalize_lockfile(
}
};
continue;
} else if line.starts_with('#') {
continue;
}
writeln!(rv, "{}", line)?;
}
Expand Down

0 comments on commit fd1d4be

Please sign in to comment.