22// Licensed under the MIT License.
33
44use crate :: known;
5+ use crate :: known:: Environment ;
6+ use crate :: locator:: Locator ;
57use crate :: messaging;
8+ use crate :: messaging:: EnvManager ;
69use crate :: messaging:: EnvManagerType ;
10+ use crate :: messaging:: MessageDispatcher ;
11+ use crate :: messaging:: PythonEnvironment ;
712use crate :: utils:: find_python_binary_path;
13+ use crate :: utils:: PythonEnv ;
814use regex:: Regex ;
15+ use std:: collections:: HashMap ;
916use std:: env;
1017use std:: path:: { Path , PathBuf } ;
1118
@@ -129,7 +136,7 @@ fn get_conda_bin_names() -> Vec<&'static str> {
129136}
130137
131138/// Find the conda binary on the PATH environment variable
132- fn find_conda_binary_on_path ( environment : & impl known:: Environment ) -> Option < PathBuf > {
139+ fn find_conda_binary_on_path ( environment : & dyn known:: Environment ) -> Option < PathBuf > {
133140 let paths = environment. get_env_var ( "PATH" . to_string ( ) ) ?;
134141 for path in env:: split_paths ( & paths) {
135142 for bin in get_conda_bin_names ( ) {
@@ -148,7 +155,7 @@ fn find_conda_binary_on_path(environment: &impl known::Environment) -> Option<Pa
148155}
149156
150157#[ cfg( windows) ]
151- fn get_known_conda_locations ( environment : & impl known:: Environment ) -> Vec < PathBuf > {
158+ fn get_known_conda_locations ( environment : & dyn known:: Environment ) -> Vec < PathBuf > {
152159 let user_profile = environment. get_env_var ( "USERPROFILE" . to_string ( ) ) . unwrap ( ) ;
153160 let program_data = environment. get_env_var ( "PROGRAMDATA" . to_string ( ) ) . unwrap ( ) ;
154161 let all_user_profile = environment
@@ -170,7 +177,7 @@ fn get_known_conda_locations(environment: &impl known::Environment) -> Vec<PathB
170177}
171178
172179#[ cfg( unix) ]
173- fn get_known_conda_locations ( environment : & impl known:: Environment ) -> Vec < PathBuf > {
180+ fn get_known_conda_locations ( environment : & dyn known:: Environment ) -> Vec < PathBuf > {
174181 let mut known_paths = vec ! [
175182 PathBuf :: from( "/opt/anaconda3/bin" ) ,
176183 PathBuf :: from( "/opt/miniconda3/bin" ) ,
@@ -192,7 +199,7 @@ fn get_known_conda_locations(environment: &impl known::Environment) -> Vec<PathB
192199}
193200
194201/// Find conda binary in known locations
195- fn find_conda_binary_in_known_locations ( environment : & impl known:: Environment ) -> Option < PathBuf > {
202+ fn find_conda_binary_in_known_locations ( environment : & dyn known:: Environment ) -> Option < PathBuf > {
196203 let conda_bin_names = get_conda_bin_names ( ) ;
197204 let known_locations = get_known_conda_locations ( environment) ;
198205 for location in known_locations {
@@ -209,7 +216,7 @@ fn find_conda_binary_in_known_locations(environment: &impl known::Environment) -
209216}
210217
211218/// Find the conda binary on the system
212- pub fn find_conda_binary ( environment : & impl known:: Environment ) -> Option < PathBuf > {
219+ pub fn find_conda_binary ( environment : & dyn known:: Environment ) -> Option < PathBuf > {
213220 let conda_binary_on_path = find_conda_binary_on_path ( environment) ;
214221 match conda_binary_on_path {
215222 Some ( conda_binary_on_path) => Some ( conda_binary_on_path) ,
@@ -232,7 +239,7 @@ pub fn get_conda_version(conda_binary: &PathBuf) -> Option<String> {
232239 get_version_from_meta_json ( & conda_python_json_path)
233240}
234241
235- fn get_conda_envs_from_environment_txt ( environment : & impl known:: Environment ) -> Vec < String > {
242+ fn get_conda_envs_from_environment_txt ( environment : & dyn known:: Environment ) -> Vec < String > {
236243 let mut envs = vec ! [ ] ;
237244 let home = environment. get_user_home ( ) ;
238245 match home {
@@ -255,7 +262,7 @@ fn get_conda_envs_from_environment_txt(environment: &impl known::Environment) ->
255262
256263fn get_known_env_locations (
257264 conda_bin : & PathBuf ,
258- environment : & impl known:: Environment ,
265+ environment : & dyn known:: Environment ,
259266) -> Vec < String > {
260267 let mut paths = vec ! [ ] ;
261268 let home = environment. get_user_home ( ) ;
@@ -290,7 +297,7 @@ fn get_known_env_locations(
290297
291298fn get_conda_envs_from_known_env_locations (
292299 conda_bin : & PathBuf ,
293- environment : & impl known:: Environment ,
300+ environment : & dyn known:: Environment ,
294301) -> Vec < String > {
295302 let mut envs = vec ! [ ] ;
296303 for location in get_known_env_locations ( conda_bin, environment) {
@@ -333,7 +340,7 @@ struct CondaEnv {
333340
334341fn get_distinct_conda_envs (
335342 conda_bin : & PathBuf ,
336- environment : & impl known:: Environment ,
343+ environment : & dyn known:: Environment ,
337344) -> Vec < CondaEnv > {
338345 let mut envs = get_conda_envs_from_environment_txt ( environment) ;
339346 let mut known_envs = get_conda_envs_from_known_env_locations ( conda_bin, environment) ;
@@ -377,52 +384,91 @@ fn get_distinct_conda_envs(
377384 conda_envs
378385}
379386
380- pub fn find_and_report (
381- dispatcher : & mut impl messaging:: MessageDispatcher ,
382- environment : & impl known:: Environment ,
383- ) {
384- let conda_binary = find_conda_binary ( environment) ;
385- match conda_binary {
386- Some ( conda_binary) => {
387- let env_manager = messaging:: EnvManager :: new (
388- conda_binary. clone ( ) ,
389- get_conda_version ( & conda_binary) ,
390- EnvManagerType :: Conda ,
387+ pub struct Conda < ' a > {
388+ pub environments : HashMap < String , PythonEnvironment > ,
389+ pub manager : Option < EnvManager > ,
390+ pub environment : & ' a dyn Environment ,
391+ }
392+
393+ impl Conda < ' _ > {
394+ pub fn with < ' a > ( environment : & ' a impl Environment ) -> Conda {
395+ Conda {
396+ environments : HashMap :: new ( ) ,
397+ environment,
398+ manager : None ,
399+ }
400+ }
401+ }
402+
403+ impl Locator for Conda < ' _ > {
404+ fn is_known ( & self , python_executable : & PathBuf ) -> bool {
405+ self . environments
406+ . contains_key ( python_executable. to_str ( ) . unwrap_or_default ( ) )
407+ }
408+
409+ fn track_if_compatible ( & mut self , _env : & PythonEnv ) -> bool {
410+ // We will find everything in gather
411+ false
412+ }
413+
414+ fn gather ( & mut self ) -> Option < ( ) > {
415+ let conda_binary = find_conda_binary ( self . environment ) ?;
416+ let manager = EnvManager :: new (
417+ conda_binary. clone ( ) ,
418+ get_conda_version ( & conda_binary) ,
419+ EnvManagerType :: Conda ,
420+ ) ;
421+ self . manager = Some ( manager. clone ( ) ) ;
422+
423+ let envs = get_distinct_conda_envs ( & conda_binary, self . environment ) ;
424+ for env in envs {
425+ let executable = find_python_binary_path ( Path :: new ( & env. path ) ) ;
426+ let env = messaging:: PythonEnvironment :: new (
427+ Some ( env. name . to_string ( ) ) ,
428+ executable. clone ( ) ,
429+ messaging:: PythonEnvironmentCategory :: Conda ,
430+ get_conda_python_version ( & env. path ) ,
431+ Some ( env. path . clone ( ) ) ,
432+ Some ( env. path . clone ( ) ) ,
433+ Some ( manager. clone ( ) ) ,
434+ if env. named {
435+ Some ( vec ! [
436+ conda_binary. to_string_lossy( ) . to_string( ) ,
437+ "run" . to_string( ) ,
438+ "-n" . to_string( ) ,
439+ env. name. to_string( ) ,
440+ "python" . to_string( ) ,
441+ ] )
442+ } else {
443+ Some ( vec ! [
444+ conda_binary. to_string_lossy( ) . to_string( ) ,
445+ "run" . to_string( ) ,
446+ "-p" . to_string( ) ,
447+ env. path. to_string_lossy( ) . to_string( ) ,
448+ "python" . to_string( ) ,
449+ ] )
450+ } ,
391451 ) ;
392- dispatcher. report_environment_manager ( env_manager. clone ( ) ) ;
393-
394- let envs = get_distinct_conda_envs ( & conda_binary, environment) ;
395- for env in envs {
396- let executable = find_python_binary_path ( Path :: new ( & env. path ) ) ;
397- let params = messaging:: PythonEnvironment :: new (
398- Some ( env. name . to_string ( ) ) ,
399- executable,
400- messaging:: PythonEnvironmentCategory :: Conda ,
401- get_conda_python_version ( & env. path ) ,
402- Some ( env. path . clone ( ) ) ,
403- Some ( env. path . clone ( ) ) ,
404- Some ( env_manager. clone ( ) ) ,
405- if env. named {
406- Some ( vec ! [
407- conda_binary. to_string_lossy( ) . to_string( ) ,
408- "run" . to_string( ) ,
409- "-n" . to_string( ) ,
410- env. name. to_string( ) ,
411- "python" . to_string( ) ,
412- ] )
413- } else {
414- Some ( vec ! [
415- conda_binary. to_string_lossy( ) . to_string( ) ,
416- "run" . to_string( ) ,
417- "-p" . to_string( ) ,
418- env. path. to_string_lossy( ) . to_string( ) ,
419- "python" . to_string( ) ,
420- ] )
421- } ,
422- ) ;
423- dispatcher. report_environment ( params) ;
452+
453+ if let Some ( exe) = executable {
454+ self . environments
455+ . insert ( exe. to_str ( ) . unwrap_or_default ( ) . to_string ( ) , env) ;
456+ } else if let Some ( env_path) = env. env_path . clone ( ) {
457+ self . environments
458+ . insert ( env_path. to_str ( ) . unwrap ( ) . to_string ( ) , env) ;
424459 }
425460 }
426- None => ( ) ,
461+
462+ Some ( ( ) )
463+ }
464+
465+ fn report ( & self , reporter : & mut dyn MessageDispatcher ) {
466+ if let Some ( manager) = & self . manager {
467+ reporter. report_environment_manager ( manager. clone ( ) ) ;
468+ }
469+
470+ for env in self . environments . values ( ) {
471+ reporter. report_environment ( env. clone ( ) ) ;
472+ }
427473 }
428474}
0 commit comments