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 uv #657

Merged
merged 23 commits into from
Feb 15, 2024
Merged
Show file tree
Hide file tree
Changes from 22 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
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 {
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I know this got merged already but this has a typo, it should probably be use_uv not use_uf.

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