Skip to content

gh-106045: Fix venv creation from a python executable symlink - #115237

Closed
mayeut wants to merge 3 commits into
python:mainfrom
mayeut:venv-home-follow-symlink
Closed

mayeut wants to merge 3 commits into
python:mainfrom
mayeut:venv-home-follow-symlink

Conversation

@mayeut

@mayeut mayeut commented Feb 10, 2024 •

Copy link
Copy Markdown
Contributor

@mayeut
mayeut requested a review from vsajip as a code owner February 10, 2024 10:58
@mayeut
mayeut force-pushed the venv-home-follow-symlink branch from 91e8d28 to ad36335 Compare May 11, 2024 17:04
@mayeut
mayeut marked this pull request as draft September 28, 2024 08:53
@mayeut
mayeut force-pushed the venv-home-follow-symlink branch 2 times, most recently from ca424f1 to 340d9c2 Compare September 28, 2024 10:45
@mayeut
mayeut marked this pull request as ready for review September 28, 2024 11:15

ghost left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

The PR looks good 👍

Comment thread Lib/venv/__init__.py Outdated
Comment on lines +169 to +175
executable_ = os.path.abspath(executable)
while os.path.islink(executable_):
link = os.readlink(executable_)
if os.path.isabs(link):
executable_ = link
else:
executable_ = os.path.join(os.path.dirname(executable_), link)

ghost Jan 8, 2025

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Can you move this to a helper function? This way the ensure_directories and symlink resolving logic is clearly separated,

ghost Jan 11, 2025

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.

done

Comment thread Lib/test/test_venv.py Outdated
subprocess.check_call(cmd)
data = self.get_text_file_contents('pyvenv.cfg')
self.assertIn('home = %s' % tree_symlink, data)
self.assertIn('executable = %s' %

ghost Jan 8, 2025

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

nitpick: Since this is so path-operation heavy, it would be nice to use pathlib here instead.

ghost Jan 11, 2025

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.

done

ghost left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

I concur with @FFY00's comments. Also, as another nitpick, why use the name executable_ as a local variable? The trailing underscore is not a common thing to see, in my experience,

ghost left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

My view is that this is doing the right thing, but in the wrong place. Instead I think we should not resolve the executable path at all in venv, and instead we should resolve the prefix based on the executable symlink at Python startup (in getpath.py).

Based on what I understand, the issue that this PR is fixing was just fixed by #127974.

Comment thread Lib/venv/__init__.py Outdated
# we don't want to overwrite the executable used in context
executable_ = os.path.abspath(executable)
while os.path.islink(executable_):
link = os.readlink(executable_)

ghost Jan 9, 2025

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Technically we need to watch out for circular links. I think having this in a separate function (as suggested) will make that less painful when implementing.

FWIW, I don't know why there isn't something in the standard library for recursively resolving a symlink (without recursively resolving all child paths as realpath does). Perhaps one for Python ideas?

ghost Jan 11, 2025

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.

done

@mayeut

ghost commented Jan 11, 2025

Copy link
Copy Markdown
Contributor Author

Based on what I understand, the issue that this PR is fixing was just fixed by #127974.

It appears that the linked PR does not resolve the issue.
Here are the steps I used on macOS on the main branch:

./configure --with-pydebug && make -j
mkdir ../temp-test
ln -s $(pwd)/python.exe ../temp-test/python
../temp-test/python -m venv ../temp-test/temp-test-venv
Error: Command '['.../temp-test/temp-test-venv/bin/python', '-m', 'ensurepip', '--upgrade', '--default-pip']' returned non-zero exit status 1.

@FFY00

ghost commented Jan 11, 2025

Copy link
Copy Markdown
Member

That PR builds on top of GH-127972, so it only works with --enable-shared.

@mayeut
mayeut force-pushed the venv-home-follow-symlink branch from 340d9c2 to f9ef949 Compare January 11, 2025 11:41
Comment thread Lib/venv/__init__.py
- we stop if a candidate does not resolve to the same file
(this can happen with normpath)
"""
result = os.path.abspath(path)

ghost Jan 12, 2025

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.

os.path.abspath is done first as was used before. It does normalize the path which may end-up with an invalid path in case of symlinks (e.g. "symlink_dir/../segment").

@python-cla-bot

ghost commented Apr 18, 2025 •

Copy link
Copy Markdown

All commit authors signed the Contributor License Agreement.

CLA signed

@github-actions

ghost commented Apr 15, 2026

Copy link
Copy Markdown

This PR is stale because it has been open for 30 days with no activity.

@gaborbernat

ghost commented Jun 5, 2026

Copy link
Copy Markdown
Contributor

This is approved but now shows as conflicting — it needs a rebase onto main to merge. For cross-tracking, virtualenv has the same unresolved-symlink behavior in pyvenv.cfg (pypa/virtualenv#3157).

@github-actions github-actions Bot removed the stale Stale PR or inactive for long period of time. label Jun 6, 2026
@github-actions

ghost commented Sep 7, 2026

Copy link
Copy Markdown

This PR is stale because it has been open for 90 days with no activity.

@github-actions github-actions Bot added the stale Stale PR or inactive for long period of time. label Sep 7, 2026
@ambv

ghost commented Oct 20, 2026

Copy link
Copy Markdown
Contributor

This PR is superseded by #156483, a newer open pull request for the same issue (gh-106045), and it no longer merges cleanly. Closing to cull the number of open pull requests. Do not reopen this pull request without getting a go-ahead from a triager or core developer.

@ambv ambv closed this Oct 20, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

awaiting merge stale Stale PR or inactive for long period of time.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

6 participants