Skip to content

Commit

Permalink
Use uv in rye build when enabled (#978)
Browse files Browse the repository at this point in the history
The `build` package supports uv since version 1.2.0 - it can use either
uv or pip as installer.

The main way to use it would be to install `build[uv]` but rye already
has uv installed separately, build will find it on the path as a
fallback, so this can work for rye.

build is implicitly tested by test_publish.

Relates to #668
  • Loading branch information
bluss authored Apr 24, 2024
1 parent 5fc717d commit c62d0f4
Show file tree
Hide file tree
Showing 5 changed files with 44 additions and 6 deletions.
2 changes: 2 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,8 @@ that were not yet released.

_Unreleased_

- Use uv in `rye build` when uv is enabled. #978

<!-- released start -->

## 0.33.0
Expand Down
4 changes: 2 additions & 2 deletions rye/src/bootstrap.rs
Original file line number Diff line number Diff line change
Expand Up @@ -33,10 +33,10 @@ pub const SELF_PYTHON_TARGET_VERSION: PythonVersionRequest = PythonVersionReques
suffix: None,
};

const SELF_VERSION: u64 = 17;
const SELF_VERSION: u64 = 18;

const SELF_REQUIREMENTS: &str = r#"
build==1.1.1
build==1.2.1
certifi==2024.2.2
charset-normalizer==3.3.2
click==8.1.7
Expand Down
26 changes: 22 additions & 4 deletions rye/src/cli/build.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,13 +2,15 @@ use std::fs;
use std::path::PathBuf;
use std::process::{Command, Stdio};

use anyhow::{bail, Error};
use anyhow::{anyhow, bail, Error};
use clap::Parser;
use console::style;

use crate::bootstrap::ensure_self_venv;
use crate::config::Config;
use crate::pyproject::{locate_projects, PyProject};
use crate::utils::{get_venv_python_bin, CommandOutput, IoPathContext};
use crate::utils::{get_venv_python_bin, prepend_path_to_path_env, CommandOutput, IoPathContext};
use crate::uv::UvBuilder;

/// Builds a package for distribution.
#[derive(Parser, Debug)]
Expand Down Expand Up @@ -44,7 +46,7 @@ pub struct Args {

pub fn execute(cmd: Args) -> Result<(), Error> {
let output = CommandOutput::from_quiet_and_verbose(cmd.quiet, cmd.verbose);
let venv = ensure_self_venv(output)?;
let self_venv = ensure_self_venv(output)?;
let project = PyProject::load_or_discover(cmd.pyproject.as_deref())?;

let out = match cmd.out {
Expand All @@ -61,6 +63,7 @@ pub fn execute(cmd: Args) -> Result<(), Error> {
}
}

let use_uv = Config::current().use_uv();
let projects = locate_projects(project, cmd.all, &cmd.package[..])?;

for project in projects {
Expand All @@ -75,21 +78,36 @@ pub fn execute(cmd: Args) -> Result<(), Error> {
style(project.normalized_name()?).cyan()
);

let mut build_cmd = Command::new(get_venv_python_bin(&venv));
let mut build_cmd = Command::new(get_venv_python_bin(&self_venv));
build_cmd
.arg("-mbuild")
.env("NO_COLOR", "1")
.arg("--outdir")
.arg(&out)
.arg(&*project.root_path());

if use_uv {
// we need to ensure uv is available to use without installing it into self_venv
let uv = UvBuilder::new().with_output(output).ensure_exists()?;
let uv_dir = uv
.uv_bin()
.parent()
.ok_or_else(|| anyhow!("Could not find uv binary in self venv: empty path"))?;
build_cmd.env("PATH", prepend_path_to_path_env(uv_dir)?);
build_cmd.arg("--installer=uv");
}

if cmd.wheel {
build_cmd.arg("--wheel");
}
if cmd.sdist {
build_cmd.arg("--sdist");
}

if output == CommandOutput::Verbose {
build_cmd.arg("--verbose");
}

if output == CommandOutput::Quiet {
build_cmd.stdout(Stdio::null());
build_cmd.stderr(Stdio::null());
Expand Down
11 changes: 11 additions & 0 deletions rye/src/utils/mod.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
use std::borrow::Cow;
use std::convert::Infallible;
use std::ffi::OsString;
use std::io::{Cursor, Read};
use std::path::{Path, PathBuf};
use std::process::{Command, ExitStatus, Stdio};
Expand Down Expand Up @@ -234,6 +235,16 @@ where
ENV_VAR_RE.replace_all(string, |m: &Captures| f(&m[1]).unwrap_or_default())
}

/// Prepend the given path to the current value of the $PATH environment variable
pub fn prepend_path_to_path_env(path: &Path) -> Result<OsString, Error> {
let mut paths = Vec::new();
paths.push(path.to_owned());
if let Some(existing_path) = std::env::var_os("PATH") {
paths.extend(std::env::split_paths(&existing_path));
}
Ok(std::env::join_paths(paths)?)
}

#[derive(Copy, Clone, Debug)]
enum ArchiveFormat {
TarGz,
Expand Down
7 changes: 7 additions & 0 deletions rye/src/uv.rs
Original file line number Diff line number Diff line change
Expand Up @@ -272,6 +272,13 @@ impl Uv {
}
}

/// Get uv binary path
///
/// Warning: Always use self.cmd() when at all possible
pub fn uv_bin(&self) -> &Path {
&self.uv_bin
}

fn create_venv(
&self,
venv_dir: &Path,
Expand Down

0 comments on commit c62d0f4

Please sign in to comment.