Skip to content

Commit e4f8f87

Browse files
committed
v1 of the shim extracted from other work
1 parent 26bf4f4 commit e4f8f87

File tree

3 files changed

+57
-48
lines changed

3 files changed

+57
-48
lines changed

py/tools/venv_shim/BUILD.bazel

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@ rust_binary(
66
"src/main.rs",
77
],
88
deps = [
9+
"@crate_index//:miette",
910
],
1011
)
1112

py/tools/venv_shim/Cargo.toml

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -9,14 +9,14 @@ edition.workspace = true
99
readme.workspace = true
1010
rust-version.workspace = true
1111

12+
[features]
13+
debug = []
14+
1215
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
1316

1417
[[bin]]
1518
name = "python_shim"
1619
path = "src/main.rs"
1720

1821
[dependencies]
19-
#libc = { workspace = true }
20-
#clap = { workspace = true }
21-
#miette = { workspace = true }
22-
#py = { path = "../py" }
22+
miette = { workspace = true }

py/tools/venv_shim/src/main.rs

Lines changed: 52 additions & 44 deletions
Original file line numberDiff line numberDiff line change
@@ -1,18 +1,11 @@
1+
use miette::miette;
12
use std::env;
23
use std::fs;
34
use std::io::{self, BufRead};
45
use std::os::unix::process::CommandExt;
56
use std::path::{Path, PathBuf};
67
use std::process::Command;
78

8-
fn compare_versions(version_from_cfg: &str, executable_path: &Path) -> bool {
9-
if let Some(file_name) = executable_path.file_name().and_then(|n| n.to_str()) {
10-
return file_name.ends_with(&format!("python{}", version_from_cfg));
11-
} else {
12-
false
13-
}
14-
}
15-
169
fn find_pyvenv_cfg(start_path: &Path) -> Option<PathBuf> {
1710
let parent = start_path.parent()?.parent()?;
1811
let cfg_path = parent.join("pyvenv.cfg");
@@ -39,7 +32,30 @@ fn extract_pyvenv_version_info(cfg_path: &Path) -> Result<Option<String>, io::Er
3932
Ok(None)
4033
}
4134

42-
fn find_python_executables(version_from_cfg: &str, exclude_dir: &Path) -> Option<Vec<PathBuf>> {
35+
fn parse_version_info(version_str: &str) -> Option<String> {
36+
// To avoid pulling in the regex crate, we're gonna do this by hand.
37+
let parts: Vec<_> = version_str.split(".").collect();
38+
match parts[..] {
39+
[major, minor, ..] => Some(format!("{}.{}", major, minor)),
40+
_ => None,
41+
}
42+
}
43+
44+
fn compare_versions(
45+
version_from_cfg: &str,
46+
executable_path: &Path,
47+
) -> bool {
48+
if let Some(file_name) = executable_path.file_name().and_then(|n| n.to_str()) {
49+
return file_name.ends_with(&format!("python{}", version_from_cfg));
50+
} else {
51+
false
52+
}
53+
}
54+
55+
fn find_python_executables(
56+
version_from_cfg: &str,
57+
exclude_dir: &Path,
58+
) -> Option<Vec<PathBuf>> {
4359
let python_prefix = format!("python{}", version_from_cfg);
4460
let path_env = env::var_os("PATH")?;
4561

@@ -63,80 +79,65 @@ fn find_python_executables(version_from_cfg: &str, exclude_dir: &Path) -> Option
6379
}
6480
}
6581

66-
fn parse_version_info(version_str: &str) -> Option<String> {
67-
// To avoid pulling in the regex crate, we're gonna do this by hand.
68-
let parts: Vec<_> = version_str.split(".").collect();
69-
match parts[..] {
70-
[major, minor, ..] => Some(format!("{}.{}", major, minor)),
71-
_ => None,
72-
}
73-
}
74-
75-
fn main() -> () {
82+
fn main() -> miette::Result<()> {
7683
let current_exe = env::current_exe().unwrap();
7784
let args: Vec<_> = env::args().collect();
78-
println!("In the Aspect venv shim!");
85+
86+
#[cfg(feature = "debug")]
7987
println!("[aspect] Current executable path: {:?}", current_exe);
8088

8189
let pyvenv_cfg_path = match find_pyvenv_cfg(&current_exe) {
8290
Some(path) => {
83-
println!("[aspect] Found pyvenv.cfg at: {:?}", path);
91+
#[cfg(feature = "debug")]
92+
eprintln!("[aspect] Found pyvenv.cfg at: {:?}", path);
8493
path
8594
}
8695
None => {
87-
eprintln!("pyvenv.cfg not found one directory level up.");
88-
return;
96+
return Err(miette!("pyvenv.cfg not found one directory level up."));
8997
}
9098
};
9199

92100
let version_info_result = extract_pyvenv_version_info(&pyvenv_cfg_path).unwrap();
93101
let version_info = match version_info_result {
94102
Some(v) => {
95-
println!("[aspect] version_info from pyvenv.cfg: {}", v);
103+
#[cfg(feature = "debug")]
104+
eprintln!("[aspect] version_info from pyvenv.cfg: {}", v);
96105
v
97106
}
98107
None => {
99-
eprintln!("version_info key not found in pyvenv.cfg.");
100-
return;
108+
return Err(miette!("version_info key not found in pyvenv.cfg."));
101109
}
102110
};
103111

104112
let target_python_version = match parse_version_info(&version_info) {
105113
Some(v) => {
106-
println!("[aspect] Parsed target Python version (major.minor): {}", v);
114+
#[cfg(feature = "debug")]
115+
eprintln!("[aspect] Parsed target Python version (major.minor): {}", v);
107116
v
108117
}
109118
None => {
110-
eprintln!("Could not parse version_info as x.y.");
111-
return;
119+
return Err(miette!("Could not parse version_info as x.y."));
112120
}
113121
};
114122

115-
if target_python_version.is_empty() {
116-
eprintln!("Target Python version is empty.");
117-
return;
118-
}
119-
120123
let exclude_dir = current_exe.parent().unwrap();
121124
if let Some(python_executables) = find_python_executables(&target_python_version, exclude_dir) {
122-
if python_executables.is_empty() {
125+
#[cfg(feature = "debug")]
126+
{
123127
eprintln!(
124-
"No suitable Python interpreter found in PATH matching version '{}'.",
125-
target_python_version
128+
"[aspect] Found potential Python interpreters in PATH with matching version:"
126129
);
127-
return;
128-
}
129-
130-
println!("[aspect] Found potential Python interpreters in PATH with matching version:");
131-
for exe in &python_executables {
132-
println!("[aspect] - {:?}", exe);
130+
for exe in &python_executables {
131+
println!("[aspect] - {:?}", exe);
132+
}
133133
}
134134

135135
let interpreter_path = &python_executables[0];
136136
let exe_path = current_exe.to_string_lossy().into_owned();
137137
let exec_args = &args[1..];
138138

139-
println!(
139+
#[cfg(feature = "debug")]
140+
eprintln!(
140141
"[aspect] Attempting to execute: {:?} with argv[0] as {:?} and args as {:?}",
141142
interpreter_path, exe_path, exec_args,
142143
);
@@ -162,5 +163,12 @@ fn main() -> () {
162163
}
163164

164165
let _ = cmd.exec();
166+
167+
return Ok(());
168+
} else {
169+
return Err(miette!(
170+
"No suitable Python interpreter found in PATH matching version '{}'.",
171+
&version_info,
172+
));
165173
}
166174
}

0 commit comments

Comments
 (0)