Skip to content

Commit

Permalink
Allow per dependency build isolation for setup.py projects as well (#…
Browse files Browse the repository at this point in the history
…6517)

<!--
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

<!-- What's the purpose of the change? What does it do, and why? -->

This changes the behavior a bit of the per-dependency build-isolation
override. That, if the dist name is known, it is passed into the
`SourceBuild::Setup` function. This allows for this override to work for
projects without a `pyproject.toml`, like `detectron2`, using the
specified requirement name. Previously only the `pyproject.toml` name
could be used, which these projects are lacking. An example of a
use-case is given in the *Test Plan* section.

Additionally, the `no_build_isolation_package` has been adding to
`InstallerSettingsRef` and used in `sync` and other commands, as this
was not done yet.

This is useful if you want to **non**-isolate a single package, even
ones without a proper `pyproject.toml`


## Test Plan

<!-- How was it tested? -->

With the following pyproject.toml.

```toml
[project]
name = "detectron-uv"
version = "0.1.0"
description = "Add your description here"
readme = "README.md"
requires-python = ">=3.12"
dependencies = [
    "detectron2",
    "setuptools",
    "torch",
]

[build-system]
requires = ["hatchling"]
build-backend = "hatchling.build"

[tool.uv.sources]
detectron2 = { git = "https://github.com/facebookresearch/detectron2", rev = "bcfd464d0c810f0442d91a349c0f6df945467143" }

[tool.uv]
no-build-isolation-package = ["detectron2"]
```

The package `detectron2` is now correctly **non**-isolated. Before,
because the logic depended on getting the name from the
`pyproject.toml`, which is lacking in detectron2 you would get the
message, that the source could not be built. This was because it would
still be *isolated* in that case.

With these changes you can now install using (given that you are inside
a workspace with a venv):

```
uv pip install torch setuptools
uv sync
```

This would previously fail with something like:

```
error: Failed to prepare distributions
  Caused by: Failed to fetch wheel: detectron2 @ git+https://github.com/facebookresearch/detectron2@bcfd464d0c810f0442d91a349c0f6df945467143
  Caused by: Build backend failed to determine extra requires with `build_wheel()` with exit status: 1
--- stdout:

--- stderr:
Traceback (most recent call last):
  File "<string>", line 14, in <module>
  File "/Users/tdejager/Library/Caches/uv/builds-v0/.tmptloDcZ/lib/python3.12/site-packages/setuptools/build_meta.py", line 332, in get_requires_for_build_wheel
    return self._get_build_requires(config_settings, requirements=[])
           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/Users/tdejager/Library/Caches/uv/builds-v0/.tmptloDcZ/lib/python3.12/site-packages/setuptools/build_meta.py", line 302, in _get_build_requires
    self.run_setup()
  File "/Users/tdejager/Library/Caches/uv/builds-v0/.tmptloDcZ/lib/python3.12/site-packages/setuptools/build_meta.py", line 502, in run_setup
    super().run_setup(setup_script=setup_script)
  File "/Users/tdejager/Library/Caches/uv/builds-v0/.tmptloDcZ/lib/python3.12/site-packages/setuptools/build_meta.py", line 318, in run_setup
    exec(code, locals())
  File "<string>", line 10, in <module>
ModuleNotFoundError: No module named 'torch'
---
  Caused by: This error likely indicates that detectron2 @ git+https://github.com/facebookresearch/detectron2@bcfd464d0c810f0442d91a349c0f6df945467143 depends on torch, but doesn't declare it as a build dependency. If detectron2 @ git+https://github.com/facebookresearch/detectron2@bcfd464d0c810f0442d91a349c0f6df945467143 is a first-party package, consider adding torch to its `build-system.requires`. Otherwise, `uv pip install torch` into the environment and re-run with `--no-build-isolation`.
  ```

**Edit**:

Some wording, used isolated where it should be **non**-isolated.
  • Loading branch information
tdejager committed Aug 26, 2024
1 parent b68406b commit 50997bc
Show file tree
Hide file tree
Showing 3 changed files with 9 additions and 5 deletions.
9 changes: 5 additions & 4 deletions crates/uv-build/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -398,6 +398,7 @@ impl SourceBuild {
pub async fn setup(
source: &Path,
subdirectory: Option<&Path>,
fallback_package_name: Option<&PackageName>,
interpreter: &Interpreter,
build_context: &impl BuildContext,
source_build_context: SourceBuildContext,
Expand All @@ -422,10 +423,10 @@ impl SourceBuild {
let (pep517_backend, project) =
Self::extract_pep517_backend(&source_tree, &default_backend).map_err(|err| *err)?;

let package_name = project.clone().map(|p| p.name);
let package_name = project.as_ref().map(|p| &p.name).or(fallback_package_name);

// Create a virtual environment, or install into the shared environment if requested.
let venv = if let Some(venv) = build_isolation.shared_environment(package_name.as_ref()) {
let venv = if let Some(venv) = build_isolation.shared_environment(package_name) {
venv.clone()
} else {
uv_virtualenv::create_venv(
Expand All @@ -440,7 +441,7 @@ impl SourceBuild {

// Setup the build environment. If build isolation is disabled, we assume the build
// environment is already setup.
if build_isolation.is_isolated(package_name.as_ref()) {
if build_isolation.is_isolated(package_name) {
let resolved_requirements = Self::get_resolved_requirements(
build_context,
source_build_context,
Expand Down Expand Up @@ -490,7 +491,7 @@ impl SourceBuild {
// Create the PEP 517 build environment. If build isolation is disabled, we assume the build
// environment is already setup.
let runner = PythonRunner::new(concurrent_builds);
if build_isolation.is_isolated(package_name.as_ref()) {
if build_isolation.is_isolated(package_name) {
create_pep517_build_environment(
&runner,
&source_tree,
Expand Down
1 change: 1 addition & 0 deletions crates/uv-dev/src/build.rs
Original file line number Diff line number Diff line change
Expand Up @@ -98,6 +98,7 @@ pub(crate) async fn build(args: BuildArgs) -> Result<PathBuf> {
let builder = SourceBuild::setup(
&args.sdist,
args.subdirectory.as_deref(),
None,
python.interpreter(),
&build_dispatch,
SourceBuildContext::default(),
Expand Down
4 changes: 3 additions & 1 deletion crates/uv-dispatch/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -298,11 +298,12 @@ impl<'a> BuildContext for BuildDispatch<'a> {
dist: Option<&'data SourceDist>,
build_kind: BuildKind,
) -> Result<SourceBuild> {
let dist_name = dist.map(distribution_types::Name::name);
// Note we can only prevent builds by name for packages with names
// unless all builds are disabled.
if self
.build_options
.no_build_requirement(dist.map(distribution_types::Name::name))
.no_build_requirement(dist_name)
// We always allow editable builds
&& !matches!(build_kind, BuildKind::Editable)
{
Expand All @@ -318,6 +319,7 @@ impl<'a> BuildContext for BuildDispatch<'a> {
let builder = SourceBuild::setup(
source,
subdirectory,
dist_name,
self.interpreter,
self,
self.source_build_context.clone(),
Expand Down

0 comments on commit 50997bc

Please sign in to comment.