fix(python): include project roots in run and debug imports

Python file launches only exposed the script directory, so imports of sibling project packages failed. Add content, source and test roots to the effective PYTHONPATH after environment resolution, preserving existing paths. Apply the shared behavior to Python/test process launches and debugpy launches while leaving attach and remote adapter paths unchanged.

Refs #216
Цей коміт міститься в:
l0ng-ai authored and GitHub committed 2026-10-29 15:11:22 +08:00
1 джерело 3f9512056d
коміт c7d32f9e23
8 files changed
+195 -3

No files matched your search

+44
Переглянути файл
@@ -0,0 +1,44 @@
//! Python imports see the same content/source roots as the IDE.
use ide_core::{IdeError, IdeResult};
use std::collections::BTreeMap;
use std::path::PathBuf;
pub fn extend(env: &mut BTreeMap<String, String>, roots: &[PathBuf], inherit: bool) -> IdeResult<()> {
if roots.is_empty() {
return Ok(());
}
let inherited = if inherit { crate::system_env().remove("PYTHONPATH") } else { None };
let existing = env.get("PYTHONPATH").or(inherited.as_ref());
let mut paths = Vec::new();
for root in roots {
if !paths.contains(root) {
paths.push(root.clone());
}
}
if let Some(existing) = existing {
for path in std::env::split_paths(existing) {
if !paths.contains(&path) {
paths.push(path);
}
}
}
let joined =
std::env::join_paths(paths).map_err(|e| IdeError::invalid(format!("invalid Python import path: {e}")))?;
env.insert("PYTHONPATH".into(), joined.to_string_lossy().into_owned());
Ok(())
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn keeps_configured_paths_without_duplicates_or_system_leaks() {
let root = std::env::temp_dir().join("python project");
let other = root.join("vendor");
let value = std::env::join_paths([&other, &root]).unwrap().to_string_lossy().into_owned();
let mut env = BTreeMap::from([("PYTHONPATH".into(), value)]);
extend(&mut env, std::slice::from_ref(&root), false).unwrap();
assert_eq!(std::env::split_paths(&env["PYTHONPATH"]).collect::<Vec<_>>(), [root, other]);
}
}