rusty_stack/installers/components/
wandb.rs1#[derive(Debug, Clone, Copy, PartialEq, Eq)]
15pub enum InstallMethod {
16 Global,
18 Venv,
20 Auto,
22}
23
24impl std::fmt::Display for InstallMethod {
25 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
26 match self {
27 InstallMethod::Global => write!(f, "global"),
28 InstallMethod::Venv => write!(f, "venv"),
29 InstallMethod::Auto => write!(f, "auto"),
30 }
31 }
32}
33
34#[derive(Debug, Clone)]
36pub struct WandbConfig {
37 pub python_bin: String,
39 pub method: InstallMethod,
41 pub dry_run: bool,
43 pub strict_rocm: bool,
45}
46
47impl Default for WandbConfig {
48 fn default() -> Self {
49 Self {
50 python_bin: "python3".to_string(),
51 method: InstallMethod::Auto,
52 dry_run: false,
53 strict_rocm: true,
54 }
55 }
56}
57
58#[derive(Debug, Clone, PartialEq, Eq)]
60pub struct ShellCommand {
61 pub program: String,
63 pub args: Vec<String>,
65 pub env: Vec<(String, String)>,
67}
68
69impl ShellCommand {
70 pub fn to_command_string(&self) -> String {
72 let env_prefix = self
73 .env
74 .iter()
75 .map(|(k, v)| format!("{k}={v}"))
76 .collect::<Vec<_>>()
77 .join(" ");
78 let cmd = if self.args.is_empty() {
79 self.program.clone()
80 } else {
81 format!("{} {}", self.program, self.args.join(" "))
82 };
83 if env_prefix.is_empty() {
84 cmd
85 } else {
86 format!("{env_prefix} {cmd}")
87 }
88 }
89}
90
91pub struct WandbInstaller {
93 config: WandbConfig,
94}
95
96impl WandbInstaller {
97 pub fn new(config: WandbConfig) -> Self {
99 Self { config }
100 }
101
102 pub fn with_defaults() -> Self {
104 Self::new(WandbConfig::default())
105 }
106
107 pub fn build_install_command(&self) -> ShellCommand {
117 let use_break = self.config.method == InstallMethod::Global
118 || self.config.method == InstallMethod::Auto;
119
120 let mut args = vec!["-m".to_string(), "pip".to_string(), "install".to_string()];
121 if use_break {
122 args.push("--break-system-packages".to_string());
123 }
124 args.push("--upgrade".to_string());
125 args.push("wandb".to_string());
126
127 ShellCommand {
128 program: self.config.python_bin.clone(),
129 args,
130 env: vec![],
131 }
132 }
133}
134
135#[cfg(test)]
140mod tests {
141 use super::*;
142
143 #[test]
146 fn test_install_command_global() {
147 let installer = WandbInstaller::new(WandbConfig {
148 method: InstallMethod::Global,
149 ..Default::default()
150 });
151 let cmd = installer.build_install_command();
152 assert_eq!(cmd.program, "python3");
153 assert!(cmd.args.contains(&"-m".to_string()));
154 assert!(cmd.args.contains(&"pip".to_string()));
155 assert!(cmd.args.contains(&"install".to_string()));
156 assert!(cmd.args.contains(&"--break-system-packages".to_string()));
157 assert!(cmd.args.contains(&"wandb".to_string()));
158 }
159
160 #[test]
161 fn test_install_command_venv() {
162 let installer = WandbInstaller::new(WandbConfig {
163 method: InstallMethod::Venv,
164 ..Default::default()
165 });
166 let cmd = installer.build_install_command();
167 assert!(!cmd.args.contains(&"--break-system-packages".to_string()));
168 assert!(cmd.args.contains(&"wandb".to_string()));
169 }
170
171 #[test]
172 fn test_install_command_auto() {
173 let installer = WandbInstaller::new(WandbConfig {
174 method: InstallMethod::Auto,
175 ..Default::default()
176 });
177 let cmd = installer.build_install_command();
178 assert!(cmd.args.contains(&"--break-system-packages".to_string()));
179 assert!(cmd.args.contains(&"wandb".to_string()));
180 }
181
182 #[test]
183 fn test_command_string_format() {
184 let cmd = ShellCommand {
185 program: "python3".to_string(),
186 args: vec![
187 "-m".to_string(),
188 "pip".to_string(),
189 "install".to_string(),
190 "wandb".to_string(),
191 ],
192 env: vec![],
193 };
194 assert_eq!(cmd.to_command_string(), "python3 -m pip install wandb");
195 }
196
197 #[test]
198 fn test_command_string_with_env() {
199 let cmd = ShellCommand {
200 program: "python3".to_string(),
201 args: vec![
202 "-m".to_string(),
203 "pip".to_string(),
204 "install".to_string(),
205 "wandb".to_string(),
206 ],
207 env: vec![("ROCM_PATH".to_string(), "/opt/rocm".to_string())],
208 };
209 let s = cmd.to_command_string();
210 assert!(s.contains("ROCM_PATH=/opt/rocm"));
211 assert!(s.contains("python3 -m pip install wandb"));
212 }
213}