use {
crate::{
environment::Environment,
py_packaging::{distribution::AppleSdkInfo, embedding::EmbeddedPythonContext},
},
anyhow::Result,
python_packaging::{
licensing::{LicensedComponent, LicensedComponents},
policy::PythonPackagingPolicy,
resource::{
PythonExtensionModule, PythonModuleSource, PythonPackageDistributionResource,
PythonPackageResource, PythonResource,
},
resource_collection::{
AddResourceAction, PrePackagedResource, PythonResourceAddCollectionContext,
},
},
simple_file_manifest::File,
std::{collections::HashMap, path::Path, sync::Arc},
tugger_windows::VcRedistributablePlatform,
};
#[derive(Clone, Copy, Debug, PartialEq, Eq)]
pub enum LibpythonLinkMode {
Static,
Dynamic,
}
#[derive(Clone, Debug, PartialEq, Eq)]
pub enum PackedResourcesLoadMode {
None,
EmbeddedInBinary(String),
BinaryRelativePathMemoryMapped(String),
}
impl ToString for PackedResourcesLoadMode {
fn to_string(&self) -> String {
match self {
Self::None => "none".to_string(),
Self::EmbeddedInBinary(filename) => format!("embedded:{}", filename),
Self::BinaryRelativePathMemoryMapped(path) => {
format!("binary-relative-memory-mapped:{}", path)
}
}
}
}
impl TryFrom<&str> for PackedResourcesLoadMode {
type Error = String;
fn try_from(value: &str) -> Result<Self, Self::Error> {
if value == "none" {
Ok(Self::None)
} else {
let parts = value.splitn(2, ':').collect::<Vec<_>>();
if parts.len() != 2 {
Err(
"resources load mode value not recognized; must have form `type:value`"
.to_string(),
)
} else {
let prefix = parts[0];
let value = parts[1];
match prefix {
"embedded" => {
Ok(Self::EmbeddedInBinary(value.to_string()))
}
"binary-relative-memory-mapped" => {
Ok(Self::BinaryRelativePathMemoryMapped(value.to_string()))
}
_ => Err(format!("{} is not a valid prefix; must be 'embedded' or 'binary-relative-memory-mapped'", prefix))
}
}
}
}
}
#[derive(Clone, Copy, Debug, PartialEq, Eq)]
pub enum WindowsRuntimeDllsMode {
Never,
WhenPresent,
Always,
}
impl ToString for WindowsRuntimeDllsMode {
fn to_string(&self) -> String {
match self {
Self::Never => "never",
Self::WhenPresent => "when-present",
Self::Always => "always",
}
.to_string()
}
}
impl TryFrom<&str> for WindowsRuntimeDllsMode {
type Error = String;
fn try_from(value: &str) -> Result<Self, Self::Error> {
match value {
"never" => Ok(Self::Never),
"when-present" => Ok(Self::WhenPresent),
"always" => Ok(Self::Always),
_ => Err(format!("{} is not a valid mode; must be 'never'", value)),
}
}
}
pub type ResourceAddCollectionContextCallback<'a> = Box<
dyn Fn(
&PythonPackagingPolicy,
&PythonResource,
&mut PythonResourceAddCollectionContext,
) -> Result<()>
+ 'a,
>;
pub trait PythonBinaryBuilder {
fn clone_trait(&self) -> Arc<dyn PythonBinaryBuilder>;
fn name(&self) -> String;
fn libpython_link_mode(&self) -> LibpythonLinkMode;
fn target_triple(&self) -> &str;
fn vc_runtime_requirements(&self) -> Option<(String, VcRedistributablePlatform)>;
fn cache_tag(&self) -> &str;
fn python_packaging_policy(&self) -> &PythonPackagingPolicy;
fn host_python_exe_path(&self) -> &Path;
fn target_python_exe_path(&self) -> &Path;
fn apple_sdk_info(&self) -> Option<&AppleSdkInfo>;
fn windows_runtime_dlls_mode(&self) -> &WindowsRuntimeDllsMode;
fn set_windows_runtime_dlls_mode(&mut self, value: WindowsRuntimeDllsMode);
fn tcl_files_path(&self) -> &Option<String>;
fn set_tcl_files_path(&mut self, value: Option<String>);
fn windows_subsystem(&self) -> &str;
fn set_windows_subsystem(&mut self, value: &str) -> Result<()>;
fn licenses_filename(&self) -> Option<&str>;
fn set_licenses_filename(&mut self, value: Option<String>);
fn packed_resources_load_mode(&self) -> &PackedResourcesLoadMode;
fn set_packed_resources_load_mode(&mut self, load_mode: PackedResourcesLoadMode);
fn iter_resources<'a>(
&'a self,
) -> Box<dyn Iterator<Item = (&'a String, &'a PrePackagedResource)> + 'a>;
fn index_package_license_info_from_resources<'a>(
&mut self,
resources: &[PythonResource<'a>],
) -> Result<()>;
fn pip_download(
&mut self,
env: &Environment,
verbose: bool,
args: &[String],
) -> Result<Vec<PythonResource>>;
fn pip_install(
&mut self,
env: &Environment,
verbose: bool,
install_args: &[String],
extra_envs: &HashMap<String, String>,
) -> Result<Vec<PythonResource>>;
fn read_package_root(
&mut self,
path: &Path,
packages: &[String],
) -> Result<Vec<PythonResource>>;
fn read_virtualenv(&mut self, path: &Path) -> Result<Vec<PythonResource>>;
fn setup_py_install(
&mut self,
env: &Environment,
package_path: &Path,
verbose: bool,
extra_envs: &HashMap<String, String>,
extra_global_arguments: &[String],
) -> Result<Vec<PythonResource>>;
fn add_distribution_resources(
&mut self,
callback: Option<ResourceAddCollectionContextCallback>,
) -> Result<Vec<AddResourceAction>>;
fn add_python_module_source(
&mut self,
module: &PythonModuleSource,
add_context: Option<PythonResourceAddCollectionContext>,
) -> Result<Vec<AddResourceAction>>;
fn add_python_package_resource(
&mut self,
resource: &PythonPackageResource,
add_context: Option<PythonResourceAddCollectionContext>,
) -> Result<Vec<AddResourceAction>>;
fn add_python_package_distribution_resource(
&mut self,
resource: &PythonPackageDistributionResource,
add_context: Option<PythonResourceAddCollectionContext>,
) -> Result<Vec<AddResourceAction>>;
fn add_python_extension_module(
&mut self,
extension_module: &PythonExtensionModule,
add_context: Option<PythonResourceAddCollectionContext>,
) -> Result<Vec<AddResourceAction>>;
fn add_file_data(
&mut self,
file: &File,
add_context: Option<PythonResourceAddCollectionContext>,
) -> Result<Vec<AddResourceAction>>;
fn filter_resources_from_files(
&mut self,
files: &[&Path],
glob_patterns: &[&str],
) -> Result<()>;
fn requires_jemalloc(&self) -> bool;
fn requires_mimalloc(&self) -> bool;
fn requires_snmalloc(&self) -> bool;
fn licensed_components(&self) -> Result<LicensedComponents>;
fn add_licensed_component(&mut self, component: LicensedComponent) -> Result<()>;
fn to_embedded_python_context(
&self,
env: &Environment,
opt_level: &str,
) -> Result<EmbeddedPythonContext>;
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_resources_load_mode_serialization() {
assert_eq!(
PackedResourcesLoadMode::None.to_string(),
"none".to_string()
);
assert_eq!(
PackedResourcesLoadMode::EmbeddedInBinary("resources".into()).to_string(),
"embedded:resources".to_string()
);
assert_eq!(
PackedResourcesLoadMode::BinaryRelativePathMemoryMapped("relative-resources".into())
.to_string(),
"binary-relative-memory-mapped:relative-resources".to_string()
);
}
#[test]
fn test_resources_load_mode_parsing() -> Result<()> {
assert_eq!(
PackedResourcesLoadMode::try_from("none").unwrap(),
PackedResourcesLoadMode::None
);
assert_eq!(
PackedResourcesLoadMode::try_from("embedded:resources").unwrap(),
PackedResourcesLoadMode::EmbeddedInBinary("resources".into())
);
assert_eq!(
PackedResourcesLoadMode::try_from("binary-relative-memory-mapped:relative").unwrap(),
PackedResourcesLoadMode::BinaryRelativePathMemoryMapped("relative".into())
);
Ok(())
}
}