-
-
Notifications
You must be signed in to change notification settings - Fork 31.6k
gh-106045: Fix venv
creation from a python executable symlink
#115237
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: main
Are you sure you want to change the base?
Conversation
mayeut
commented
Feb 10, 2024
•
edited by Eclips4
Loading
edited by Eclips4
- Issue: venv base path does not resolve symlinks using realpath() #106045
91e8d28
to
ad36335
Compare
ca424f1
to
340d9c2
Compare
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The PR looks good 👍
Lib/venv/__init__.py
Outdated
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) |
There was a problem hiding this comment.
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,
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
done
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' % |
There was a problem hiding this comment.
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.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
done
There was a problem hiding this comment.
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,
There was a problem hiding this comment.
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.
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_) |
There was a problem hiding this comment.
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?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
done
It appears that the linked PR does not resolve the issue.
|
That PR builds on top of GH-127972, so it only works with |
340d9c2
to
f9ef949
Compare
- we stop if a candidate does not resolve to the same file | ||
(this can happen with normpath) | ||
""" | ||
result = os.path.abspath(path) |
There was a problem hiding this comment.
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").
The following commit authors need to sign the Contributor License Agreement: |