diff --git a/src/metadata.rs b/src/metadata.rs index a620c9cee..874cbb7ff 100644 --- a/src/metadata.rs +++ b/src/metadata.rs @@ -44,6 +44,8 @@ pub struct Metadata21 { pub maintainer: Option, pub maintainer_email: Option, pub license: Option, + // https://peps.python.org/pep-0639/#license-file-multiple-use + pub license_files: Vec, pub classifiers: Vec, pub requires_dist: Vec, pub provides_dist: Vec, @@ -144,10 +146,7 @@ impl Metadata21 { } if let Some(license_path) = file { let license_path = manifest_path.join(license_path); - self.license = Some(fs::read_to_string(&license_path).context(format!( - "Failed to read license file specified in pyproject.toml, which should be at {}", - license_path.display() - ))?); + self.license_files.push(license_path); } if let Some(license_text) = text { self.license = Some(license_text.clone()); @@ -351,6 +350,7 @@ impl Metadata21 { author: authors, author_email, license: cargo_toml.package.license.clone(), + license_files: Vec::new(), // Values provided through `[project.metadata.maturin]` classifiers, @@ -404,6 +404,13 @@ impl Metadata21 { add_vec("Requires-External", &self.requires_external); add_vec("Provides-Extra", &self.provides_extra); + let license_files: Vec = self + .license_files + .iter() + .map(|path| path.file_name().unwrap().to_str().unwrap().to_string()) + .collect(); + add_vec("License-File", &license_files); + let mut add_option = |name, value: &Option| { if let Some(some) = value.clone() { fields.push((name, some)); @@ -791,33 +798,14 @@ mod test { "boltons; (sys_platform == 'win32') and extra == 'test'" ] ); + assert_eq!(metadata.license.as_ref().unwrap(), "MIT"); + + let license_file = &metadata.license_files[0]; + assert_eq!(license_file.file_name().unwrap(), "LICENSE"); let content = metadata.to_file_contents(); let pkginfo: Result = content.parse(); assert!(pkginfo.is_ok()); - - let license = metadata - .to_vec() - .into_iter() - .filter_map(|(key, val)| { - if key.starts_with("License") { - Some(val) - } else { - None - } - }) - .next() - .unwrap(); - let mut lines = license.split_inclusive('\n'); - assert_eq!( - lines.next().unwrap(), - "Copyright (c) 2018-present konstin\r\n" - ); - assert_eq!(lines.next().unwrap(), "\t\r\n"); - assert_eq!( - lines.next().unwrap(), - "\tPermission is hereby granted, free of charge, to any\r\n" - ); } #[test] diff --git a/src/module_writer.rs b/src/module_writer.rs index bcbc65a94..2782a3cd3 100644 --- a/src/module_writer.rs +++ b/src/module_writer.rs @@ -833,5 +833,14 @@ pub fn write_dist_info( )?; } + if !metadata21.license_files.is_empty() { + for path in &metadata21.license_files { + let filename = path.file_name().with_context(|| { + format!("missing file name for license file {}", path.display()) + })?; + writer.add_file(dist_info_dir.join(filename), path)?; + } + } + Ok(()) } diff --git a/test-crates/pyo3-pure/Cargo.toml b/test-crates/pyo3-pure/Cargo.toml index 6e828b12c..dacec5f8e 100644 --- a/test-crates/pyo3-pure/Cargo.toml +++ b/test-crates/pyo3-pure/Cargo.toml @@ -4,6 +4,7 @@ name = "pyo3-pure" version = "2.1.2" edition = "2018" description = "Implements a dummy function (get_fortytwo.DummyClass.get_42()) in rust" +license = "MIT" [dependencies] pyo3 = { version = "0.15.1", features = ["abi3-py36", "extension-module"] }