bpo-45337: Use the realpath of the new executable when creating a venv on Windows (GH-28663)

This commit is contained in:
Steve Dower 2021-10-07 21:26:12 +01:00 committed by GitHub
parent 8deb7afbaa
commit 6811fdaec8
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
3 changed files with 29 additions and 9 deletions

View File

@ -150,14 +150,20 @@ def test_prompt(self):
def test_upgrade_dependencies(self):
builder = venv.EnvBuilder()
bin_path = 'Scripts' if sys.platform == 'win32' else 'bin'
python_exe = 'python.exe' if sys.platform == 'win32' else 'python'
python_exe = os.path.split(sys.executable)[1]
with tempfile.TemporaryDirectory() as fake_env_dir:
expect_exe = os.path.normcase(
os.path.join(fake_env_dir, bin_path, python_exe)
)
if sys.platform == 'win32':
expect_exe = os.path.normcase(os.path.realpath(expect_exe))
def pip_cmd_checker(cmd):
cmd[0] = os.path.normcase(cmd[0])
self.assertEqual(
cmd,
[
os.path.join(fake_env_dir, bin_path, python_exe),
expect_exe,
'-m',
'pip',
'install',

View File

@ -142,6 +142,20 @@ def create_if_needed(d):
context.bin_name = binname
context.env_exe = os.path.join(binpath, exename)
create_if_needed(binpath)
# Assign and update the command to use when launching the newly created
# environment, in case it isn't simply the executable script (e.g. bpo-45337)
context.env_exec_cmd = context.env_exe
if sys.platform == 'win32':
# bpo-45337: Fix up env_exec_cmd to account for file system redirections.
# Some redirects only apply to CreateFile and not CreateProcess
real_env_exe = os.path.realpath(context.env_exe)
if os.path.normcase(real_env_exe) != os.path.normcase(context.env_exe):
logger.warning('Actual environment location may have moved due to '
'redirects, links or junctions.\n'
' Requested location: "%s"\n'
' Actual location: "%s"',
context.env_exe, real_env_exe)
context.env_exec_cmd = real_env_exe
return context
def create_configuration(self, context):
@ -294,8 +308,8 @@ def _setup_pip(self, context):
# We run ensurepip in isolated mode to avoid side effects from
# environment vars, the current directory and anything else
# intended for the global Python environment
cmd = [context.env_exe, '-Im', 'ensurepip', '--upgrade',
'--default-pip']
cmd = [context.env_exec_cmd, '-Im', 'ensurepip', '--upgrade',
'--default-pip']
subprocess.check_output(cmd, stderr=subprocess.STDOUT)
def setup_scripts(self, context):
@ -395,11 +409,7 @@ def upgrade_dependencies(self, context):
logger.debug(
f'Upgrading {CORE_VENV_DEPS} packages in {context.bin_path}'
)
if sys.platform == 'win32':
python_exe = os.path.join(context.bin_path, 'python.exe')
else:
python_exe = os.path.join(context.bin_path, 'python')
cmd = [python_exe, '-m', 'pip', 'install', '--upgrade']
cmd = [context.env_exec_cmd, '-m', 'pip', 'install', '--upgrade']
cmd.extend(CORE_VENV_DEPS)
subprocess.check_call(cmd)

View File

@ -0,0 +1,4 @@
venv now warns when the created environment may need to be accessed at a
different path, due to redirections, links or junctions. It also now
correctly installs or upgrades components when the alternate path is
required.