Add PEP 714 support for JSON API client (#3698)

## Summary

Closes https://github.com/astral-sh/uv/issues/3689.

## Test Plan

Manually verified we pick up `core-metadata` from PyPI if I remove the
aliases.
This commit is contained in:
Charlie Marsh 2024-05-21 11:52:37 -04:00 committed by GitHub
parent 95af1db0bb
commit 5205165d42
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
3 changed files with 44 additions and 7 deletions

View file

@ -44,8 +44,10 @@ impl File {
pub fn try_from(file: pypi_types::File, base: &Url) -> Result<Self, FileConversionError> { pub fn try_from(file: pypi_types::File, base: &Url) -> Result<Self, FileConversionError> {
Ok(Self { Ok(Self {
dist_info_metadata: file dist_info_metadata: file
.dist_info_metadata .core_metadata
.as_ref() .as_ref()
.or(file.dist_info_metadata.as_ref())
.or(file.data_dist_info_metadata.as_ref())
.is_some_and(DistInfoMetadata::is_available), .is_some_and(DistInfoMetadata::is_available),
filename: file.filename, filename: file.filename,
hashes: file.hashes.into_digests(), hashes: file.hashes.into_digests(),

View file

@ -37,14 +37,17 @@ fn sorted_simple_json_files<'de, D: Deserializer<'de>>(d: D) -> Result<Vec<File>
#[derive(Debug, Clone, Deserialize)] #[derive(Debug, Clone, Deserialize)]
#[serde(rename_all = "kebab-case")] #[serde(rename_all = "kebab-case")]
pub struct File { pub struct File {
// Non-PEP 691-compliant alias used by PyPI. // PEP 714-renamed field, followed by PEP 691-compliant field, followed by non-PEP 691-compliant
#[serde(alias = "data-dist-info-metadata")] // alias used by PyPI.
pub core_metadata: Option<DistInfoMetadata>,
pub dist_info_metadata: Option<DistInfoMetadata>, pub dist_info_metadata: Option<DistInfoMetadata>,
pub data_dist_info_metadata: Option<DistInfoMetadata>,
pub filename: String, pub filename: String,
pub hashes: Hashes, pub hashes: Hashes,
/// There are a number of invalid specifiers on pypi, so we first try to parse it into a [`VersionSpecifiers`] /// There are a number of invalid specifiers on PyPI, so we first try to parse it into a
/// according to spec (PEP 440), then a [`LenientVersionSpecifiers`] with fixup for some common problems and if this /// [`VersionSpecifiers`] according to spec (PEP 440), then a [`LenientVersionSpecifiers`] with
/// still fails, we skip the file when creating a version map. /// fixup for some common problems and if this still fails, we skip the file when creating a
/// version map.
#[serde(default, deserialize_with = "deserialize_version_specifiers_lenient")] #[serde(default, deserialize_with = "deserialize_version_specifiers_lenient")]
pub requires_python: Option<Result<VersionSpecifiers, VersionSpecifiersParseError>>, pub requires_python: Option<Result<VersionSpecifiers, VersionSpecifiersParseError>>,
pub size: Option<u64>, pub size: Option<u64>,

View file

@ -212,7 +212,9 @@ impl SimpleHtml {
}; };
Ok(File { Ok(File {
dist_info_metadata, core_metadata: dist_info_metadata,
dist_info_metadata: None,
data_dist_info_metadata: None,
yanked, yanked,
requires_python, requires_python,
hashes, hashes,
@ -298,7 +300,9 @@ mod tests {
), ),
files: [ files: [
File { File {
core_metadata: None,
dist_info_metadata: None, dist_info_metadata: None,
data_dist_info_metadata: None,
filename: "Jinja2-3.1.2-py3-none-any.whl", filename: "Jinja2-3.1.2-py3-none-any.whl",
hashes: Hashes { hashes: Hashes {
md5: None, md5: None,
@ -354,7 +358,9 @@ mod tests {
), ),
files: [ files: [
File { File {
core_metadata: None,
dist_info_metadata: None, dist_info_metadata: None,
data_dist_info_metadata: None,
filename: "Jinja2-3.1.2-py3-none-any.whl", filename: "Jinja2-3.1.2-py3-none-any.whl",
hashes: Hashes { hashes: Hashes {
md5: Some( md5: Some(
@ -413,7 +419,9 @@ mod tests {
), ),
files: [ files: [
File { File {
core_metadata: None,
dist_info_metadata: None, dist_info_metadata: None,
data_dist_info_metadata: None,
filename: "Jinja2-3.1.2-py3-none-any.whl", filename: "Jinja2-3.1.2-py3-none-any.whl",
hashes: Hashes { hashes: Hashes {
md5: None, md5: None,
@ -469,7 +477,9 @@ mod tests {
), ),
files: [ files: [
File { File {
core_metadata: None,
dist_info_metadata: None, dist_info_metadata: None,
data_dist_info_metadata: None,
filename: "Jinja2-3.1.2+233fca715f49-py3-none-any.whl", filename: "Jinja2-3.1.2+233fca715f49-py3-none-any.whl",
hashes: Hashes { hashes: Hashes {
md5: None, md5: None,
@ -525,7 +535,9 @@ mod tests {
), ),
files: [ files: [
File { File {
core_metadata: None,
dist_info_metadata: None, dist_info_metadata: None,
data_dist_info_metadata: None,
filename: "Jinja2-3.1.2-py3-none-any.whl", filename: "Jinja2-3.1.2-py3-none-any.whl",
hashes: Hashes { hashes: Hashes {
md5: None, md5: None,
@ -581,7 +593,9 @@ mod tests {
), ),
files: [ files: [
File { File {
core_metadata: None,
dist_info_metadata: None, dist_info_metadata: None,
data_dist_info_metadata: None,
filename: "torchtext-0.17.0+cpu-cp39-cp39-win_amd64.whl", filename: "torchtext-0.17.0+cpu-cp39-cp39-win_amd64.whl",
hashes: Hashes { hashes: Hashes {
md5: None, md5: None,
@ -635,7 +649,9 @@ mod tests {
), ),
files: [ files: [
File { File {
core_metadata: None,
dist_info_metadata: None, dist_info_metadata: None,
data_dist_info_metadata: None,
filename: "Jinja2-3.1.2-py3-none-any.whl", filename: "Jinja2-3.1.2-py3-none-any.whl",
hashes: Hashes { hashes: Hashes {
md5: None, md5: None,
@ -723,7 +739,9 @@ mod tests {
), ),
files: [ files: [
File { File {
core_metadata: None,
dist_info_metadata: None, dist_info_metadata: None,
data_dist_info_metadata: None,
filename: "Jinja2-3.1.2-py3-none-any.whl", filename: "Jinja2-3.1.2-py3-none-any.whl",
hashes: Hashes { hashes: Hashes {
md5: None, md5: None,
@ -777,7 +795,9 @@ mod tests {
), ),
files: [ files: [
File { File {
core_metadata: None,
dist_info_metadata: None, dist_info_metadata: None,
data_dist_info_metadata: None,
filename: "Jinja2-3.1.2-py3-none-any.whl", filename: "Jinja2-3.1.2-py3-none-any.whl",
hashes: Hashes { hashes: Hashes {
md5: None, md5: None,
@ -866,7 +886,9 @@ mod tests {
), ),
files: [ files: [
File { File {
core_metadata: None,
dist_info_metadata: None, dist_info_metadata: None,
data_dist_info_metadata: None,
filename: "jaxlib-0.1.52+cuda100-cp36-none-manylinux2010_x86_64.whl", filename: "jaxlib-0.1.52+cuda100-cp36-none-manylinux2010_x86_64.whl",
hashes: Hashes { hashes: Hashes {
md5: None, md5: None,
@ -881,7 +903,9 @@ mod tests {
yanked: None, yanked: None,
}, },
File { File {
core_metadata: None,
dist_info_metadata: None, dist_info_metadata: None,
data_dist_info_metadata: None,
filename: "jaxlib-0.1.52+cuda100-cp37-none-manylinux2010_x86_64.whl", filename: "jaxlib-0.1.52+cuda100-cp37-none-manylinux2010_x86_64.whl",
hashes: Hashes { hashes: Hashes {
md5: None, md5: None,
@ -945,7 +969,9 @@ mod tests {
), ),
files: [ files: [
File { File {
core_metadata: None,
dist_info_metadata: None, dist_info_metadata: None,
data_dist_info_metadata: None,
filename: "Flask-0.1.tar.gz", filename: "Flask-0.1.tar.gz",
hashes: Hashes { hashes: Hashes {
md5: None, md5: None,
@ -962,7 +988,9 @@ mod tests {
yanked: None, yanked: None,
}, },
File { File {
core_metadata: None,
dist_info_metadata: None, dist_info_metadata: None,
data_dist_info_metadata: None,
filename: "Flask-0.10.1.tar.gz", filename: "Flask-0.10.1.tar.gz",
hashes: Hashes { hashes: Hashes {
md5: None, md5: None,
@ -979,7 +1007,9 @@ mod tests {
yanked: None, yanked: None,
}, },
File { File {
core_metadata: None,
dist_info_metadata: None, dist_info_metadata: None,
data_dist_info_metadata: None,
filename: "flask-3.0.1.tar.gz", filename: "flask-3.0.1.tar.gz",
hashes: Hashes { hashes: Hashes {
md5: None, md5: None,
@ -1045,7 +1075,9 @@ mod tests {
), ),
files: [ files: [
File { File {
core_metadata: None,
dist_info_metadata: None, dist_info_metadata: None,
data_dist_info_metadata: None,
filename: "Jinja2-3.1.2-py3-none-any.whl", filename: "Jinja2-3.1.2-py3-none-any.whl",
hashes: Hashes { hashes: Hashes {
md5: None, md5: None,