Respect subdirectories when reading static metadata (#2728)

## Summary

This was just an oversight (and a lack of test coverage).

Closes https://github.com/astral-sh/uv/issues/2727.
This commit is contained in:
Charlie Marsh 2024-03-29 22:36:10 -04:00 committed by GitHub
parent 1f31350d46
commit ff6aea3f5c
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
2 changed files with 46 additions and 6 deletions

View file

@ -956,7 +956,7 @@ impl<'a, T: BuildContext> SourceDistCachedBuilder<'a, T> {
debug!("Preparing metadata for: {source}");
// Attempt to read static metadata from the `PKG-INFO` file.
match read_pkg_info(source_root).await {
match read_pkg_info(source_root, subdirectory).await {
Ok(metadata) => {
debug!("Found static `PKG-INFO` for: {source}");
@ -979,7 +979,7 @@ impl<'a, T: BuildContext> SourceDistCachedBuilder<'a, T> {
}
// Attempt to read static metadata from the `pyproject.toml`.
match read_pyproject_toml(source_root).await {
match read_pyproject_toml(source_root, subdirectory).await {
Ok(metadata) => {
debug!("Found static `pyproject.toml` for: {source}");
@ -1112,9 +1112,16 @@ impl ExtractedSource {
/// Read the [`Metadata23`] from a source distribution's `PKG-INFO` file, if it uses Metadata 2.2
/// or later _and_ none of the required fields (`Requires-Python`, `Requires-Dist`, and
/// `Provides-Extra`) are marked as dynamic.
pub(crate) async fn read_pkg_info(source_tree: &Path) -> Result<Metadata23, Error> {
pub(crate) async fn read_pkg_info(
source_tree: &Path,
subdirectory: Option<&Path>,
) -> Result<Metadata23, Error> {
// Read the `PKG-INFO` file.
let content = match fs::read(source_tree.join("PKG-INFO")).await {
let pkg_info = match subdirectory {
Some(subdirectory) => source_tree.join(subdirectory).join("PKG-INFO"),
None => source_tree.join("PKG-INFO"),
};
let content = match fs::read(pkg_info).await {
Ok(content) => content,
Err(err) if err.kind() == std::io::ErrorKind::NotFound => {
return Err(Error::MissingPkgInfo);
@ -1130,9 +1137,16 @@ pub(crate) async fn read_pkg_info(source_tree: &Path) -> Result<Metadata23, Erro
/// Read the [`Metadata23`] from a source distribution's `pyproject.tom` file, if it defines static
/// metadata consistent with PEP 621.
pub(crate) async fn read_pyproject_toml(source_tree: &Path) -> Result<Metadata23, Error> {
pub(crate) async fn read_pyproject_toml(
source_tree: &Path,
subdirectory: Option<&Path>,
) -> Result<Metadata23, Error> {
// Read the `pyproject.toml` file.
let content = match fs::read_to_string(source_tree.join("pyproject.toml")).await {
let pyproject_toml = match subdirectory {
Some(subdirectory) => source_tree.join(subdirectory).join("pyproject.toml"),
None => source_tree.join("pyproject.toml"),
};
let content = match fs::read_to_string(pyproject_toml).await {
Ok(content) => content,
Err(err) if err.kind() == std::io::ErrorKind::NotFound => {
return Err(Error::MissingPyprojectToml);

View file

@ -1378,6 +1378,32 @@ fn compile_git_mismatched_name() -> Result<()> {
Ok(())
}
/// Resolve a specific Git dependency with a subdirectory, where the root directory contains a
/// static `pyproject.toml` file.
#[test]
fn compile_git_subdirectory_static_metadata() -> Result<()> {
let context = TestContext::new("3.12");
let requirements_in = context.temp_dir.child("requirements.in");
requirements_in.write_str("uv-public-pypackage @ git+https://github.com/astral-test/uv-workspace-pypackage#subdirectory=uv-public-pypackage")?;
uv_snapshot!(context.compile()
.arg("requirements.in"), @r###"
success: true
exit_code: 0
----- stdout -----
# This file was autogenerated by uv via the following command:
# uv pip compile --cache-dir [CACHE_DIR] --exclude-newer 2024-03-25T00:00:00Z requirements.in
uv-public-pypackage @ git+https://github.com/astral-test/uv-workspace-pypackage#subdirectory=uv-public-pypackage@b8c4e192456d736c27f2c84c61175c896dba8373
----- stderr -----
Resolved 1 package in [TIME]
"###
);
Ok(())
}
/// Request Flask, but include a URL dependency for Werkzeug, which should avoid adding a
/// duplicate dependency from `PyPI`.
#[test]