Skip to content

Commit a8731ed

Browse files
authored
Merge branch 'main' into don/prior-eagle
2 parents 7417eee + e331280 commit a8731ed

File tree

4 files changed

+86
-29
lines changed

4 files changed

+86
-29
lines changed

.vscode/settings.json

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -10,5 +10,6 @@
1010
"git.branchProtection": [
1111
"main",
1212
"release/*"
13-
]
14-
}
13+
],
14+
"git.branchProtectionPrompt": "alwaysCommitToNewBranch"
15+
}

crates/pet-core/src/os_environment.rs

Lines changed: 1 addition & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -152,8 +152,5 @@ fn get_user_home() -> Option<PathBuf> {
152152
}
153153

154154
fn get_env_var(key: String) -> Option<String> {
155-
match env::var(key) {
156-
Ok(path) => Some(path),
157-
Err(_) => None,
158-
}
155+
env::var(key).ok()
159156
}

crates/pet-core/src/pyvenv_cfg.rs

Lines changed: 75 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -22,14 +22,21 @@ pub struct PyVenvCfg {
2222
pub version: String,
2323
pub version_major: u64,
2424
pub version_minor: u64,
25+
pub prompt: Option<String>,
2526
}
2627

2728
impl PyVenvCfg {
28-
fn new(version: String, version_major: u64, version_minor: u64) -> Self {
29+
fn new(
30+
version: String,
31+
version_major: u64,
32+
version_minor: u64,
33+
prompt: Option<String>,
34+
) -> Self {
2935
Self {
3036
version,
3137
version_major,
3238
version_minor,
39+
prompt,
3340
}
3441
}
3542
pub fn find(path: &Path) -> Option<Self> {
@@ -88,40 +95,85 @@ fn find(path: &Path) -> Option<PathBuf> {
8895

8996
fn parse(file: &Path) -> Option<PyVenvCfg> {
9097
let contents = fs::read_to_string(file).ok()?;
98+
let mut version: Option<String> = None;
99+
let mut version_major: Option<u64> = None;
100+
let mut version_minor: Option<u64> = None;
101+
let mut prompt: Option<String> = None;
102+
91103
for line in contents.lines() {
92-
if !line.contains("version") {
93-
continue;
104+
if version.is_none() {
105+
if let Some((ver, major, minor)) = parse_version(line, &VERSION) {
106+
version = Some(ver);
107+
version_major = Some(major);
108+
version_minor = Some(minor);
109+
continue;
110+
}
111+
if let Some((ver, major, minor)) = parse_version(line, &VERSION_INFO) {
112+
version = Some(ver);
113+
version_major = Some(major);
114+
version_minor = Some(minor);
115+
continue;
116+
}
94117
}
95-
if let Some(cfg) = parse_version(line, &VERSION) {
96-
return Some(cfg);
118+
if prompt.is_none() {
119+
if let Some(p) = parse_prompt(line) {
120+
prompt = Some(p);
121+
}
97122
}
98-
if let Some(cfg) = parse_version(line, &VERSION_INFO) {
99-
return Some(cfg);
123+
if version.is_some() && prompt.is_some() {
124+
break;
100125
}
101126
}
102-
None
127+
128+
match (version, version_major, version_minor) {
129+
(Some(ver), Some(major), Some(minor)) => Some(PyVenvCfg::new(ver, major, minor, prompt)),
130+
_ => None,
131+
}
103132
}
104133

105-
fn parse_version(line: &str, regex: &Regex) -> Option<PyVenvCfg> {
134+
fn parse_version(line: &str, regex: &Regex) -> Option<(String, u64, u64)> {
106135
if let Some(captures) = regex.captures(line) {
107136
if let Some(value) = captures.get(1) {
108137
let version = value.as_str();
109-
let parts: Vec<&str> = version.splitn(3, ".").take(2).collect();
110-
// .expect() below is OK because the version regex
111-
// guarantees there are at least two digits.
112-
let version_major = parts[0]
113-
.parse()
114-
.expect("python major version to be an integer");
115-
let version_minor = parts[1]
116-
.parse()
117-
.expect("python minor version to be an integer");
118-
return Some(PyVenvCfg::new(
119-
version.to_string(),
120-
version_major,
121-
version_minor,
122-
));
138+
let parts: Vec<&str> = version.split('.').collect();
139+
if parts.len() >= 2 {
140+
let version_major = parts[0]
141+
.parse()
142+
.expect("python major version to be an integer");
143+
let version_minor = parts[1]
144+
.parse()
145+
.expect("python minor version to be an integer");
146+
return Some((version.to_string(), version_major, version_minor));
147+
}
123148
}
124149
}
150+
None
151+
}
125152

153+
fn parse_prompt(line: &str) -> Option<String> {
154+
let trimmed = line.trim();
155+
if trimmed.starts_with("prompt") {
156+
if let Some(eq_idx) = trimmed.find('=') {
157+
// let value = trimmed[eq_idx + 1..].trim();
158+
let mut name = trimmed[eq_idx + 1..].trim().to_string();
159+
// Strip any leading or trailing single or double quotes
160+
if name.starts_with('"') {
161+
name = name.trim_start_matches('"').to_string();
162+
}
163+
if name.ends_with('"') {
164+
name = name.trim_end_matches('"').to_string();
165+
}
166+
// Strip any leading or trailing single or double quotes
167+
if name.starts_with('\'') {
168+
name = name.trim_start_matches('\'').to_string();
169+
}
170+
if name.ends_with('\'') {
171+
name = name.trim_end_matches('\'').to_string();
172+
}
173+
if !name.is_empty() {
174+
return Some(name);
175+
}
176+
}
177+
}
126178
None
127179
}

crates/pet-venv/src/lib.rs

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -63,8 +63,15 @@ impl Locator for Venv {
6363
if let Some(ref prefix) = prefix {
6464
symlinks.append(&mut find_executables(prefix));
6565
}
66+
67+
// Get the name from the prefix if it exists.
68+
let cfg = PyVenvCfg::find(env.executable.parent()?)
69+
.or_else(|| PyVenvCfg::find(&env.prefix.clone()?));
70+
let name = cfg.and_then(|cfg| cfg.prompt);
71+
6672
Some(
6773
PythonEnvironmentBuilder::new(Some(PythonEnvironmentKind::Venv))
74+
.name(name)
6875
.executable(Some(env.executable.clone()))
6976
.version(version)
7077
.prefix(prefix)

0 commit comments

Comments
 (0)