From fee344db6fec72d7d5aa9eef03a7d76cb48d4c37 Mon Sep 17 00:00:00 2001 From: Charlie Marsh Date: Tue, 21 May 2024 14:05:40 -0400 Subject: [PATCH] Add PEP 714 support for HTML API client (#3697) ## Summary If `data-core-metadata` is set, we need to respect that over `data-dist-info-metadata` in the HTML client. See: https://github.com/astral-sh/uv/issues/3689 --- crates/uv-client/src/html.rs | 167 +++++++++++++++++++++++++++++++++-- 1 file changed, 160 insertions(+), 7 deletions(-) diff --git a/crates/uv-client/src/html.rs b/crates/uv-client/src/html.rs index 571c35e5b..5a17998ac 100644 --- a/crates/uv-client/src/html.rs +++ b/crates/uv-client/src/html.rs @@ -185,10 +185,14 @@ impl SimpleHtml { None }; - // Extract the `data-dist-info-metadata` field, which should be set on - // the `data-dist-info-metadata` attribute. - let dist_info_metadata = if let Some(dist_info_metadata) = - link.attributes().get("data-dist-info-metadata").flatten() + // Extract the `core-metadata` field, which is either set on: + // - `data-core-metadata`, per PEP 714. + // - `data-dist-info-metadata`, per PEP 658. + let core_metadata = if let Some(dist_info_metadata) = link + .attributes() + .get("data-core-metadata") + .flatten() + .or_else(|| link.attributes().get("data-dist-info-metadata").flatten()) { let dist_info_metadata = std::str::from_utf8(dist_info_metadata.as_bytes())?; let dist_info_metadata = html_escape::decode_html_entities(dist_info_metadata); @@ -212,7 +216,7 @@ impl SimpleHtml { }; Ok(File { - core_metadata: dist_info_metadata, + core_metadata, dist_info_metadata: None, data_dist_info_metadata: None, yanked, @@ -936,9 +940,9 @@ mod tests {

Links for flask

- Flask-0.1.tar.gz + Flask-0.1.tar.gz
- Flask-0.10.1.tar.gz + Flask-0.10.1.tar.gz
flask-3.0.1.tar.gz
@@ -1108,4 +1112,153 @@ mod tests { } "###); } + + /// Respect PEP 714 (see: ). + #[test] + fn parse_core_metadata() { + let text = r#" + + + +

Links for jinja2

+ Jinja2-3.1.2-py3-none-any.whl
+ Jinja2-3.1.3-py3-none-any.whl
+ Jinja2-3.1.4-py3-none-any.whl
+ Jinja2-3.1.5-py3-none-any.whl
+ Jinja2-3.1.6-py3-none-any.whl
+ + + "#; + let base = Url::parse("https://account.d.codeartifact.us-west-2.amazonaws.com/pypi/shared-packages-pypi/simple/flask/") + .unwrap(); + let result = SimpleHtml::parse(text, &base).unwrap(); + insta::assert_debug_snapshot!(result, @r###" + SimpleHtml { + base: BaseUrl( + Url { + scheme: "https", + cannot_be_a_base: false, + username: "", + password: None, + host: Some( + Domain( + "account.d.codeartifact.us-west-2.amazonaws.com", + ), + ), + port: None, + path: "/pypi/shared-packages-pypi/simple/flask/", + query: None, + fragment: None, + }, + ), + files: [ + File { + core_metadata: Some( + Bool( + true, + ), + ), + dist_info_metadata: None, + data_dist_info_metadata: None, + filename: "Jinja2-3.1.2-py3-none-any.whl", + hashes: Hashes { + md5: None, + sha256: None, + sha384: None, + sha512: None, + }, + requires_python: None, + size: None, + upload_time: None, + url: "/whl/Jinja2-3.1.2-py3-none-any.whl", + yanked: None, + }, + File { + core_metadata: Some( + Bool( + true, + ), + ), + dist_info_metadata: None, + data_dist_info_metadata: None, + filename: "Jinja2-3.1.3-py3-none-any.whl", + hashes: Hashes { + md5: None, + sha256: None, + sha384: None, + sha512: None, + }, + requires_python: None, + size: None, + upload_time: None, + url: "/whl/Jinja2-3.1.3-py3-none-any.whl", + yanked: None, + }, + File { + core_metadata: Some( + Bool( + false, + ), + ), + dist_info_metadata: None, + data_dist_info_metadata: None, + filename: "Jinja2-3.1.4-py3-none-any.whl", + hashes: Hashes { + md5: None, + sha256: None, + sha384: None, + sha512: None, + }, + requires_python: None, + size: None, + upload_time: None, + url: "/whl/Jinja2-3.1.4-py3-none-any.whl", + yanked: None, + }, + File { + core_metadata: Some( + Bool( + false, + ), + ), + dist_info_metadata: None, + data_dist_info_metadata: None, + filename: "Jinja2-3.1.5-py3-none-any.whl", + hashes: Hashes { + md5: None, + sha256: None, + sha384: None, + sha512: None, + }, + requires_python: None, + size: None, + upload_time: None, + url: "/whl/Jinja2-3.1.5-py3-none-any.whl", + yanked: None, + }, + File { + core_metadata: Some( + Bool( + true, + ), + ), + dist_info_metadata: None, + data_dist_info_metadata: None, + filename: "Jinja2-3.1.6-py3-none-any.whl", + hashes: Hashes { + md5: None, + sha256: None, + sha384: None, + sha512: None, + }, + requires_python: None, + size: None, + upload_time: None, + url: "/whl/Jinja2-3.1.6-py3-none-any.whl", + yanked: None, + }, + ], + } + "###); + } }