venvlauncher#6527
Conversation
📝 WalkthroughWalkthroughAdds a new Windows-focused Rust venv launcher crate that discovers a virtualenv via pyvenv.cfg, selects python/pythonw, sets PYVENV_LAUNCHER, re-execs Python, and updates VM path resolution to be launcher-aware preserving the real base executable. Changes
Sequence DiagramsequenceDiagram
autonumber
actor User
participant Launcher as venvlauncher (exe)
participant VenvCfg as pyvenv.cfg
participant Python as python.exe / pythonw.exe
participant VM as RustPython VM
User->>Launcher: start with args
Launcher->>Launcher: inspect exe name -> choose target (pythonw/python)
Launcher->>VenvCfg: locate pyvenv.cfg (walk from Scripts/)
VenvCfg-->>Launcher: return home path (home=...)
Launcher->>Launcher: validate Python exists under home
Launcher->>Launcher: set __PYVENV_LAUNCHER__ env
Launcher->>Python: exec target Python with original args
Python->>VM: VM startup reads __PYVENV_LAUNCHER__
Note over VM: VM sets sys.executable=launcher\nand sys._base_executable=real python
VM-->>User: exit code propagated
Estimated code review effort🎯 4 (Complex) | ⏱️ ~45 minutes Possibly related PRs
Suggested reviewers
Poem
Pre-merge checks and finishing touches❌ Failed checks (1 inconclusive)
✅ Passed checks (2 passed)
✨ Finishing touches
🧪 Generate unit tests (beta)
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
Sorry, something went wrong.
88dc2ca to
ec93177
Compare
December 25, 2025 13:15
There was a problem hiding this comment.
Actionable comments posted: 7
🧹 Nitpick comments (5)
crates/vm/src/getpath.rs (1)
123-132: Consider validating the launcher path before use.The code reads
__PYVENV_LAUNCHER__and uses it directly without verifying that the path is valid or exists. While this mirrors CPython's behavior, consider whether RustPython should add defensive validation to prevent potential issues with malformed or non-existent launcher paths.🔎 Potential validation approach
let exe_dir = if let Ok(launcher) = env::var("__PYVENV_LAUNCHER__") { + let launcher_path = PathBuf::from(&launcher); + if !launcher_path.exists() { + // Log warning or fallback to non-launcher behavior + } paths.executable = launcher.clone(); paths.base_executable = real_executable; PathBuf::from(&launcher).parent().map(PathBuf::from)crates/venvlauncher/Cargo.toml (1)
19-19: Clarify or remove misleading comment about free-threading.The comment mentions "Free-threaded variants (RustPython uses Py_GIL_DISABLED=true)" but the launcher implementation doesn't contain any free-threading logic. The launcher simply delegates to the Python executable, so the 't' suffix in the binary name is purely conventional (to match CPython's naming). Consider clarifying that these launchers merely forward to free-threaded Python builds rather than implementing free-threading themselves.
🔎 Suggested clarification
-# Free-threaded variants (RustPython uses Py_GIL_DISABLED=true) +# Launcher variants for free-threaded Python builds (suffix 't' matches CPython convention)crates/venvlauncher/src/main.rs (3)
82-86: Consider handling inline comments in configuration values.The
read_home()function doesn't handle inline comments (e.g.,home = /path # this is the Python home). While this may not be common inpyvenv.cfg, it could cause issues if users add comments.🔎 Enhanced parsing with inline comment support
if let Some(rest) = line.strip_prefix("home") { let rest = rest.trim_start(); if let Some(value) = rest.strip_prefix('=') { - return Ok(value.trim().to_string()); + let value = value.trim(); + // Strip inline comments + let value = value.split('#').next().unwrap_or(value).trim(); + return Ok(value.to_string()); } }
99-99: Redundant type casting in exit code handling.The code casts
Option<i32>tou32after unwrapping. Sincestatus.code()returnsOption<i32>, the pattern could be simplified.🔎 Simplified version
- Ok(status.code().unwrap_or(1) as u32) + Ok(status.code().unwrap_or(1).max(0) as u32)Also consider handling negative exit codes (though rare) by clamping to 0.
112-120: Test cleanup may fail on panic.If the test panics before
fs::remove_file(), the temporary file will be left behind. Consider using RAII or test fixtures for cleanup.🔎 Use drop guard for cleanup
struct TempFile(PathBuf); impl Drop for TempFile { fn drop(&mut self) { let _ = fs::remove_file(&self.0); } } #[test] fn test_read_home() { let cfg_path = std::env::temp_dir().join("test_pyvenv.cfg"); let _guard = TempFile(cfg_path.clone()); let mut file = fs::File::create(&cfg_path).unwrap(); // ... rest of test // No manual cleanup needed }
📜 Review details
Configuration used: Path: .coderabbit.yml
Review profile: CHILL
Plan: Pro
⛔ Files ignored due to path filters (5)
Cargo.lockis excluded by!**/*.lockLib/venv/scripts/nt/venvlauncher.exeis excluded by!**/*.exe,!Lib/**Lib/venv/scripts/nt/venvlaunchert.exeis excluded by!**/*.exe,!Lib/**Lib/venv/scripts/nt/venvwlauncher.exeis excluded by!**/*.exe,!Lib/**Lib/venv/scripts/nt/venvwlaunchert.exeis excluded by!**/*.exe,!Lib/**
📒 Files selected for processing (5)
.cspell.dict/cpython.txtcrates/venvlauncher/Cargo.tomlcrates/venvlauncher/build.rscrates/venvlauncher/src/main.rscrates/vm/src/getpath.rs
🧰 Additional context used
📓 Path-based instructions (1)
**/*.rs
📄 CodeRabbit inference engine (.github/copilot-instructions.md)
**/*.rs: Follow the default rustfmt code style by runningcargo fmtto format Rust code
Always run clippy to lint Rust code (cargo clippy) before completing tasks and fix any warnings or lints introduced by changes
Follow Rust best practices for error handling and memory management
Use the macro system (pyclass,pymodule,pyfunction, etc.) when implementing Python functionality in Rust
Files:
crates/venvlauncher/src/main.rscrates/venvlauncher/build.rscrates/vm/src/getpath.rs
🧠 Learnings (4)
📚 Learning: 2025-11-29T12:17:28.606Z
Learnt from: CR
Repo: RustPython/RustPython PR: 0
File: .github/copilot-instructions.md:0-0
Timestamp: 2025-11-29T12:17:28.606Z
Learning: Run `cargo test --workspace --exclude rustpython_wasm` to execute Rust unit tests
Applied to files:
crates/venvlauncher/Cargo.toml
📚 Learning: 2025-11-29T12:17:28.606Z
Learnt from: CR
Repo: RustPython/RustPython PR: 0
File: .github/copilot-instructions.md:0-0
Timestamp: 2025-11-29T12:17:28.606Z
Learning: Applies to **/*.rs : Use the macro system (`pyclass`, `pymodule`, `pyfunction`, etc.) when implementing Python functionality in Rust
Applied to files:
crates/venvlauncher/Cargo.toml
📚 Learning: 2025-11-29T12:17:28.606Z
Learnt from: CR
Repo: RustPython/RustPython PR: 0
File: .github/copilot-instructions.md:0-0
Timestamp: 2025-11-29T12:17:28.606Z
Learning: Use `cargo run -- script.py` instead of the standard `python` command to run and test Python code with RustPython
Applied to files:
crates/venvlauncher/src/main.rs
📚 Learning: 2025-06-28T16:31:03.991Z
Learnt from: arihant2math
Repo: RustPython/RustPython PR: 5790
File: build.rs:2-2
Timestamp: 2025-06-28T16:31:03.991Z
Learning: In Cargo build scripts (build.rs), the environment variable CARGO_CFG_TARGET_OS is guaranteed to exist and is automatically set by Cargo during the build process, making unwrap() safe to use when accessing this variable.
Applied to files:
crates/venvlauncher/build.rs
🧬 Code graph analysis (2)
crates/venvlauncher/src/main.rs (1)
crates/venvlauncher/build.rs (1)
main(5-18)
crates/vm/src/getpath.rs (2)
crates/vm/src/stdlib/sys.rs (1)
executable(176-178)crates/vm/src/stdlib/posix.rs (1)
env(1149-1167)
🔇 Additional comments (3)
.cspell.dict/cpython.txt (1)
51-51: LGTM!The dictionary entries correctly reflect the new venv launcher binary variants introduced in this PR.
Also applies to: 69-73
crates/vm/src/getpath.rs (1)
113-132: Approve the launcher path handling logic.The implementation correctly separates launcher-based and non-launcher flows, setting
sys.executableto the launcher path andsys._base_executableto the real Python executable when launched from a venv. The logic aligns with CPython's venv launcher behavior.crates/venvlauncher/Cargo.toml (1)
11-26: LGTM: Binary target configuration is appropriate.Using a single
main.rsfor all four launcher variants is the correct approach, as the launcher determines behavior based on its invocation name at runtime.
Sorry, something went wrong.
ec93177 to
5f84ae3
Compare
December 25, 2025 14:37
There was a problem hiding this comment.
Actionable comments posted: 0
♻️ Duplicate comments (2)
crates/venvlauncher/src/main.rs (2)
15-23: Exit code truncation may lose information.Casting
u32tou8on line 17 silently truncates exit codes > 255. Consider clamping to preserve meaningful error indication.
62-67: PreferCommand::envover unsafeenv::set_var.The
unsafeblock forenv::set_varis risky—the single-threaded assumption isn't guaranteed by Rust's runtime. The safer approach is to set the environment variable on the child process viaCommand::env().🔎 Proposed fix
Modify
launch_processto accept the launcher path and set the env var there:-fn launch_process(exe: &Path, args: &[String]) -> Result<u32, Box<dyn std::error::Error>> { +fn launch_process(exe: &Path, args: &[String], launcher_path: &Path) -> Result<u32, Box<dyn std::error::Error>> { use std::process::Command; - let status = Command::new(exe).args(args).status()?; + let status = Command::new(exe) + .args(args) + .env("__PYVENV_LAUNCHER__", launcher_path) + .status()?; Ok(status.code().unwrap_or(1) as u32) }Then in
run():- // 6. Set __PYVENV_LAUNCHER__ environment variable - // This tells Python it was launched from a venv - // SAFETY: We are in a single-threaded context (program entry point) - unsafe { - env::set_var("__PYVENV_LAUNCHER__", &exe_path); - } - // 7. Launch Python with same arguments let args: Vec<String> = env::args().skip(1).collect(); - launch_process(&python_path, &args) + launch_process(&python_path, &args, &exe_path)
🧹 Nitpick comments (1)
crates/venvlauncher/src/main.rs (1)
106-125: Test isolation could be improved for parallel execution.The tests use fixed temp file names (
test_pyvenv.cfg,test_pyvenv2.cfg, etc.) in the shared temp directory. If tests run in parallel, they could interfere with each other. Consider usingtempfilecrate or unique names.🔎 Proposed improvement using tempfile
use tempfile::NamedTempFile; #[test] fn test_read_home() { let mut file = NamedTempFile::new().unwrap(); writeln!(file, "home = C:\\Python313").unwrap(); writeln!(file, "include-system-site-packages = false").unwrap(); writeln!(file, "version = 3.13.0").unwrap(); let home = read_home(file.path()).unwrap(); assert_eq!(home, "C:\\Python313"); // File is automatically deleted when `file` goes out of scope }This requires adding
tempfileas a dev-dependency inCargo.toml.
📜 Review details
Configuration used: Path: .coderabbit.yml
Review profile: CHILL
Plan: Pro
⛔ Files ignored due to path filters (5)
Cargo.lockis excluded by!**/*.lockLib/venv/scripts/nt/venvlauncher.exeis excluded by!**/*.exe,!Lib/**Lib/venv/scripts/nt/venvlaunchert.exeis excluded by!**/*.exe,!Lib/**Lib/venv/scripts/nt/venvwlauncher.exeis excluded by!**/*.exe,!Lib/**Lib/venv/scripts/nt/venvwlaunchert.exeis excluded by!**/*.exe,!Lib/**
📒 Files selected for processing (5)
.cspell.dict/cpython.txtcrates/venvlauncher/Cargo.tomlcrates/venvlauncher/build.rscrates/venvlauncher/src/main.rscrates/vm/src/getpath.rs
🚧 Files skipped from review as they are similar to previous changes (4)
- crates/vm/src/getpath.rs
- crates/venvlauncher/Cargo.toml
- crates/venvlauncher/build.rs
- .cspell.dict/cpython.txt
🧰 Additional context used
📓 Path-based instructions (1)
**/*.rs
📄 CodeRabbit inference engine (.github/copilot-instructions.md)
**/*.rs: Follow the default rustfmt code style by runningcargo fmtto format Rust code
Always run clippy to lint Rust code (cargo clippy) before completing tasks and fix any warnings or lints introduced by changes
Follow Rust best practices for error handling and memory management
Use the macro system (pyclass,pymodule,pyfunction, etc.) when implementing Python functionality in Rust
Files:
crates/venvlauncher/src/main.rs
🧠 Learnings (4)
📚 Learning: 2025-06-27T14:47:28.810Z
Learnt from: moreal
Repo: RustPython/RustPython PR: 5847
File: vm/src/stdlib/stat.rs:547-567
Timestamp: 2025-06-27T14:47:28.810Z
Learning: In RustPython's stat module implementation, platform-specific constants like SF_SUPPORTED and SF_SYNTHETIC should be conditionally declared only for the platforms where they're available (e.g., macOS), following CPython's approach of optional declaration using #ifdef checks rather than providing fallback values for other platforms.
Applied to files:
crates/venvlauncher/src/main.rs
📚 Learning: 2025-06-27T14:47:28.810Z
Learnt from: moreal
Repo: RustPython/RustPython PR: 5847
File: vm/src/stdlib/stat.rs:547-567
Timestamp: 2025-06-27T14:47:28.810Z
Learning: In RustPython's stat module implementation, platform-specific constants like SF_SUPPORTED and SF_SYNTHETIC should be conditionally declared only for the platforms where they're available (e.g., macOS), following CPython's approach of optional declaration rather than providing fallback values for other platforms.
Applied to files:
crates/venvlauncher/src/main.rs
📚 Learning: 2025-06-28T16:31:03.991Z
Learnt from: arihant2math
Repo: RustPython/RustPython PR: 5790
File: build.rs:2-2
Timestamp: 2025-06-28T16:31:03.991Z
Learning: In Cargo build scripts (build.rs), the environment variable CARGO_CFG_TARGET_OS is guaranteed to exist and is automatically set by Cargo during the build process, making unwrap() safe to use when accessing this variable.
Applied to files:
crates/venvlauncher/src/main.rs
📚 Learning: 2025-11-29T12:17:28.606Z
Learnt from: CR
Repo: RustPython/RustPython PR: 0
File: .github/copilot-instructions.md:0-0
Timestamp: 2025-11-29T12:17:28.606Z
Learning: Applies to Lib/test/**/*.py : When modifying test files in `Lib/test/`, use `unittest.skip("TODO: RustPython <reason>")` or `unittest.expectedFailure` with `# TODO: RUSTPYTHON <reason>` comment to mark unsupported features
Applied to files:
crates/venvlauncher/src/main.rs
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (8)
- GitHub Check: Run snippets and cpython tests (ubuntu-latest)
- GitHub Check: Run snippets and cpython tests (windows-latest)
- GitHub Check: Run snippets and cpython tests (macos-latest)
- GitHub Check: Run rust tests (windows-latest)
- GitHub Check: Check Rust code with clippy
- GitHub Check: Ensure compilation on various targets
- GitHub Check: Check the WASM package and demo
- GitHub Check: Run snippets and cpython tests on wasm-wasi
🔇 Additional comments (6)
crates/venvlauncher/src/main.rs (6)
1-8: Platform guard properly implemented.The
compile_error!macro ensures this crate only compiles on Windows, addressing the Windows-only nature of this launcher. Documentation is clear.
10-13: LGTM!Clean and minimal imports, all are used in the implementation.
25-41: LGTM!The launcher name detection logic correctly differentiates between GUI (
pythonw.exe) and console (python.exe) variants. Path discovery fromScripts/to venv root follows the expected Windows venv layout.
74-95: LGTM!The
read_homeparser correctly handles whitespace variations (home = valuevshome=value), skips comments and empty lines, and uses idiomatic Rust string processing. This aligns with CPython's pyvenv.cfg format expectations.
97-104: LGTM!Simple and correct process delegation. The
unwrap_or(1)fallback for abnormal termination is reasonable.
127-155: LGTM!Good test coverage for parsing variations. The
#[cfg(all(test, windows))]guard ensures these Windows-path-dependent tests only run on Windows.
Sorry, something went wrong.
5f84ae3 to
b0360a4
Compare
December 25, 2025 15:48
There was a problem hiding this comment.
Actionable comments posted: 2
📜 Review details
Configuration used: Path: .coderabbit.yml
Review profile: CHILL
Plan: Pro
⛔ Files ignored due to path filters (5)
Cargo.lockis excluded by!**/*.lockLib/venv/scripts/nt/venvlauncher.exeis excluded by!**/*.exe,!Lib/**Lib/venv/scripts/nt/venvlaunchert.exeis excluded by!**/*.exe,!Lib/**Lib/venv/scripts/nt/venvwlauncher.exeis excluded by!**/*.exe,!Lib/**Lib/venv/scripts/nt/venvwlaunchert.exeis excluded by!**/*.exe,!Lib/**
📒 Files selected for processing (6)
.cspell.dict/cpython.txt.github/workflows/ci.yamlcrates/venvlauncher/Cargo.tomlcrates/venvlauncher/build.rscrates/venvlauncher/src/main.rscrates/vm/src/getpath.rs
🚧 Files skipped from review as they are similar to previous changes (4)
- crates/venvlauncher/build.rs
- crates/venvlauncher/src/main.rs
- crates/vm/src/getpath.rs
- .cspell.dict/cpython.txt
🧰 Additional context used
🧠 Learnings (6)
📚 Learning: 2025-11-29T12:17:28.606Z
Learnt from: CR
Repo: RustPython/RustPython PR: 0
File: .github/copilot-instructions.md:0-0
Timestamp: 2025-11-29T12:17:28.606Z
Learning: Run `cargo test --workspace --exclude rustpython_wasm` to execute Rust unit tests
Applied to files:
.github/workflows/ci.yamlcrates/venvlauncher/Cargo.toml
📚 Learning: 2025-11-29T12:17:28.606Z
Learnt from: CR
Repo: RustPython/RustPython PR: 0
File: .github/copilot-instructions.md:0-0
Timestamp: 2025-11-29T12:17:28.606Z
Learning: Applies to **/*.rs : Always run clippy to lint Rust code (`cargo clippy`) before completing tasks and fix any warnings or lints introduced by changes
Applied to files:
.github/workflows/ci.yaml
📚 Learning: 2025-11-29T12:17:28.606Z
Learnt from: CR
Repo: RustPython/RustPython PR: 0
File: .github/copilot-instructions.md:0-0
Timestamp: 2025-11-29T12:17:28.606Z
Learning: Use `cargo run -- script.py` instead of the standard `python` command to run and test Python code with RustPython
Applied to files:
.github/workflows/ci.yaml
📚 Learning: 2025-09-28T22:22:55.921Z
Learnt from: reactive-firewall
Repo: RustPython/RustPython PR: 6176
File: .github/workflows/Check_Tests.yml:133-141
Timestamp: 2025-09-28T22:22:55.921Z
Learning: In the RustPython project's CI-5974-Test-RustPython-Integration action, the override-rustpython-path input is marked as required but has runtime fallback logic that defaults to RUSTPYTHONPATH environment variable or "Lib" if neither is provided, making explicit specification unnecessary in most cases.
Applied to files:
.github/workflows/ci.yaml
📚 Learning: 2025-06-28T16:31:03.991Z
Learnt from: arihant2math
Repo: RustPython/RustPython PR: 5790
File: build.rs:2-2
Timestamp: 2025-06-28T16:31:03.991Z
Learning: In Cargo build scripts (build.rs), the environment variable CARGO_CFG_TARGET_OS is guaranteed to exist and is automatically set by Cargo during the build process, making unwrap() safe to use when accessing this variable.
Applied to files:
.github/workflows/ci.yaml
📚 Learning: 2025-11-29T12:17:28.606Z
Learnt from: CR
Repo: RustPython/RustPython PR: 0
File: .github/copilot-instructions.md:0-0
Timestamp: 2025-11-29T12:17:28.606Z
Learning: Applies to **/*.rs : Use the macro system (`pyclass`, `pymodule`, `pyfunction`, etc.) when implementing Python functionality in Rust
Applied to files:
crates/venvlauncher/Cargo.toml
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (10)
- GitHub Check: Run snippets and cpython tests (windows-latest)
- GitHub Check: Run snippets and cpython tests (macos-latest)
- GitHub Check: Run rust tests (windows-latest)
- GitHub Check: Run rust tests (macos-latest)
- GitHub Check: Run snippets and cpython tests (ubuntu-latest)
- GitHub Check: Run rust tests (ubuntu-latest)
- GitHub Check: Run snippets and cpython tests on wasm-wasi
- GitHub Check: Check Rust code with clippy
- GitHub Check: Ensure compilation on various targets
- GitHub Check: Check the WASM package and demo
🔇 Additional comments (2)
crates/venvlauncher/Cargo.toml (1)
28-36: LGTM! Windows dependencies are properly scoped.The Windows-specific dependencies are correctly limited to
cfg(windows)targets, and the Win32 feature selection looks appropriate for a venv launcher that needs process creation, environment manipulation, and file system access..github/workflows/ci.yaml (1)
143-149: Verify Windows launcher builds and tests execute on Windows CI.Ensure that once the exclusion logic is fixed, the Windows venv launcher is properly compiled and tested on the
windows-latestrunner. The launcher should undergo clippy checks and unit tests specific to Windows.After addressing the exclusion issue, run the following to confirm the launcher is being tested:
#!/bin/bash # Check if there are any Windows-specific tests for the venv launcher fd -e rs . crates/venvlauncher --exec rg -l "test|Test" {}
Sorry, something went wrong.
40acd55
into
RustPython:main
Dec 25, 2025
Summary by CodeRabbit
New Features
Bug Fixes
Chores
✏️ Tip: You can customize this high-level summary in your review settings.