-
Notifications
You must be signed in to change notification settings - Fork 39
Expand file tree
/
Copy pathresolve.rs
More file actions
136 lines (125 loc) · 4.56 KB
/
resolve.rs
File metadata and controls
136 lines (125 loc) · 4.56 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
// Copyright (c) Microsoft Corporation.
// Licensed under the MIT License.
use std::{path::PathBuf, sync::Arc};
use log::{trace, warn};
use pet_core::{
arch::Architecture,
env::PythonEnv,
os_environment::Environment,
python_environment::{PythonEnvironment, PythonEnvironmentBuilder},
Locator,
};
use pet_env_var_path::get_search_paths_from_env_variables;
use pet_python_utils::{
env::ResolvedPythonEnv,
executable::{find_executable, is_python_executable_name},
};
use crate::locators::identify_python_environment_using_locators;
#[derive(Debug)]
pub struct ResolvedEnvironment {
pub discovered: PythonEnvironment,
pub resolved: Option<PythonEnvironment>,
}
pub fn resolve_environment(
executable: &PathBuf,
locators: &Arc<Vec<Arc<dyn Locator>>>,
os_environment: &dyn Environment,
) -> Option<ResolvedEnvironment> {
// First check if executable is actually a file or a path.
let mut executable = executable.to_owned();
if executable.is_dir() {
trace!(
"Looking to resolve Python executable in provided directory, {:?}, file = {:?}, sylink = {:?}, metadata = {:?}",
executable,
executable.is_file(),
executable.is_symlink(),
executable.metadata(),
);
executable = match find_executable(&executable) {
Some(exe) => exe,
None => {
warn!("Could not find Python executable in {:?}", executable);
executable
}
};
trace!(
"Found Python executable in provided directory, {:?}",
executable
);
}
// Validate that the executable filename looks like a Python executable
// before proceeding with the locator chain or spawning.
if executable.is_file() && !is_python_executable_name(&executable) {
warn!(
"Path {:?} does not look like a Python executable, skipping resolve",
executable
);
return None;
}
// First check if this is a known environment
let env = PythonEnv::new(executable.to_owned(), None, None);
trace!(
"In resolve_environment, looking for Python Env {:?} in {:?}",
env,
executable
);
let global_env_search_paths: Vec<PathBuf> = get_search_paths_from_env_variables(os_environment);
if let Some(env) =
identify_python_environment_using_locators(&env, locators, &global_env_search_paths)
{
// Ok we got the environment.
// Now try to resolve this fully, by spawning python.
if let Some(ref executable) = env.executable {
if let Some(info) = ResolvedPythonEnv::from(executable) {
trace!(
"In resolve_environment, Resolved Python Exe {:?} as {:?}",
executable,
info
);
let discovered = env.clone();
let mut symlinks = env.symlinks.clone().unwrap_or_default();
symlinks.push(info.executable.clone());
symlinks.append(&mut info.symlinks.clone().unwrap_or_default());
symlinks.sort();
symlinks.dedup();
let version = Some(info.version.clone());
let prefix = Some(info.prefix.clone());
let arch = Some(if info.is64_bit {
Architecture::X64
} else {
Architecture::X86
});
let resolved = PythonEnvironmentBuilder::new(env.kind)
.arch(arch)
.display_name(env.display_name)
.executable(Some(info.executable.clone()))
.manager(env.manager)
.name(env.name)
.prefix(prefix)
.project(env.project)
.symlinks(Some(symlinks))
.version(version)
.build();
info.add_to_cache(resolved.clone());
Some(ResolvedEnvironment {
discovered,
resolved: Some(resolved),
})
} else {
Some(ResolvedEnvironment {
discovered: env,
resolved: None,
})
}
} else {
warn!("Unknown Python Env {:?} resolved as {:?}", executable, env);
Some(ResolvedEnvironment {
discovered: env,
resolved: None,
})
}
} else {
warn!("Unknown Python Env {:?}", executable);
None
}
}