metadata_directory already contains dist-info directory (#10005)

From PEP 517:

```python
def prepare_metadata_for_build_wheel(metadata_directory, config_settings=None):
    ...
```

> Must create a .dist-info directory containing wheel metadata inside
the specified metadata_directory (i.e., creates a directory like
{metadata_directory}/{package}-{version}.dist-info/).

```python
def build_wheel(wheel_directory, config_settings=None, metadata_directory=None):
    ...
```

> If the build frontend has previously called
prepare_metadata_for_build_wheel and depends on the wheel resulting from
this call to have metadata matching this earlier call, then it should
provide the path to the created .dist-info directory as the
metadata_directory argument.

Notice that the `metadata_directory` is different for the both hooks:
For `prepare_metadata_for_build_wheel` is doesn't contain the
`.dist-info` directory as final segment, for `build_wheel` it does.

Previously, the code assumed that both directories didn't contain the
`.dist-info` for both cases.

Checked with:

```
maturin build
uv init test-uv-build-backend --build-backend uv
cd test-uv-build-backend
uv build --sdist --preview
cd ..
UV_PREVIEW=1 pip install test-uv-build-backend/dist/test_uv_build_backend-0.1.0.tar.gz --no-index --find-links target/wheels/ -v --no-cache-dir
```

Fixes #9969
This commit is contained in:
konsti 2024-12-18 20:14:08 +01:00 committed by GitHub
parent 9305badcaf
commit cb325e2e2f
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
2 changed files with 71 additions and 10 deletions

View file

@ -11,6 +11,7 @@ use std::fs::FileType;
use std::io;
use std::path::{Path, PathBuf, StripPrefixError};
use thiserror::Error;
use tracing::debug;
use uv_fs::Simplified;
use uv_globfilter::PortableGlobError;
@ -139,26 +140,22 @@ fn check_metadata_directory(
return Ok(());
};
let dist_info_dir = format!(
"{}-{}.dist-info",
pyproject_toml.name().as_dist_info_name(),
pyproject_toml.version()
debug!(
"Checking metadata directory {}",
metadata_directory.user_display()
);
// `METADATA` is a mandatory file.
let current = pyproject_toml
.to_metadata(source_tree)?
.core_metadata_format();
let previous =
fs_err::read_to_string(metadata_directory.join(&dist_info_dir).join("METADATA"))?;
let previous = fs_err::read_to_string(metadata_directory.join("METADATA"))?;
if previous != current {
return Err(Error::InconsistentSteps("METADATA"));
}
// `entry_points.txt` is not written if it would be empty.
let entrypoints_path = metadata_directory
.join(&dist_info_dir)
.join("entry_points.txt");
let entrypoints_path = metadata_directory.join("entry_points.txt");
match pyproject_toml.to_entry_points()? {
None => {
if entrypoints_path.is_file() {
@ -461,4 +458,68 @@ mod tests {
Sincerely, the authors
"###);
}
/// Test that `build_wheel` works after the `prepare_metadata_for_build_wheel` hook.
#[test]
fn prepare_metadata_then_build_wheel() {
let src = TempDir::new().unwrap();
fs_err::write(
src.path().join("pyproject.toml"),
indoc! {r#"
[project]
name = "two-step-build"
version = "1.0.0"
[build-system]
requires = ["uv>=0.5.15,<0.6"]
build-backend = "uv"
"#
},
)
.unwrap();
fs_err::create_dir_all(src.path().join("src").join("two_step_build")).unwrap();
File::create(
src.path()
.join("src")
.join("two_step_build")
.join("__init__.py"),
)
.unwrap();
// Prepare the metadata.
let metadata_dir = TempDir::new().unwrap();
let dist_info_dir = metadata(src.path(), metadata_dir.path(), "0.5.15").unwrap();
let metadata_prepared =
fs_err::read_to_string(metadata_dir.path().join(&dist_info_dir).join("METADATA"))
.unwrap();
// Build the wheel, using the prepared metadata directory.
let output_dir = TempDir::new().unwrap();
build_wheel(
src.path(),
output_dir.path(),
Some(&metadata_dir.path().join(&dist_info_dir)),
"0.5.15",
)
.unwrap();
let wheel = output_dir
.path()
.join("two_step_build-1.0.0-py3-none-any.whl");
let mut wheel = zip::ZipArchive::new(File::open(wheel).unwrap()).unwrap();
let mut metadata_wheel = String::new();
wheel
.by_name("two_step_build-1.0.0.dist-info/METADATA")
.unwrap()
.read_to_string(&mut metadata_wheel)
.unwrap();
assert_eq!(metadata_prepared, metadata_wheel);
assert_snapshot!(metadata_wheel, @r###"
Metadata-Version: 2.3
Name: two-step-build
Version: 1.0.0
"###);
}
}