Support using uv build-backend in the Python backend (#13049)

<!--
Thank you for contributing to uv! To help us out with reviewing, please
consider the following:

- Does this pull request include a summary of the change? (See below.)
- Does this pull request include a descriptive title?
- Does this pull request include references to any relevant issues?
-->

## Summary

Provide an in-code switch to permit using the `uv build-backend` command
rather than the default `uv-build` in the Python PEP517 backend. This
option is intended to be used by downstream packagers to provide an
option of reusing `uv` that was built already instead of having to build
a second `uv-build` executable that largely overlaps with `uv`.

Fixes #12389

## Test Plan

The option is intended for downstream consumption only, and it is tested
downstream (via attempting to build a package using the `uv_build`
backend). The backend itself is covered by tests already.

---------

Co-authored-by: konstin <konstin@mailbox.org>
This commit is contained in:
Michał Górny 2025-04-22 13:46:42 +02:00 committed by GitHub
parent 7807e64357
commit 41727cbc54
No known key found for this signature in database
GPG key ID: B5690EEEBB952194

View file

@ -21,6 +21,11 @@ if TYPE_CHECKING:
from collections.abc import Mapping, Sequence # noqa:I001
from typing import Any # noqa:I001
# Use the `uv build-backend` command rather than `uv-build`. This options is provided
# for downstream distributions who provide `uv` and wish to avoid building a partially
# overlapping `uv-build` executable.
USE_UV_EXECUTABLE = False
def warn_config_settings(config_settings: "Mapping[Any, Any] | None" = None) -> None:
import sys
@ -38,12 +43,17 @@ def call(
import sys
warn_config_settings(config_settings)
uv_bin_name = "uv" if USE_UV_EXECUTABLE else "uv-build"
# Unlike `find_uv_bin`, this mechanism must work according to PEP 517
uv_bin = shutil.which("uv-build")
uv_bin = shutil.which(uv_bin_name)
if uv_bin is None:
raise RuntimeError("uv was not properly installed")
raise RuntimeError(f"{uv_bin_name} was not properly installed")
build_backend_args = ["build-backend"] if USE_UV_EXECUTABLE else []
# Forward stderr, capture stdout for the filename
result = subprocess.run([uv_bin, *args], stdout=subprocess.PIPE)
result = subprocess.run(
[uv_bin, *build_backend_args, *args], stdout=subprocess.PIPE
)
if result.returncode != 0:
sys.exit(result.returncode)
# If there was extra stdout, forward it (there should not be extra stdout)
@ -51,7 +61,10 @@ def call(
sys.stdout.writelines(stdout[:-1])
# Fail explicitly instead of an irrelevant stacktrace
if not stdout:
print("uv subprocess did not return a filename on stdout", file=sys.stderr)
print(
f"{uv_bin_name} subprocess did not return a filename on stdout",
file=sys.stderr,
)
sys.exit(1)
return stdout[-1].strip()