Skip to content

Prefer resolved executable symlinks in POSIX virtual environments - #9058

Merged
youknowone merged 1 commit into
RustPython:mainfrom
youknowdot:fix-venv-executable-symlinks
Oct 11, 2026
Merged

youknowone merged 1 commit into
RustPython:mainfrom
youknowdot:fix-venv-executable-symlinks

Conversation

@youknowdot

@youknowdot youknowdot commented Oct 10, 2026 •

Copy link
Copy Markdown
Contributor

Current revision

Targets main after #8950, with one logical commit: 915a6836eb71e5d1c345457c76c0d7b2be1f72f7 (parent a10744303f6fb113a6082dde133958ad882d25a4). The unique patch is byte-identical after rebasing onto current Python 3.15 main, including the merged shared IO correction; original author attribution and assistance trailers are retained. No files under Lib/ are changed.

Normal hooks, whitespace checks, and independent tree/history review passed. The temporary [skip ci] marker is removed and normal CI is enabled for this final head. No new local build or runtime test is claimed. Validation recorded below belongs to earlier revisions unless explicitly stated otherwise.

Summary

Extract the Python 3.14-compatible venv executable-symlink behavior from #8954 (43065e79ddc46eafeca58cb39398ac007b5d25f7), without copying its broader custom metadata traversal.

When pyvenv.cfg supplies a home directory, follow final-component executable symlinks before falling back to home/<invoked name>. Preserve directory aliases, copied-executable fallback, non-venv invocation paths, Windows behavior, and existing launcher-override precedence.

The resolver follows CPython 3.14.7's getpath helper, including its bounded traversal, rather than using filesystem canonicalization, which would incorrectly resolve directory aliases. The selection contract is in getpath.py.

Validation

  • Independent source review caught and corrected directory-alias handling and the macOS-framework limitation in the initial test design before publication.
  • Exact CPython 3.14.7 and the native final head pass the complete existing sys snippet, including nine bounded scenarios: absolute/relative/chained links, both config locations, non-venv preservation, copied fallback, directory aliases, double-leading slash, and Linux launcher override.
  • Both dedicated snippet pytest entries pass under Python 3.14.7. The original generic local runner used Python 3.12, whose -S prefix behavior differs; validation was moved to the correct reference version without weakening assertions.
  • Normal hooks, VM Clippy, and separately configured CAPI Clippy pass with -D warnings.

All new assertions are Python-side. Children only print sys attributes, run with -B -S and timeouts, and execute the trusted interpreter or its copy inside owned temporary directories. No package installation, configuration-provided executable, dangling/cyclic launch, or root-path probe is part of the tests.

Boundaries

The local character-count rule follows RustPython's existing UTF-8/surrogateescape filesystem contract; arbitrary non-UTF-8 CPython locale parity is not claimed. Root-level edge behavior was source-reviewed only. WASI/Emscripten are excluded from new runtime coverage; non-Linux native execution remains unverified.

No cfg parser, custom base-executable/executable metadata, PYTHONHOME handling, shared path converter, or canonical test assertion/marker is changed. Canonical test_getpath.py is absent from this checkout; no canonical-suite pass is claimed. Hosted CI remains required.

Summary by CodeRabbit

  • Compatibility
    • RustPython now targets Python 3.15.0.
    • Virtual environments report the executable behind absolute, relative, and chained symlinks. Resolved paths are used when available; existing fallback behavior remains, and non-virtual-environment launches and copied executables are unchanged.
  • Bug Fixes
    • Improved compatibility for sequence repetition, logarithms, timestamp conversion, AST construction, memory-mapped searches, and struct formats.
    • Error messages and exceptions are more consistent for formatting, module creation, and invalid inputs.

macOS framework reference correction

Follow-up f29bb73 corrects the new test fixture's expectations for the installed macOS framework launcher. The launcher recreates __PYVENV_LAUNCHER__, presets the framework base, and canonicalizes the invocation directory (launcher source, getpath precedence). The fixture now combines the configured framework feature with exact installed-launcher file identity; direct embedded-app binaries keep the ordinary path expectations. All cases and exact assertions remain; no implementation-name guard or production change is added.

