mirror of
https://github.com/astral-sh/uv.git
synced 2025-08-04 19:08:04 +00:00
Move PEP 440 and PEP 508 parsing out of TOML deserialization (#4176)
## Summary If we want more granular control over how these errors are handled, then we need to move them out of the TOML deserialization. No actual behavior changes here. Part of https://github.com/astral-sh/uv/issues/4142.
This commit is contained in:
parent
a761047df9
commit
72859d8f9b
3 changed files with 38 additions and 28 deletions
1
Cargo.lock
generated
1
Cargo.lock
generated
|
@ -2781,6 +2781,7 @@ dependencies = [
|
||||||
"anyhow",
|
"anyhow",
|
||||||
"chrono",
|
"chrono",
|
||||||
"indexmap",
|
"indexmap",
|
||||||
|
"itertools 0.13.0",
|
||||||
"mailparse",
|
"mailparse",
|
||||||
"once_cell",
|
"once_cell",
|
||||||
"pep440_rs",
|
"pep440_rs",
|
||||||
|
|
|
@ -20,6 +20,7 @@ uv-git = { workspace = true }
|
||||||
|
|
||||||
chrono = { workspace = true, features = ["serde"] }
|
chrono = { workspace = true, features = ["serde"] }
|
||||||
indexmap = { workspace = true, features = ["serde"] }
|
indexmap = { workspace = true, features = ["serde"] }
|
||||||
|
itertools = { workspace = true }
|
||||||
mailparse = { workspace = true }
|
mailparse = { workspace = true }
|
||||||
once_cell = { workspace = true }
|
once_cell = { workspace = true }
|
||||||
regex = { workspace = true }
|
regex = { workspace = true }
|
||||||
|
|
|
@ -3,6 +3,7 @@
|
||||||
use std::str::FromStr;
|
use std::str::FromStr;
|
||||||
|
|
||||||
use indexmap::IndexMap;
|
use indexmap::IndexMap;
|
||||||
|
use itertools::Itertools;
|
||||||
use mailparse::{MailHeaderMap, MailParseError};
|
use mailparse::{MailHeaderMap, MailParseError};
|
||||||
use serde::{Deserialize, Serialize};
|
use serde::{Deserialize, Serialize};
|
||||||
use thiserror::Error;
|
use thiserror::Error;
|
||||||
|
@ -86,16 +87,14 @@ impl Metadata23 {
|
||||||
.map_err(MetadataError::Pep440VersionError)?;
|
.map_err(MetadataError::Pep440VersionError)?;
|
||||||
let requires_dist = headers
|
let requires_dist = headers
|
||||||
.get_all_values("Requires-Dist")
|
.get_all_values("Requires-Dist")
|
||||||
.map(|requires_dist| {
|
.map(|requires_dist| LenientRequirement::from_str(&requires_dist))
|
||||||
LenientRequirement::from_str(&requires_dist).map(Requirement::from)
|
.map_ok(Requirement::from)
|
||||||
})
|
|
||||||
.collect::<Result<Vec<_>, _>>()?;
|
.collect::<Result<Vec<_>, _>>()?;
|
||||||
let requires_python = headers
|
let requires_python = headers
|
||||||
.get_first_value("Requires-Python")
|
.get_first_value("Requires-Python")
|
||||||
.map(|requires_python| {
|
.map(|requires_python| LenientVersionSpecifiers::from_str(&requires_python))
|
||||||
LenientVersionSpecifiers::from_str(&requires_python).map(VersionSpecifiers::from)
|
.transpose()?
|
||||||
})
|
.map(VersionSpecifiers::from);
|
||||||
.transpose()?;
|
|
||||||
let provides_extras = headers
|
let provides_extras = headers
|
||||||
.get_all_values("Provides-Extra")
|
.get_all_values("Provides-Extra")
|
||||||
.filter_map(|provides_extra| match ExtraName::new(provides_extra) {
|
.filter_map(|provides_extra| match ExtraName::new(provides_extra) {
|
||||||
|
@ -161,16 +160,14 @@ impl Metadata23 {
|
||||||
// The remaining fields are required to be present.
|
// The remaining fields are required to be present.
|
||||||
let requires_dist = headers
|
let requires_dist = headers
|
||||||
.get_all_values("Requires-Dist")
|
.get_all_values("Requires-Dist")
|
||||||
.map(|requires_dist| {
|
.map(|requires_dist| LenientRequirement::from_str(&requires_dist))
|
||||||
LenientRequirement::from_str(&requires_dist).map(Requirement::from)
|
.map_ok(Requirement::from)
|
||||||
})
|
|
||||||
.collect::<Result<Vec<_>, _>>()?;
|
.collect::<Result<Vec<_>, _>>()?;
|
||||||
let requires_python = headers
|
let requires_python = headers
|
||||||
.get_first_value("Requires-Python")
|
.get_first_value("Requires-Python")
|
||||||
.map(|requires_python| {
|
.map(|requires_python| LenientVersionSpecifiers::from_str(&requires_python))
|
||||||
LenientVersionSpecifiers::from_str(&requires_python).map(VersionSpecifiers::from)
|
.transpose()?
|
||||||
})
|
.map(VersionSpecifiers::from);
|
||||||
.transpose()?;
|
|
||||||
let provides_extras = headers
|
let provides_extras = headers
|
||||||
.get_all_values("Provides-Extra")
|
.get_all_values("Provides-Extra")
|
||||||
.filter_map(|provides_extra| match ExtraName::new(provides_extra) {
|
.filter_map(|provides_extra| match ExtraName::new(provides_extra) {
|
||||||
|
@ -217,15 +214,23 @@ impl Metadata23 {
|
||||||
let version = project
|
let version = project
|
||||||
.version
|
.version
|
||||||
.ok_or(MetadataError::FieldNotFound("version"))?;
|
.ok_or(MetadataError::FieldNotFound("version"))?;
|
||||||
let requires_python = project.requires_python.map(VersionSpecifiers::from);
|
|
||||||
|
// Parse the Python version requirements.
|
||||||
|
let requires_python = project
|
||||||
|
.requires_python
|
||||||
|
.map(|requires_python| {
|
||||||
|
LenientVersionSpecifiers::from_str(&requires_python).map(VersionSpecifiers::from)
|
||||||
|
})
|
||||||
|
.transpose()?;
|
||||||
|
|
||||||
// Extract the requirements.
|
// Extract the requirements.
|
||||||
let mut requires_dist = project
|
let mut requires_dist = project
|
||||||
.dependencies
|
.dependencies
|
||||||
.unwrap_or_default()
|
.unwrap_or_default()
|
||||||
.into_iter()
|
.into_iter()
|
||||||
.map(Requirement::from)
|
.map(|requires_dist| LenientRequirement::from_str(&requires_dist))
|
||||||
.collect::<Vec<_>>();
|
.map_ok(Requirement::from)
|
||||||
|
.collect::<Result<Vec<_>, _>>()?;
|
||||||
|
|
||||||
// Extract the optional dependencies.
|
// Extract the optional dependencies.
|
||||||
let mut provides_extras: Vec<ExtraName> = Vec::new();
|
let mut provides_extras: Vec<ExtraName> = Vec::new();
|
||||||
|
@ -233,9 +238,10 @@ impl Metadata23 {
|
||||||
requires_dist.extend(
|
requires_dist.extend(
|
||||||
requirements
|
requirements
|
||||||
.into_iter()
|
.into_iter()
|
||||||
.map(Requirement::from)
|
.map(|requires_dist| LenientRequirement::from_str(&requires_dist))
|
||||||
.map(|requirement| requirement.with_extra_marker(&extra))
|
.map_ok(Requirement::from)
|
||||||
.collect::<Vec<_>>(),
|
.map_ok(|requirement| requirement.with_extra_marker(&extra))
|
||||||
|
.collect::<Result<Vec<_>, _>>()?,
|
||||||
);
|
);
|
||||||
provides_extras.push(extra);
|
provides_extras.push(extra);
|
||||||
}
|
}
|
||||||
|
@ -272,11 +278,11 @@ struct Project {
|
||||||
/// The version of the project as supported by PEP 440
|
/// The version of the project as supported by PEP 440
|
||||||
version: Option<Version>,
|
version: Option<Version>,
|
||||||
/// The Python version requirements of the project
|
/// The Python version requirements of the project
|
||||||
requires_python: Option<LenientVersionSpecifiers>,
|
requires_python: Option<String>,
|
||||||
/// Project dependencies
|
/// Project dependencies
|
||||||
dependencies: Option<Vec<LenientRequirement>>,
|
dependencies: Option<Vec<String>>,
|
||||||
/// Optional dependencies
|
/// Optional dependencies
|
||||||
optional_dependencies: Option<IndexMap<ExtraName, Vec<LenientRequirement>>>,
|
optional_dependencies: Option<IndexMap<ExtraName, Vec<String>>>,
|
||||||
/// Specifies which fields listed by PEP 621 were intentionally unspecified
|
/// Specifies which fields listed by PEP 621 were intentionally unspecified
|
||||||
/// so another tool can/will provide such metadata dynamically.
|
/// so another tool can/will provide such metadata dynamically.
|
||||||
dynamic: Option<Vec<String>>,
|
dynamic: Option<Vec<String>>,
|
||||||
|
@ -370,8 +376,9 @@ impl RequiresDist {
|
||||||
.dependencies
|
.dependencies
|
||||||
.unwrap_or_default()
|
.unwrap_or_default()
|
||||||
.into_iter()
|
.into_iter()
|
||||||
.map(Requirement::from)
|
.map(|requires_dist| LenientRequirement::from_str(&requires_dist))
|
||||||
.collect::<Vec<_>>();
|
.map_ok(Requirement::from)
|
||||||
|
.collect::<Result<Vec<_>, _>>()?;
|
||||||
|
|
||||||
// Extract the optional dependencies.
|
// Extract the optional dependencies.
|
||||||
let mut provides_extras: Vec<ExtraName> = Vec::new();
|
let mut provides_extras: Vec<ExtraName> = Vec::new();
|
||||||
|
@ -379,9 +386,10 @@ impl RequiresDist {
|
||||||
requires_dist.extend(
|
requires_dist.extend(
|
||||||
requirements
|
requirements
|
||||||
.into_iter()
|
.into_iter()
|
||||||
.map(Requirement::from)
|
.map(|requires_dist| LenientRequirement::from_str(&requires_dist))
|
||||||
.map(|requirement| requirement.with_extra_marker(&extra))
|
.map_ok(Requirement::from)
|
||||||
.collect::<Vec<_>>(),
|
.map_ok(|requirement| requirement.with_extra_marker(&extra))
|
||||||
|
.collect::<Result<Vec<_>, _>>()?,
|
||||||
);
|
);
|
||||||
provides_extras.push(extra);
|
provides_extras.push(extra);
|
||||||
}
|
}
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue