Error when an explicit index is unnamed (#17777)

Since you cannot reference these indexes, I don't think we need a
warning and deprecation period.

Co-authored-by: Claude <noreply@anthropic.com>
This commit is contained in:
Zanie Blue
2026-01-31 09:54:17 -06:00
parent 3ba3fe355f
commit bd08ee3c4e
2 changed files with 95 additions and 1 deletions
+51 -1
View File
@@ -51,7 +51,7 @@ impl IndexCacheControl {
}
}
#[derive(Debug, Clone, Serialize, Deserialize)]
#[derive(Debug, Clone, Serialize)]
#[cfg_attr(feature = "schemars", derive(schemars::JsonSchema))]
#[serde(rename_all = "kebab-case")]
pub struct Index {
@@ -545,6 +545,56 @@ impl<'a> From<&'a IndexUrl> for IndexMetadataRef<'a> {
}
}
/// Wire type for deserializing an [`Index`] with validation.
#[derive(Deserialize)]
#[serde(rename_all = "kebab-case")]
struct IndexWire {
name: Option<IndexName>,
url: IndexUrl,
#[serde(default)]
explicit: bool,
#[serde(default)]
default: bool,
#[serde(default)]
format: IndexFormat,
publish_url: Option<DisplaySafeUrl>,
#[serde(default)]
authenticate: AuthPolicy,
#[serde(default)]
ignore_error_codes: Option<Vec<SerializableStatusCode>>,
#[serde(default)]
cache_control: Option<IndexCacheControl>,
}
impl<'de> Deserialize<'de> for Index {
fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
where
D: serde::Deserializer<'de>,
{
let wire = IndexWire::deserialize(deserializer)?;
if wire.explicit && wire.name.is_none() {
return Err(serde::de::Error::custom(format!(
"An index with `explicit = true` requires a `name`: {}",
wire.url
)));
}
Ok(Self {
name: wire.name,
url: wire.url,
explicit: wire.explicit,
default: wire.default,
origin: None,
format: wire.format,
publish_url: wire.publish_url,
authenticate: wire.authenticate,
ignore_error_codes: wire.ignore_error_codes,
cache_control: wire.cache_control,
})
}
}
/// An error that can occur when parsing an [`Index`].
#[derive(Error, Debug)]
pub enum IndexSourceError {
+44
View File
@@ -18910,6 +18910,50 @@ fn lock_explicit_default_index() -> Result<()> {
Ok(())
}
/// Error when an explicit index does not have a name.
#[test]
fn lock_unnamed_explicit_index() -> Result<()> {
let context = TestContext::new("3.12");
let pyproject_toml = context.temp_dir.child("pyproject.toml");
pyproject_toml.write_str(
r#"
[project]
name = "project"
version = "0.1.0"
requires-python = ">=3.12"
dependencies = ["iniconfig==2.0.0"]
[[tool.uv.index]]
url = "https://test.pypi.org/simple"
explicit = true
"#,
)?;
uv_snapshot!(context.filters(), context.lock(), @r#"
success: false
exit_code: 2
----- stdout -----
----- stderr -----
warning: Failed to parse `pyproject.toml` during settings discovery:
TOML parse error at line 8, column 9
|
8 | [[tool.uv.index]]
| ^^^^^^^^^^^^^^^^^
An index with `explicit = true` requires a `name`: https://test.pypi.org/simple
error: Failed to parse: `pyproject.toml`
Caused by: TOML parse error at line 8, column 9
|
8 | [[tool.uv.index]]
| ^^^^^^^^^^^^^^^^^
An index with `explicit = true` requires a `name`: https://test.pypi.org/simple
"#);
Ok(())
}
#[test]
fn lock_named_index() -> Result<()> {
let context = TestContext::new("3.12");