The corrected full snippet passes native RustPython and both CPython 3.14.7/3.14.8 references on Linux; the reference/native pytest harness also passes. Independent source review and normal hooks passed. Production files are identical to 68ea941, whose native binary was reused for this test-only validation. Actual macOS framework validation requires the new hosted run; it has not been reproduced locally. An arbitrary copied framework stub as the original parent interpreter remains outside this fixture's pre-existing scope.

@coderabbitai

coderabbitai Bot commented Oct 10, 2026 •

Copy link
Copy Markdown
Contributor

Review in Change Stack →

Note

Reviews paused

It looks like this branch is under active development. To avoid overwhelming you with review comments due to an influx of new commits, CodeRabbit has automatically paused this review. You can configure this behavior by changing the reviews.auto_review.auto_pause_after_reviewed_commits setting.

Use the following commands to manage reviews:

  • @coderabbitai resume to resume automatic reviews.
  • @coderabbitai review to trigger a single review.

Use the checkboxes below for quick actions:

  • ▶️ Resume reviews
  • 🔍 Trigger review

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration
  • Configuration used: Repository: RustPython/RustPython/.coderabbit.yml
  • Review profile: CHILL
  • Plan: Advanced
  • Run ID: 9c8e5a13-a4c4-4428-9110-2f5bd2798c9e






📥 Commits

Reviewing files that changed from the base of the PR and between 7a0e83f and 7032ba3.







📒 Files selected for processing (1)
  • extra_tests/snippets/stdlib_sys.py






Included review availability: This review used your included allowance. Your plan provides up to 10 included reviews per hour; 7 remain after this review.








📝 Walkthrough
📝 Walkthrough
📝 Walkthrough
📝 Walkthrough
📝 Walkthrough
📝 Walkthrough

Walkthrough

Unix venv base-executable selection now checks resolved executable symlinks before using the existing home-based fallback. New POSIX tests check executable paths and prefixes across symlink, copied executable, directory alias, and launcher cases.

Changes

Unix executable paths

Layer / File(s) Summary
Resolve executable paths and verify venv behavior
crates/vm/src/getpath.rs, extra_tests/snippets/stdlib_sys.py
A Unix-only helper follows up to 40 final-component symlinks and normalizes relative targets lexically. Venv base-executable selection uses a nonempty resolved target when it differs from the executable; the existing home-based fallback remains. POSIX tests cover symlink, copy, directory alias, and launcher cases.

Priority: ⬇️ Low

Estimated code review effort: 2 (Simple) | ~15 minutes

Change: Bug fix

Suggested reviewers: youknowone

















Merge Risk: ⚪ Minimal · up to 7032b

The change makes Unix virtual environments prefer resolved executable symlinks and adds tests for it. No merge-blocking problem was found in the supplied context. macOS framework behavior still needs its hosted CI run.

Pre-merge checks | Passed 4 | Failed 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage Warning Docstring coverage is 32.35% which is insufficient. The required threshold is 80.00%. Docstring coverage is scoped to functions touched by this diff. Analyzed 68 functions across 38 files. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check name Status Explanation
Linked Issues check Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check Passed Check skipped because no linked issues were found for this pull request.
Description Check Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check Passed The title clearly and concisely describes the main change: preferring resolved executable symlinks in POSIX virtual environments.

  • Fix all pre-merge checks with AI
✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create a new PR











  • Autofix · Keep fixing CodeRabbit findings and required CI, and resolving merge conflicts

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.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

@youknowone
youknowone marked this pull request as ready for review October 10, 2026 11:56
@youknowone
youknowone enabled auto-merge (squash) October 10, 2026 11:56
@chatgpt-codex-connector

chatgpt-codex-connector Bot commented Oct 10, 2026 •

Copy link
Copy Markdown

Codex Review Summary

This comment shows the latest Codex review activity on this pull request.

Review Status Commit Review trigger
📝 Code Review ✅ Completed 2026-10-11T16:15:55.669775Z 915a683 New commits
ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review" or "@codex security review".

Codex reacts with 👀 while any review is running, comments if it has suggestions, and reacts with 👍 once all reviews finish with no findings.

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 68ea9412c4

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment thread crates/vm/src/getpath.rs
Comment on lines +321 to +323
let end = bytes.iter().rposition(|&b| b == b'/');
let dirname = &bytes[..end.unwrap_or(bytes.len())];
let mut joined = PathBuf::from(std::ffi::OsStr::from_bytes(dirname));

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge Preserve the root when joining relative link targets

