use {
anyhow::Result,
python_packaging::{
module_util::{packages_from_module_name, resolve_path_for_module},
resource::{
PythonExtensionModule, PythonModuleSource, PythonPackageDistributionResource,
PythonPackageResource,
},
},
simple_file_manifest::{FileEntry, FileManifest},
};
pub trait AddToFileManifest {
fn add_to_file_manifest(&self, manifest: &mut FileManifest, prefix: &str) -> Result<()>;
}
impl AddToFileManifest for PythonModuleSource {
fn add_to_file_manifest(&self, manifest: &mut FileManifest, prefix: &str) -> Result<()> {
let content = self.source.resolve_content()?;
manifest.add_file_entry(&self.resolve_path(prefix), content)?;
for package in packages_from_module_name(&self.name) {
let package_path = resolve_path_for_module(prefix, &package, true, None);
if !manifest.has_path(&package_path) {
manifest.add_file_entry(&package_path, vec![])?;
}
}
Ok(())
}
}
impl AddToFileManifest for PythonPackageResource {
fn add_to_file_manifest(&self, manifest: &mut FileManifest, prefix: &str) -> Result<()> {
let dest_path = self.resolve_path(prefix);
manifest.add_file_entry(&dest_path, self.data.resolve_content()?)?;
Ok(())
}
}
impl AddToFileManifest for PythonPackageDistributionResource {
fn add_to_file_manifest(&self, manifest: &mut FileManifest, prefix: &str) -> Result<()> {
let dest_path = self.resolve_path(prefix);
manifest.add_file_entry(&dest_path, self.data.resolve_content()?)?;
Ok(())
}
}
impl AddToFileManifest for PythonExtensionModule {
fn add_to_file_manifest(&self, manifest: &mut FileManifest, prefix: &str) -> Result<()> {
if let Some(data) = &self.shared_library {
manifest.add_file_entry(
&self.resolve_path(prefix),
FileEntry::new_from_data(data.resolve_content()?, true),
)?;
}
Ok(())
}
}
#[cfg(test)]
mod tests {
use {super::*, itertools::Itertools, simple_file_manifest::FileData, std::path::PathBuf};
const DEFAULT_CACHE_TAG: &str = "cpython-39";
#[test]
fn test_source_module_add_to_manifest_top_level() -> Result<()> {
let mut m = FileManifest::default();
PythonModuleSource {
name: "foo".to_string(),
source: FileData::Memory(vec![]),
is_package: false,
cache_tag: DEFAULT_CACHE_TAG.to_string(),
is_stdlib: false,
is_test: false,
}
.add_to_file_manifest(&mut m, ".")?;
PythonModuleSource {
name: "bar".to_string(),
source: FileData::Memory(vec![]),
is_package: false,
cache_tag: DEFAULT_CACHE_TAG.to_string(),
is_stdlib: false,
is_test: false,
}
.add_to_file_manifest(&mut m, ".")?;
let entries = m.iter_entries().collect_vec();
assert_eq!(entries.len(), 2);
assert_eq!(entries[0].0, &PathBuf::from("./bar.py"));
assert_eq!(entries[1].0, &PathBuf::from("./foo.py"));
Ok(())
}
#[test]
fn test_source_module_add_to_manifest_top_level_package() -> Result<()> {
let mut m = FileManifest::default();
PythonModuleSource {
name: "foo".to_string(),
source: FileData::Memory(vec![]),
is_package: true,
cache_tag: DEFAULT_CACHE_TAG.to_string(),
is_stdlib: false,
is_test: false,
}
.add_to_file_manifest(&mut m, ".")?;
let entries = m.iter_entries().collect_vec();
assert_eq!(entries.len(), 1);
assert_eq!(entries[0].0, &PathBuf::from("./foo/__init__.py"));
Ok(())
}
#[test]
fn test_source_module_add_to_manifest_missing_parent() -> Result<()> {
let mut m = FileManifest::default();
PythonModuleSource {
name: "root.parent.child".to_string(),
source: FileData::Memory(vec![]),
is_package: false,
cache_tag: DEFAULT_CACHE_TAG.to_string(),
is_stdlib: false,
is_test: false,
}
.add_to_file_manifest(&mut m, ".")?;
let entries = m.iter_entries().collect_vec();
assert_eq!(entries.len(), 3);
assert_eq!(entries[0].0, &PathBuf::from("./root/__init__.py"));
assert_eq!(entries[1].0, &PathBuf::from("./root/parent/__init__.py"));
assert_eq!(entries[2].0, &PathBuf::from("./root/parent/child.py"));
Ok(())
}
#[test]
fn test_source_module_add_to_manifest_missing_parent_package() -> Result<()> {
let mut m = FileManifest::default();
PythonModuleSource {
name: "root.parent.child".to_string(),
source: FileData::Memory(vec![]),
is_package: true,
cache_tag: DEFAULT_CACHE_TAG.to_string(),
is_stdlib: false,
is_test: false,
}
.add_to_file_manifest(&mut m, ".")?;
let entries = m.iter_entries().collect_vec();
assert_eq!(entries.len(), 3);
assert_eq!(entries[0].0, &PathBuf::from("./root/__init__.py"));
assert_eq!(entries[1].0, &PathBuf::from("./root/parent/__init__.py"));
assert_eq!(
entries[2].0,
&PathBuf::from("./root/parent/child/__init__.py")
);
Ok(())
}
}