Skip to content

Commit

Permalink
pythongh-106045: Fix venv creation from a python executable symlink
Browse files Browse the repository at this point in the history
  • Loading branch information
mayeut committed Sep 28, 2024
1 parent 165ed68 commit 7a55f1b
Show file tree
Hide file tree
Showing 4 changed files with 61 additions and 1 deletion.
48 changes: 48 additions & 0 deletions Lib/test/test_venv.py
Original file line number Diff line number Diff line change
Expand Up @@ -791,6 +791,54 @@ def test_venv_same_path(self):
else:
self.assertFalse(same_path(path1, path2))

@requires_subprocess()
@unittest.skipIf(os.name == 'nt', 'not relevant on Windows')
@unittest.skipUnless(can_symlink(), 'Needs symlinks')
def test_executable_symlink(self):
"""
Test creation using a symlink to python executable.
"""
rmtree(self.env_dir)
with tempfile.TemporaryDirectory() as symlink_dir:
executable_symlink = os.path.join(
os.path.realpath(symlink_dir),
os.path.basename(sys.executable))
os.symlink(os.path.abspath(sys.executable), executable_symlink)
cmd = [executable_symlink, "-m", "venv", "--without-pip",
self.env_dir]
subprocess.check_call(cmd)
data = self.get_text_file_contents('pyvenv.cfg')
executable = sys._base_executable
path = os.path.dirname(executable)
self.assertIn('home = %s' % path, data)
self.assertIn('executable = %s' %
os.path.realpath(sys.executable), data)

@requires_subprocess()
@unittest.skipIf(os.name == 'nt', 'not relevant on Windows')
@unittest.skipUnless(can_symlink(), 'Needs symlinks')
def test_tree_symlink(self):
"""
Test creation using a symlink to python tree.
"""
rmtree(self.env_dir)
tree_abspath = os.path.dirname(os.path.abspath(sys.executable))
with tempfile.TemporaryDirectory() as symlink_dir:
tree_symlink = os.path.join(
os.path.realpath(symlink_dir),
os.path.basename(tree_abspath))
executable_symlink = os.path.join(
tree_symlink,
os.path.basename(sys.executable))
os.symlink(tree_abspath, tree_symlink)
cmd = [executable_symlink, "-m", "venv", "--without-pip",
self.env_dir]
subprocess.check_call(cmd)
data = self.get_text_file_contents('pyvenv.cfg')
self.assertIn('home = %s' % tree_symlink, data)
self.assertIn('executable = %s' %
os.path.realpath(sys.executable), data)

@requireVenvCreate
class EnsurePipTest(BaseTest):
"""Test venv module installation of pip."""
Expand Down
11 changes: 10 additions & 1 deletion Lib/venv/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -164,7 +164,16 @@ def create_if_needed(d):
'Python interpreter. Provide an explicit path or '
'check that your PATH environment variable is '
'correctly set.')
dirname, exename = os.path.split(os.path.abspath(executable))
# only resolve executable symlinks, not the full chain, see gh-106045
# 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_)
if os.path.isabs(link):
executable_ = link
else:
executable_ = os.path.join(os.path.dirname(executable_), link)
dirname, exename = os.path.split(executable_)
if sys.platform == 'win32':
# Always create the simplest name in the venv. It will either be a
# link back to executable, or a copy of the appropriate launcher
Expand Down
1 change: 1 addition & 0 deletions Misc/ACKS
Original file line number Diff line number Diff line change
Expand Up @@ -417,6 +417,7 @@ Eric Daniel
Scott David Daniels
Derzsi Dániel
Lawrence D'Anna
Matthieu Darbois
Ben Darnell
Kushal Das
Jonathan Dasteel
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
Fix ``venv`` creation from a python executable symlink. Patch by Matthieu
Darbois.

0 comments on commit 7a55f1b

Please sign in to comment.