When a venv executable is directly under / (for example, /python with /pyvenv.cfg) and the executable symlink has a relative target such as usr/bin/python, rposition returns 0 and this slice drops the only root separator. The kernel resolves that target as /usr/bin/python, but calculate_base_executable now publishes usr/bin/python as sys._base_executable, so its meaning depends on the startup working directory and consumers such as venv can select the wrong interpreter; retain the root separator when the final component starts immediately after / (and likewise for a // root).

Useful? React with 👍 / 👎.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This edge is deliberate CPython 3.14 parity. Both 3.14.7 and 3.14.8 truncate the final separator before joining a relative target: getpath.c. The join helper adds no separator for an empty dirname: fileutils.c. Consequently, /python with target usr/bin/python becomes usr/bin/python, while //python becomes /usr/bin/python. The current helper reproduces that behavior; retaining these roots would diverge from the reference contract. This particular edge was checked against the source, without creating or testing root-level filesystem paths. I am keeping the implementation unchanged.

auto-merge was automatically disabled October 10, 2026 13:41

Head branch was pushed to by a user without write access

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: f29bb731e2

ℹ️ About Codex in GitHub

Codex has been enabled to automatically review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

When you sign up for Codex through ChatGPT, Codex can also answer questions or update the PR, like "@codex address that feedback".



# A venv's symlink target takes precedence over home/<invoked name>.
if os.name == "posix" and sys.platform not in ("wasi", "emscripten"):

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P1 Badge Remove the prohibited regression-test body

This block adds synthetic test data, control flow, and assertions to an existing test file, but the repository policy permits test-file changes only for adding or removing expected-failure decorators; the regression coverage therefore needs to be removed from stdlib_sys.py rather than added here.

AGENTS.md reference: AGENTS.md:L273-L279

Useful? React with 👍 / 👎.

@youknowdot
youknowdot force-pushed the fix-venv-executable-symlinks branch from f29bb73 to 1601d76 Compare October 11, 2026 03:08
@chatgpt-codex-connector

Copy link
Copy Markdown

Codex usage limits have been reached for code reviews. Please check with the admins of this repo to increase the limits by adding credits.
Credits must be used to enable repository wide code reviews.

@youknowdot
youknowdot force-pushed the fix-venv-executable-symlinks branch from 1601d76 to 7a0e83f Compare October 11, 2026 03:21
@chatgpt-codex-connector

Copy link
Copy Markdown

Codex usage limits have been reached for code reviews. Please check with the admins of this repo to increase the limits by adding credits.
Credits must be used to enable repository wide code reviews.

@youknowone
youknowone changed the base branch from main to stack/python-3.15-8950 October 11, 2026 03:25
@youknowdot
youknowdot force-pushed the fix-venv-executable-symlinks branch from 7a0e83f to 7032ba3 Compare October 11, 2026 04:07
@youknowone
youknowone changed the base branch from stack/python-3.15-8950 to main October 11, 2026 04:08
@youknowdot
youknowdot force-pushed the fix-venv-executable-symlinks branch from 7032ba3 to e87b00c Compare October 11, 2026 04:14
@github-actions

Copy link
Copy Markdown
Contributor

📦 Library Dependencies

The following Lib/ modules were modified. Here are their dependencies:

[ ] test: cpython/Lib/test/test_mmap.py (TODO: 19)

dependencies:

dependent tests: (2 tests)

  • mmap: test_os
    • multiprocessing.shared_memory: test_genericalias

Legend:

  • [+] path exists in CPython
  • [x] up-to-date, [ ] outdated

Resolve executable symlinks for virtual-environment paths while retaining macOS framework launcher behavior. Include directory-canonicalization and launcher regressions, using core for UTF-8 checks.

Assisted-by: OpenAI Codex:model identifier unavailable
@youknowdot
youknowdot force-pushed the fix-venv-executable-symlinks branch from e87b00c to 915a683 Compare October 11, 2026 16:08
@youknowone
youknowone merged commit f39da82 into RustPython:main Oct 11, 2026
29 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants