rez_next_package/
lib.rs

1//! # Rez Core Package
2//!
3//! Package system implementation for Rez Core.
4//!
5//! This crate provides:
6//! - Package definition and metadata
7//! - Package variants and requirements
8//! - Package serialization/deserialization
9//! - Package validation
10//! - Package management operations
11
12pub mod package;
13pub mod python_ast_parser;
14pub mod serialization; // Always available for CLI usage // Advanced Python AST parser
15
16#[cfg(feature = "python-bindings")]
17pub mod management;
18#[cfg(feature = "python-bindings")]
19pub mod validation;
20#[cfg(feature = "python-bindings")]
21pub mod variant;
22
23pub use package::*;
24pub use python_ast_parser::*;
25pub use serialization::{PackageFormat, PackageSerializer}; // Always available for CLI usage
26
27// Always export requirement types for CLI usage
28pub mod requirement;
29pub use requirement::{Requirement, VersionConstraint};
30
31#[cfg(feature = "python-bindings")]
32pub use management::*;
33#[cfg(feature = "python-bindings")]
34pub use package::PackageRequirement as PyPackageRequirement;
35#[cfg(feature = "python-bindings")]
36pub use validation::*;
37#[cfg(feature = "python-bindings")]
38pub use variant::*;
39
40#[cfg(feature = "python-bindings")]
41use pyo3::prelude::*;
42
43/// Initialize the package module for Python
44#[cfg(feature = "python-bindings")]
45#[pymodule]
46fn rez_next_package(m: &Bound<'_, PyModule>) -> PyResult<()> {
47    m.add_class::<Package>()?;
48    m.add_class::<PackageVariant>()?;
49    m.add_class::<PyPackageRequirement>()?;
50    m.add_class::<PackageValidator>()?;
51    m.add_class::<PackageValidationResult>()?;
52    m.add_class::<PackageValidationOptions>()?;
53    m.add_class::<PackageManager>()?;
54    m.add_class::<PackageInstallOptions>()?;
55    m.add_class::<PackageCopyOptions>()?;
56    m.add_class::<PackageOperationResult>()?;
57    Ok(())
58}
59
60#[cfg(test)]
61mod tests {
62    use super::*;
63    use rez_next_version::Version;
64    use tempfile::TempDir;
65
66    #[test]
67    fn test_package_creation() {
68        let mut package = Package::new("test_package".to_string());
69        package.version = Some(Version::parse("1.0.0").unwrap());
70        package.description = Some("Test package description".to_string());
71        package.authors = vec!["Test Author".to_string()];
72
73        assert_eq!(package.name, "test_package");
74        assert!(package.version.is_some());
75        assert!(package.description.is_some());
76        assert_eq!(package.authors.len(), 1);
77    }
78
79    #[test]
80    #[cfg(feature = "python-bindings")]
81    fn test_package_validation() {
82        let mut package = Package::new("valid_package".to_string());
83        package.version = Some(Version::parse("1.0.0").unwrap());
84        package.description = Some("Valid test package".to_string());
85        package.authors = vec!["Test Author".to_string()];
86
87        let validator = PackageValidator::new(Some(PackageValidationOptions::new()));
88        let result = validator.validate_package(&package).unwrap();
89
90        assert!(result.is_valid);
91        assert_eq!(result.errors.len(), 0);
92        assert!(result.metadata_valid);
93        assert!(result.dependencies_valid);
94        assert!(result.variants_valid);
95    }
96
97    #[test]
98    #[cfg(feature = "python-bindings")]
99    fn test_package_validation_invalid() {
100        let package = Package::new("".to_string()); // Invalid name
101
102        let validator = PackageValidator::new(Some(PackageValidationOptions::new()));
103        let result = validator.validate_package(&package).unwrap();
104
105        assert!(!result.is_valid);
106        assert!(result.errors.len() > 0);
107        assert!(!result.metadata_valid);
108    }
109
110    #[test]
111    #[cfg(feature = "python-bindings")]
112    fn test_package_manager() {
113        let mut package = Package::new("test_package".to_string());
114        package.version = Some(Version::parse("1.0.0").unwrap());
115        package.description = Some("Test package for manager".to_string());
116        package.authors = vec!["Test Author".to_string()];
117
118        let manager = PackageManager::new();
119
120        let temp_dir = TempDir::new().unwrap();
121        let dest_path = temp_dir.path().to_str().unwrap();
122
123        let mut options = PackageInstallOptions::new();
124        options.dry_run = true;
125        options.validate = false;
126
127        let result = manager
128            .install_package(&package, dest_path, Some(options))
129            .unwrap();
130
131        assert!(result.success);
132        assert!(result.message.contains("Would install"));
133    }
134
135    #[test]
136    #[cfg(feature = "python-bindings")]
137    fn test_package_copy() {
138        let mut package = Package::new("original_package".to_string());
139        package.version = Some(Version::parse("1.0.0").unwrap());
140        package.description = Some("Original package".to_string());
141        package.authors = vec!["Test Author".to_string()];
142
143        let manager = PackageManager::new();
144
145        let temp_dir = TempDir::new().unwrap();
146        let dest_path = temp_dir.path().to_str().unwrap();
147
148        let mut options = PackageCopyOptions::new();
149        options.set_dest_name("renamed_package".to_string());
150        options.install_options.dry_run = true;
151        options.install_options.validate = false;
152
153        let result = manager
154            .copy_package(&package, dest_path, Some(options))
155            .unwrap();
156
157        assert!(result.success);
158    }
159
160    #[test]
161    #[cfg(feature = "python-bindings")]
162    fn test_validation_options() {
163        let default_options = PackageValidationOptions::new();
164        assert!(default_options.check_metadata);
165        assert!(default_options.check_dependencies);
166        assert!(!default_options.strict_mode);
167
168        let quick_options = PackageValidationOptions::quick();
169        assert!(quick_options.check_metadata);
170        assert!(!quick_options.check_dependencies);
171
172        let full_options = PackageValidationOptions::full();
173        assert!(full_options.check_metadata);
174        assert!(full_options.strict_mode);
175    }
176
177    #[test]
178    #[cfg(feature = "python-bindings")]
179    fn test_install_options() {
180        let default_options = PackageInstallOptions::new();
181        assert!(!default_options.overwrite);
182        assert!(default_options.validate);
183        assert!(!default_options.dry_run);
184
185        let quick_options = PackageInstallOptions::quick();
186        assert!(quick_options.skip_payload);
187        assert!(!quick_options.validate);
188
189        let safe_options = PackageInstallOptions::safe();
190        assert!(safe_options.keep_timestamp);
191        assert!(safe_options.verbose);
192    }
193}