interpreter: canonicalize when initializing search paths dynamically (#8299)

Dual-Root Mismatch in RustPython:
Unlike CPython, RustPython manages the standard library
in two separate locations in the workspace:
 - Workspace 'Lib/': Contains the test suite ('Lib/test/...') and
   standard library files.
 - crates/pylib/Lib/: A helper directory used for packaging.
   'crates/pylib/Lib' is a symlink pointing to the real workspace '../../Lib/'.

Runtime Directory Discrepancy:
 - 'sys.path' contains 'crates/pylib/Lib' (the path to the symlink).
 - Thus, when 'test.support' is imported, its '__file__' is resolved relative
   to the symlink: '/opt/RustPython/crates/pylib/Lib/test/support/__init__.py'.
 - Consequently, 'STDLIB_DIR' resolves to the symlink root:
   '/opt/RustPython/crates/pylib/Lib'.
 - However, since 'test_program.py' is executed directly from the workspace,
   its 'pkg_dir' is: '/opt/RustPython/Lib/test/test_unittest/testmock'.
 - When 'os.path.relpath(pkg_dir, top_dir)' is called:
   ---
   os.path.relpath(
       "/opt/RustPython/Lib/test/test_unittest/testmock",
       "/opt/RustPython/crates/pylib/Lib"
   )
   # Result: "../../../Lib/test/test_unittest/testmock"
   ---
   Because the relative path starts with '..', the assertion fails.

Assisted-by: Gemini
This commit is contained in:
Leesoo Ahn authored and GitHub committed 2026-07-19 13:32:46 +09:00
1 parent c7c67fd4d6
commit e68d9c266f
2 files changed
+17 -2

No files matched your search

-1
View File
@@ -505,7 +505,6 @@ class TestCommandLineArgs(unittest.TestCase):
self.assertEqual(program.testNamePatterns, ['*foo*', '*bar*', '*pat*'])
@unittest.expectedFailureIf(sys.platform != "win32", "TODO: RUSTPYTHON")
def testSelectedTestNamesFunctionalTest(self):
def run_unittest(args):
# Use -E to ignore PYTHONSAFEPATH env var
+17 -1
View File
@@ -57,7 +57,23 @@ fn setup_dynamic_stdlib(vm: &mut crate::VirtualMachine) {
use rustpython_vm::common::rc::PyRc;
let state = PyRc::get_mut(&mut vm.state).unwrap();
let paths = collect_stdlib_paths();
let paths: Vec<String> = collect_stdlib_paths()
.into_iter()
.map(|p| {
std::fs::canonicalize(&p)
.map(|canonical| {
let s = canonical.to_string_lossy();
#[cfg(windows)]
{
if let Some(stripped) = s.strip_prefix(r"\\?\") {
return stripped.to_owned();
}
}
s.into_owned()
})
.unwrap_or(p)
})
.collect();
// Set stdlib_dir to the first stdlib path if available
if let Some(first_path) = paths.first() {