From ecfa38608864f99cdb887edc97632fc3ed352fc3 Mon Sep 17 00:00:00 2001 From: Charlie Marsh Date: Mon, 21 Jul 2025 18:15:03 -0400 Subject: [PATCH] Error on unknown fields in `dependency-metadata` (#14801) ## Summary Closes https://github.com/astral-sh/uv/issues/14800. --- .../src/dependency_metadata.rs | 24 ++++++------- crates/uv/tests/it/lock.rs | 36 +++++++++++++++++++ crates/uv/tests/it/sync.rs | 6 ++-- uv.schema.json | 1 + 4 files changed, 52 insertions(+), 15 deletions(-) diff --git a/crates/uv-distribution-types/src/dependency_metadata.rs b/crates/uv-distribution-types/src/dependency_metadata.rs index ccda34795..1e978db3d 100644 --- a/crates/uv-distribution-types/src/dependency_metadata.rs +++ b/crates/uv-distribution-types/src/dependency_metadata.rs @@ -30,21 +30,20 @@ impl DependencyMetadata { if let Some(version) = version { // If a specific version was requested, search for an exact match, then a global match. - let metadata = versions + let metadata = if let Some(metadata) = versions .iter() - .find(|v| v.version.as_ref() == Some(version)) - .inspect(|_| { - debug!("Found dependency metadata entry for `{package}=={version}`"); - }) - .or_else(|| versions.iter().find(|v| v.version.is_none())) - .inspect(|_| { - debug!("Found global metadata entry for `{package}`"); - }); - let Some(metadata) = metadata else { + .find(|entry| entry.version.as_ref() == Some(version)) + { + debug!("Found dependency metadata entry for `{package}=={version}`"); + metadata + } else if let Some(metadata) = versions.iter().find(|entry| entry.version.is_none()) { + debug!("Found global metadata entry for `{package}`"); + metadata + } else { warn!("No dependency metadata entry found for `{package}=={version}`"); return None; }; - debug!("Found dependency metadata entry for `{package}=={version}`"); + Some(ResolutionMetadata { name: metadata.name.clone(), version: version.clone(), @@ -65,6 +64,7 @@ impl DependencyMetadata { return None; }; debug!("Found dependency metadata entry for `{package}` (assuming: `{version}`)"); + Some(ResolutionMetadata { name: metadata.name.clone(), version, @@ -86,7 +86,7 @@ impl DependencyMetadata { /// . #[derive(Serialize, Deserialize, Debug, Clone, PartialEq, Eq, PartialOrd, Ord)] #[cfg_attr(feature = "schemars", derive(schemars::JsonSchema))] -#[serde(rename_all = "kebab-case")] +#[serde(rename_all = "kebab-case", deny_unknown_fields)] pub struct StaticMetadata { // Mandatory fields pub name: PackageName, diff --git a/crates/uv/tests/it/lock.rs b/crates/uv/tests/it/lock.rs index 0962ff6d2..f4ccb7bf7 100644 --- a/crates/uv/tests/it/lock.rs +++ b/crates/uv/tests/it/lock.rs @@ -18597,6 +18597,42 @@ fn lock_dependency_metadata() -> Result<()> { Removed sniffio v1.3.1 "###); + // Update the static metadata. + pyproject_toml.write_str( + r#" + [project] + name = "project" + version = "0.1.0" + requires-python = ">=3.12" + dependencies = ["anyio==3.7.0"] + + [[tool.uv.dependency-metadata]] + name = "anyio" + version = "3.7.0" + requires_dist = ["typing-extensions"] + "#, + )?; + + // The operation should warn. + uv_snapshot!(context.filters(), context.lock(), @r#" + success: true + exit_code: 0 + ----- stdout ----- + + ----- stderr ----- + warning: Failed to parse `pyproject.toml` during settings discovery: + TOML parse error at line 11, column 9 + | + 11 | requires_dist = ["typing-extensions"] + | ^^^^^^^^^^^^^ + unknown field `requires_dist`, expected one of `name`, `version`, `requires-dist`, `requires-python`, `provides-extras` + + Resolved 4 packages in [TIME] + Added idna v3.6 + Removed iniconfig v2.0.0 + Added sniffio v1.3.1 + "#); + Ok(()) } diff --git a/crates/uv/tests/it/sync.rs b/crates/uv/tests/it/sync.rs index 1639ecaae..4f2853e61 100644 --- a/crates/uv/tests/it/sync.rs +++ b/crates/uv/tests/it/sync.rs @@ -7560,7 +7560,7 @@ fn sync_derivation_chain() -> Result<()> { [[tool.uv.dependency-metadata]] name = "wsgiref" version = "0.1.2" - dependencies = [] + requires-dist = [] "#, )?; @@ -7623,7 +7623,7 @@ fn sync_derivation_chain_extra() -> Result<()> { [[tool.uv.dependency-metadata]] name = "wsgiref" version = "0.1.2" - dependencies = [] + requires-dist = [] "#, )?; @@ -7688,7 +7688,7 @@ fn sync_derivation_chain_group() -> Result<()> { [[tool.uv.dependency-metadata]] name = "wsgiref" version = "0.1.2" - dependencies = [] + requires-dist = [] "#, )?; diff --git a/uv.schema.json b/uv.schema.json index 22b30cd06..d8346aab1 100644 --- a/uv.schema.json +++ b/uv.schema.json @@ -2104,6 +2104,7 @@ ] } }, + "additionalProperties": false, "required": [ "name" ]