diff --git a/Cargo.lock b/Cargo.lock index 88b2ffbf6..a987cef6d 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1266,6 +1266,7 @@ dependencies = [ "multipart", "native-tls", "once_cell", + "pep440", "platform-info", "pretty_env_logger", "pyproject-toml", @@ -1629,6 +1630,16 @@ version = "0.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "c54014ba3c1880122928735226f78b6f5bf5bd1fed15e41e92cf7aa20278ce28" +[[package]] +name = "pep440" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8841b00ca6fabc903e8ecd496d9611db402e23f15e3d19b0b587e2ca653abd89" +dependencies = [ + "lazy_static", + "regex", +] + [[package]] name = "percent-encoding" version = "2.1.0" diff --git a/Cargo.toml b/Cargo.toml index bd8bfd105..ce402abac 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -60,6 +60,10 @@ cc = "1.0.72" clap = { version = "3.2.16", features = ["derive", "env", "wrap_help"] } clap_complete = "3.1.3" clap_complete_fig = "3.1.0" +tracing = "0.1.36" +dunce = "1.0.2" +pep440 = "0.2.0" + # upload bytesize = { version = "1.0.1", optional = true } configparser = { version = "3.0.0", optional = true } @@ -67,8 +71,6 @@ multipart = { version = "0.18.0", features = ["client"], default-features = fals rpassword = { version = "7.0.0", optional = true } ureq = { version = "2.3.1", features = ["gzip", "socks-proxy"], default-features = false, optional = true } native-tls-crate = { package = "native-tls", version = "0.2.8", optional = true } -tracing = "0.1.36" -dunce = "1.0.2" [dev-dependencies] indoc = "1.0.3" diff --git a/Changelog.md b/Changelog.md index 682137822..f53683322 100644 --- a/Changelog.md +++ b/Changelog.md @@ -11,6 +11,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 * Add Linux mipsel architecture support in [#1024](https://github.com/PyO3/maturin/pull/1024) * Add Linux 32-bit powerpc architecture support in [#1026](https://github.com/PyO3/maturin/pull/1026) * Add Linux sparc64 architecture support in [#1027](https://github.com/PyO3/maturin/pull/1027) +* Add PEP 440 local version identifier support in [#1037](https://github.com/PyO3/maturin/pull/1037) ## [0.13.1] - 2022-07-26 diff --git a/src/metadata.rs b/src/metadata.rs index ae727fc4f..f00dd519c 100644 --- a/src/metadata.rs +++ b/src/metadata.rs @@ -408,7 +408,7 @@ impl Metadata21 { let mut fields = vec![ ("Metadata-Version", self.metadata_version.clone()), ("Name", self.name.clone()), - ("Version", self.get_version_escaped()), + ("Version", self.get_pep440_version()), ]; let mut add_vec = |name, values: &[String]| { @@ -505,8 +505,21 @@ impl Metadata21 { /// Returns the version encoded according to PEP 427, Section "Escaping /// and Unicode" pub fn get_version_escaped(&self) -> String { - let re = Regex::new(r"[^\w\d.]+").unwrap(); - re.replace_all(&self.version, "_").to_string() + self.get_pep440_version().replace('-', "_") + } + + /// Returns the version encoded according to PEP 440 + /// + /// See https://github.com/pypa/setuptools/blob/d90cf84e4890036adae403d25c8bb4ee97841bbf/pkg_resources/__init__.py#L1336-L1345 + pub fn get_pep440_version(&self) -> String { + match pep440::Version::parse(&self.version) { + Some(ver) => ver.normalize(), + None => { + let ver = self.version.replace(' ', "."); + let re = Regex::new(r"[^A-Za-z0-9.]+").unwrap(); + re.replace_all(&ver, "-").to_string() + } + } } /// Returns the name of the .dist-info directory as defined in the wheel specification diff --git a/test-crates/pyo3-pure/pyproject.toml b/test-crates/pyo3-pure/pyproject.toml index 23275d848..4575ddf92 100644 --- a/test-crates/pyo3-pure/pyproject.toml +++ b/test-crates/pyo3-pure/pyproject.toml @@ -7,6 +7,7 @@ bindings = "pyo3" [project] name = "pyo3-pure" +version = "0.1.0+abc123de" classifiers = [ "Programming Language :: Rust" ]