Skip to content

Commit 4ce731f

Browse files
committed
Refine the getpath implementation for pyvenv case, and get the tests to pass
1 parent 8dca58a commit 4ce731f

File tree

3 files changed

+35
-26
lines changed

3 files changed

+35
-26
lines changed

Lib/test/test_embed.py

Lines changed: 4 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -1618,13 +1618,7 @@ def test_init_pyvenv_cfg(self):
16181618
tempfile.TemporaryDirectory() as pyvenv_home:
16191619
ver = sys.version_info
16201620

1621-
if not MS_WINDOWS:
1622-
lib_dynload = os.path.join(pyvenv_home,
1623-
sys.platlibdir,
1624-
f'python{ver.major}.{ver.minor}{ABI_THREAD}',
1625-
'lib-dynload')
1626-
os.makedirs(lib_dynload)
1627-
else:
1621+
if MS_WINDOWS:
16281622
lib_folder = os.path.join(pyvenv_home, 'Lib')
16291623
os.makedirs(lib_folder)
16301624
# getpath.py uses Lib\os.py as the LANDMARK
@@ -1639,9 +1633,7 @@ def test_init_pyvenv_cfg(self):
16391633
print("include-system-site-packages = false", file=fp)
16401634

16411635
paths = self.module_search_paths()
1642-
if not MS_WINDOWS:
1643-
paths[-1] = lib_dynload
1644-
else:
1636+
if MS_WINDOWS:
16451637
paths = [
16461638
os.path.join(tmpdir, os.path.basename(paths[0])),
16471639
pyvenv_home,
@@ -1650,7 +1642,7 @@ def test_init_pyvenv_cfg(self):
16501642

16511643
executable = self.test_exe
16521644
base_executable = os.path.join(pyvenv_home, os.path.basename(executable))
1653-
exec_prefix = pyvenv_home
1645+
exec_prefix = sys.base_exec_prefix
16541646
config = {
16551647
'base_prefix': sysconfig.get_config_var("prefix"),
16561648
'base_exec_prefix': exec_prefix,
@@ -1659,16 +1651,15 @@ def test_init_pyvenv_cfg(self):
16591651
'base_executable': base_executable,
16601652
'executable': executable,
16611653
'module_search_paths': paths,
1654+
'use_frozen_modules': bool(not support.Py_DEBUG),
16621655
}
16631656
if MS_WINDOWS:
16641657
config['base_prefix'] = pyvenv_home
16651658
config['stdlib_dir'] = os.path.join(pyvenv_home, 'Lib')
1666-
config['use_frozen_modules'] = bool(not support.Py_DEBUG)
16671659
else:
16681660
# cannot reliably assume stdlib_dir here because it
16691661
# depends too much on our build. But it ought to be found
16701662
config['stdlib_dir'] = self.IGNORE_CONFIG
1671-
config['use_frozen_modules'] = bool(not support.Py_DEBUG)
16721663

16731664
env = self.copy_paths_by_env(config)
16741665
self.check_all_configs("test_init_compat_config", config,

Lib/test/test_venv.py

Lines changed: 22 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -684,7 +684,6 @@ def test_zippath_from_non_installed_posix(self):
684684
shutil.copy2(sys.executable, bindir)
685685
libdir = os.path.join(non_installed_dir, platlibdir, self.lib[1])
686686
os.makedirs(libdir)
687-
landmark = os.path.join(libdir, "os.py")
688687
abi_thread = "t" if sysconfig.get_config_var("Py_GIL_DISABLED") else ""
689688
stdlib_zip = f"python{sys.version_info.major}{sys.version_info.minor}{abi_thread}"
690689
zip_landmark = os.path.join(non_installed_dir,
@@ -748,9 +747,9 @@ def test_zippath_from_non_installed_posix(self):
748747
subprocess.check_call(cmd, env=child_env)
749748
# Now check the venv created from the non-installed python has
750749
# correct zip path in pythonpath.
751-
cmd = [self.envpy(), '-S', '-c', 'import sys; print(sys.path)']
750+
cmd = [self.envpy(), '-S', '-c', "import sys; print('\\n'.join(sys.path))"]
752751
out, err = check_output(cmd)
753-
self.assertTrue(zip_landmark.encode() in out)
752+
self.assertIn(zip_landmark, out.decode())
754753

755754
@unittest.skipIf(os.name == 'nt', 'not relevant on Windows')
756755
@requireVenvCreate
@@ -764,8 +763,9 @@ def test_venv_from_venv_with_symlink(self):
764763
self.addCleanup(rmtree, public_prefix)
765764
public_bin_dir = os.path.join(public_prefix, 'bin')
766765
os.mkdir(public_bin_dir)
767-
public_exe = os.path.join(public_bin_dir, self.exe)
766+
public_exe = os.path.join(public_bin_dir, 'python3')
768767
os.symlink(sys.executable, public_exe)
768+
underlying_prefix = sys.base_prefix
769769
cmd = [public_exe,
770770
"-m",
771771
"venv",
@@ -796,6 +796,24 @@ def test_venv_from_venv_with_symlink(self):
796796
contents = (pathlib.Path(second_venv) / 'pyvenv.cfg').read_text()
797797
self.assertIn(f'home = {public_bin_dir}\n', contents)
798798

799+
# Now validate the important sys values.
800+
venv2_sys, _ = check_output(
801+
[os.path.join(second_venv, 'bin', 'python3'),
802+
'-S', '-c',
803+
"import sys; print(f'{sys._base_executable=}\\n{sys.base_exec_prefix=}\\n{sys.base_prefix=}')"],
804+
encoding='utf8',
805+
)
806+
self.assertEqual(
807+
'\n'.join([
808+
# The base executable should be the public one, while the exec_prefix can be the
809+
# internal one (and the same as the original interpreter's base_prefix).
810+
f"sys._base_executable='{public_exe}'",
811+
f"sys.base_exec_prefix='{underlying_prefix}'",
812+
f"sys.base_prefix='{underlying_prefix}'",
813+
]),
814+
venv2_sys.strip(),
815+
)
816+
799817
@requireVenvCreate
800818
def test_activate_shell_script_has_no_dos_newlines(self):
801819
"""

Modules/getpath.py

Lines changed: 9 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -383,22 +383,22 @@ def search_up(prefix, *landmarks, test=isfile):
383383
# it in 'home'.
384384
if not base_executable:
385385
_home_executable = joinpath(executable_dir, DEFAULT_PROGRAM_NAME)
386-
_realpath_executable = None
386+
_executable_realpath = None
387387
try:
388-
_realpath_executable = realpath(executable)
388+
_executable_realpath = realpath(executable)
389389

390390
# If the realpath of the executable identified in home is the same as
391-
# the realpath of the venv's executable use the (potentially not fully
392-
# resolved via realpath) path from home.
393-
if realpath(_home_executable) == _realpath_executable:
391+
# the realpath of the venv's executable, then use the (potentially not
392+
# fully resolved via realpath) path from home.
393+
if realpath(_home_executable) == _executable_realpath:
394394
base_executable = _home_executable
395395
except OSError:
396396
pass
397397
if not base_executable:
398-
if _realpath_executable and _realpath_executable != executable:
398+
if _executable_realpath and _executable_realpath != executable:
399399
# Try to resolve symlinked executables, since that may be
400400
# more accurate than assuming the executable in 'home'.
401-
base_executable = _realpath_executable
401+
base_executable = _executable_realpath
402402
if not base_executable:
403403
base_executable = joinpath(executable_dir, basename(executable))
404404
# It's possible "python" is executed from within a posix venv but that
@@ -407,10 +407,10 @@ def search_up(prefix, *landmarks, test=isfile):
407407
#
408408
# In this case, try to fall back to known alternatives
409409
if os_name != 'nt' and not isfile(base_executable):
410-
base_exe = basename(executable)
410+
_base_exe = basename(executable)
411411
for candidate in (DEFAULT_PROGRAM_NAME, f'python{VERSION_MAJOR}.{VERSION_MINOR}'):
412412
candidate += EXE_SUFFIX if EXE_SUFFIX else ''
413-
if base_exe == candidate:
413+
if _base_exe == candidate:
414414
continue
415415
candidate = joinpath(executable_dir, candidate)
416416
# Only set base_executable if the candidate exists.

0 commit comments

Comments
 (0)