mirror of
https://github.com/astral-sh/uv.git
synced 2025-09-27 04:29:10 +00:00
Remove RFC2047 decoder (#967)
## Summary - This was inherited fromd719988323/src/metadata.rs (LL78C2-L91C26)
- ...which introduced this code here:9cd1d43f7c
- ...with the originating issue here: https://github.com/PyO3/maturin/issues/612 - ...and the upstream issue here: https://github.com/staktrace/mailparse/issues/50 It seems like the goal was to support Unicode in certain header fields, but I don't think this is necessary for us. We only use `get_first_value` for `Requires-Python`, which has to be ASCII, doesn't it? In my testing, it seems like the `charset` hack can also be removed. The tests I copied over actually work without it, which makes me a bit skeptical. The main benefit here is that we get to a remove a _big_ dependency stack, including Chumsky and Stacker and psm which have limited cross-platform support.
This commit is contained in:
parent
f17bad0a75
commit
96a61fb351
4 changed files with 59 additions and 106 deletions
91
Cargo.lock
generated
91
Cargo.lock
generated
|
@ -26,18 +26,6 @@ dependencies = [
|
||||||
"const-random",
|
"const-random",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "ahash"
|
|
||||||
version = "0.8.7"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "77c3a9648d43b9cd48db467b3f87fdd6e146bcc88ab0180006cef2179fe11d01"
|
|
||||||
dependencies = [
|
|
||||||
"cfg-if 1.0.0",
|
|
||||||
"once_cell",
|
|
||||||
"version_check",
|
|
||||||
"zerocopy",
|
|
||||||
]
|
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "aho-corasick"
|
name = "aho-corasick"
|
||||||
version = "1.1.2"
|
version = "1.1.2"
|
||||||
|
@ -62,12 +50,6 @@ dependencies = [
|
||||||
"alloc-no-stdlib",
|
"alloc-no-stdlib",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "allocator-api2"
|
|
||||||
version = "0.2.16"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "0942ffc6dcaadf03badf6e6a2d0228460359d5e34b57ccdc720b7382dfbd5ec5"
|
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "android-tzdata"
|
name = "android-tzdata"
|
||||||
version = "0.1.1"
|
version = "0.1.1"
|
||||||
|
@ -480,16 +462,6 @@ dependencies = [
|
||||||
"windows-targets 0.48.5",
|
"windows-targets 0.48.5",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "chumsky"
|
|
||||||
version = "0.9.3"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "8eebd66744a15ded14960ab4ccdbfb51ad3b81f51f3f04a80adac98c985396c9"
|
|
||||||
dependencies = [
|
|
||||||
"hashbrown 0.14.3",
|
|
||||||
"stacker",
|
|
||||||
]
|
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "ciborium"
|
name = "ciborium"
|
||||||
version = "0.2.1"
|
version = "0.2.1"
|
||||||
|
@ -747,7 +719,7 @@ version = "3.11.10"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "0f260e2fc850179ef410018660006951c1b55b79e8087e87111a2c388994b9b5"
|
checksum = "0f260e2fc850179ef410018660006951c1b55b79e8087e87111a2c388994b9b5"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"ahash 0.3.8",
|
"ahash",
|
||||||
"cfg-if 0.1.10",
|
"cfg-if 0.1.10",
|
||||||
"num_cpus",
|
"num_cpus",
|
||||||
]
|
]
|
||||||
|
@ -1233,10 +1205,6 @@ name = "hashbrown"
|
||||||
version = "0.14.3"
|
version = "0.14.3"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "290f1a1d9242c78d09ce40a5e87e7554ee637af1351968159f4952f028f75604"
|
checksum = "290f1a1d9242c78d09ce40a5e87e7554ee637af1351968159f4952f028f75604"
|
||||||
dependencies = [
|
|
||||||
"ahash 0.8.7",
|
|
||||||
"allocator-api2",
|
|
||||||
]
|
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "heck"
|
name = "heck"
|
||||||
|
@ -2272,15 +2240,6 @@ dependencies = [
|
||||||
"unicode-ident",
|
"unicode-ident",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "psm"
|
|
||||||
version = "0.1.21"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "5787f7cda34e3033a72192c018bc5883100330f362ef279a8cbccfce8bb4e874"
|
|
||||||
dependencies = [
|
|
||||||
"cc",
|
|
||||||
]
|
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "pubgrub"
|
name = "pubgrub"
|
||||||
version = "0.2.1"
|
version = "0.2.1"
|
||||||
|
@ -2842,7 +2801,6 @@ dependencies = [
|
||||||
"pep508_rs",
|
"pep508_rs",
|
||||||
"puffin-normalize",
|
"puffin-normalize",
|
||||||
"regex",
|
"regex",
|
||||||
"rfc2047-decoder",
|
|
||||||
"serde",
|
"serde",
|
||||||
"serde_json",
|
"serde_json",
|
||||||
"tempfile",
|
"tempfile",
|
||||||
|
@ -3139,20 +3097,6 @@ dependencies = [
|
||||||
"rand",
|
"rand",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "rfc2047-decoder"
|
|
||||||
version = "1.0.2"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "9e372613f15fc5171f9052b0c1fbafca5b1e5b0ba86aa13c9c39fd91ca1f7955"
|
|
||||||
dependencies = [
|
|
||||||
"base64 0.21.7",
|
|
||||||
"charset",
|
|
||||||
"chumsky",
|
|
||||||
"memchr",
|
|
||||||
"quoted_printable",
|
|
||||||
"thiserror",
|
|
||||||
]
|
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "ring"
|
name = "ring"
|
||||||
version = "0.17.7"
|
version = "0.17.7"
|
||||||
|
@ -3438,19 +3382,6 @@ version = "0.9.8"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "6980e8d7511241f8acf4aebddbb1ff938df5eebe98691418c4468d0b72a96a67"
|
checksum = "6980e8d7511241f8acf4aebddbb1ff938df5eebe98691418c4468d0b72a96a67"
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "stacker"
|
|
||||||
version = "0.1.15"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "c886bd4480155fd3ef527d45e9ac8dd7118a898a46530b7b94c3e21866259fce"
|
|
||||||
dependencies = [
|
|
||||||
"cc",
|
|
||||||
"cfg-if 1.0.0",
|
|
||||||
"libc",
|
|
||||||
"psm",
|
|
||||||
"winapi",
|
|
||||||
]
|
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "strsim"
|
name = "strsim"
|
||||||
version = "0.10.0"
|
version = "0.10.0"
|
||||||
|
@ -4506,26 +4437,6 @@ dependencies = [
|
||||||
"linked-hash-map",
|
"linked-hash-map",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "zerocopy"
|
|
||||||
version = "0.7.32"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "74d4d3961e53fa4c9a25a8637fc2bfaf2595b3d3ae34875568a5cf64787716be"
|
|
||||||
dependencies = [
|
|
||||||
"zerocopy-derive",
|
|
||||||
]
|
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "zerocopy-derive"
|
|
||||||
version = "0.7.32"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "9ce1b18ccd8e73a9321186f97e46f9f04b778851177567b1975109d26a08d2a6"
|
|
||||||
dependencies = [
|
|
||||||
"proc-macro2",
|
|
||||||
"quote",
|
|
||||||
"syn 2.0.48",
|
|
||||||
]
|
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "zip"
|
name = "zip"
|
||||||
version = "0.6.6"
|
version = "0.6.6"
|
||||||
|
|
|
@ -67,7 +67,6 @@ regex = { version = "1.10.2" }
|
||||||
reqwest = { version = "0.11.23", default-features = false, features = ["json", "gzip", "brotli", "stream", "rustls-tls"] }
|
reqwest = { version = "0.11.23", default-features = false, features = ["json", "gzip", "brotli", "stream", "rustls-tls"] }
|
||||||
reqwest-middleware = { version = "0.2.4" }
|
reqwest-middleware = { version = "0.2.4" }
|
||||||
reqwest-retry = { version = "0.3.0" }
|
reqwest-retry = { version = "0.3.0" }
|
||||||
rfc2047-decoder = { version = "1.0.2" }
|
|
||||||
rmp-serde = { version = "1.1.2" }
|
rmp-serde = { version = "1.1.2" }
|
||||||
rustc-hash = { version = "1.1.0" }
|
rustc-hash = { version = "1.1.0" }
|
||||||
seahash = { version = "4.1.0" }
|
seahash = { version = "4.1.0" }
|
||||||
|
|
|
@ -21,7 +21,6 @@ chrono = { workspace = true, features = ["serde"] }
|
||||||
mailparse = { workspace = true }
|
mailparse = { workspace = true }
|
||||||
once_cell = { workspace = true }
|
once_cell = { workspace = true }
|
||||||
regex = { workspace = true }
|
regex = { workspace = true }
|
||||||
rfc2047-decoder = { workspace = true }
|
|
||||||
serde = { workspace = true }
|
serde = { workspace = true }
|
||||||
thiserror = { workspace = true }
|
thiserror = { workspace = true }
|
||||||
tracing = { workspace = true }
|
tracing = { workspace = true }
|
||||||
|
|
|
@ -75,24 +75,16 @@ pub enum Error {
|
||||||
impl Metadata21 {
|
impl Metadata21 {
|
||||||
/// Parse distribution metadata from metadata bytes
|
/// Parse distribution metadata from metadata bytes
|
||||||
pub fn parse(content: &[u8]) -> Result<Self, Error> {
|
pub fn parse(content: &[u8]) -> Result<Self, Error> {
|
||||||
// HACK: trick mailparse to parse as UTF-8 instead of ASCII
|
let msg = mailparse::parse_mail(content)?;
|
||||||
let mut mail = b"Content-Type: text/plain; charset=utf-8\n".to_vec();
|
|
||||||
mail.extend_from_slice(content);
|
|
||||||
|
|
||||||
let msg = mailparse::parse_mail(&mail)?;
|
|
||||||
let headers = msg.get_headers();
|
let headers = msg.get_headers();
|
||||||
|
|
||||||
let get_first_value = |name| {
|
let get_first_value = |name| {
|
||||||
headers.get_first_header(name).and_then(|header| {
|
headers.get_first_header(name).and_then(|header| {
|
||||||
match rfc2047_decoder::decode(header.get_value_raw()) {
|
let value = header.get_value();
|
||||||
Ok(value) => {
|
if value == "UNKNOWN" {
|
||||||
if value == "UNKNOWN" {
|
None
|
||||||
None
|
} else {
|
||||||
} else {
|
Some(value)
|
||||||
Some(value)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
Err(_) => None,
|
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
};
|
};
|
||||||
|
@ -141,3 +133,55 @@ impl Metadata21 {
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl FromStr for Metadata21 {
|
||||||
|
type Err = Error;
|
||||||
|
fn from_str(s: &str) -> Result<Self, Self::Err> {
|
||||||
|
Metadata21::parse(s.as_bytes())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[cfg(test)]
|
||||||
|
mod tests {
|
||||||
|
use std::str::FromStr;
|
||||||
|
|
||||||
|
use pep440_rs::Version;
|
||||||
|
use puffin_normalize::PackageName;
|
||||||
|
|
||||||
|
use crate::Error;
|
||||||
|
|
||||||
|
use super::Metadata21;
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_parse_from_str() {
|
||||||
|
let s = "Metadata-Version: 1.0";
|
||||||
|
let meta: Result<Metadata21, Error> = s.parse();
|
||||||
|
assert!(matches!(meta, Err(Error::FieldNotFound("Name"))));
|
||||||
|
|
||||||
|
let s = "Metadata-Version: 1.0\nName: asdf";
|
||||||
|
let meta = Metadata21::parse(s.as_bytes());
|
||||||
|
assert!(matches!(meta, Err(Error::FieldNotFound("Version"))));
|
||||||
|
|
||||||
|
let s = "Metadata-Version: 1.0\nName: asdf\nVersion: 1.0";
|
||||||
|
let meta = Metadata21::parse(s.as_bytes()).unwrap();
|
||||||
|
assert_eq!(meta.metadata_version, "1.0");
|
||||||
|
assert_eq!(meta.name, PackageName::from_str("asdf").unwrap());
|
||||||
|
assert_eq!(meta.version, Version::new([1, 0]));
|
||||||
|
|
||||||
|
let s = "Metadata-Version: 1.0\nName: asdf\nVersion: 1.0\nAuthor: 中文\n\n一个 Python 包";
|
||||||
|
let meta = Metadata21::parse(s.as_bytes()).unwrap();
|
||||||
|
assert_eq!(meta.metadata_version, "1.0");
|
||||||
|
assert_eq!(meta.name, PackageName::from_str("asdf").unwrap());
|
||||||
|
assert_eq!(meta.version, Version::new([1, 0]));
|
||||||
|
|
||||||
|
let s = "Metadata-Version: 1.0\nName: =?utf-8?q?foobar?=\nVersion: 1.0";
|
||||||
|
let meta = Metadata21::parse(s.as_bytes()).unwrap();
|
||||||
|
assert_eq!(meta.metadata_version, "1.0");
|
||||||
|
assert_eq!(meta.name, PackageName::from_str("foobar").unwrap());
|
||||||
|
assert_eq!(meta.version, Version::new([1, 0]));
|
||||||
|
|
||||||
|
let s = "Metadata-Version: 1.0\nName: =?utf-8?q?=C3=A4_space?= <x@y.org>\nVersion: 1.0";
|
||||||
|
let meta = Metadata21::parse(s.as_bytes());
|
||||||
|
assert!(matches!(meta, Err(Error::InvalidName(_))));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue