From b0967fe4ed2e0e15f14ea574f82970a3fd4a5556 Mon Sep 17 00:00:00 2001 From: "Miss Islington (bot)" <31488909+miss-islington@users.noreply.github.com> Date: Thu, 21 Mar 2019 10:33:40 -0700 Subject: [PATCH] bpo-35978: Correctly skips venv tests in venvs (GH-12220) Also fixes venvs from the build directory on Windows. (cherry picked from commit 8bba81fd55873148c65b7d0e6a6effbd63048c76) Co-authored-by: Steve Dower --- Lib/test/test_venv.py | 15 ++++++++++----- Lib/venv/__init__.py | 19 ++++++++++++------- 2 files changed, 22 insertions(+), 12 deletions(-) diff --git a/Lib/test/test_venv.py b/Lib/test/test_venv.py index 347544a6772..19a5aab7a21 100644 --- a/Lib/test/test_venv.py +++ b/Lib/test/test_venv.py @@ -24,8 +24,12 @@ try: except ImportError: ctypes = None -skipInVenv = unittest.skipIf(sys.prefix != sys.base_prefix, - 'Test not appropriate in a venv') +# Platforms that set sys._base_executable can create venvs from within +# another venv, so no need to skip tests that require venv.create(). +requireVenvCreate = unittest.skipUnless( + hasattr(sys, '_base_executable') + or sys.prefix == sys.base_prefix, + 'cannot run venv.create from within a venv on this platform') def check_output(cmd, encoding=None): p = subprocess.Popen(cmd, @@ -118,7 +122,7 @@ class BasicTest(BaseTest): context = builder.ensure_directories(self.env_dir) self.assertEqual(context.prompt, '(My prompt) ') - @skipInVenv + @requireVenvCreate def test_prefixes(self): """ Test that the prefix values are as expected. @@ -254,7 +258,7 @@ class BasicTest(BaseTest): # run the test, the pyvenv.cfg in the venv created in the test will # point to the venv being used to run the test, and we lose the link # to the source build - so Python can't initialise properly. - @skipInVenv + @requireVenvCreate def test_executable(self): """ Test that the sys.executable value is as expected. @@ -298,6 +302,7 @@ class BasicTest(BaseTest): ) self.assertEqual(out.strip(), '0') + @requireVenvCreate def test_multiprocessing(self): """ Test that the multiprocessing is able to spawn. @@ -311,7 +316,7 @@ class BasicTest(BaseTest): 'print(Pool(1).apply_async("Python".lower).get(3))']) self.assertEqual(out.strip(), "python".encode()) -@skipInVenv +@requireVenvCreate class EnsurePipTest(BaseTest): """Test venv module installation of pip.""" def assert_pip_not_installed(self): diff --git a/Lib/venv/__init__.py b/Lib/venv/__init__.py index d5ab38958bb..4fbd954f200 100644 --- a/Lib/venv/__init__.py +++ b/Lib/venv/__init__.py @@ -176,18 +176,23 @@ class EnvBuilder: # On Windows, we rewrite symlinks to our base python.exe into # copies of venvlauncher.exe basename, ext = os.path.splitext(os.path.basename(src)) - if basename.endswith('_d'): - ext = '_d' + ext - basename = basename[:-2] - if sysconfig.is_python_build(True): + srcfn = os.path.join(os.path.dirname(__file__), + "scripts", + "nt", + basename + ext) + # Builds or venv's from builds need to remap source file + # locations, as we do not put them into Lib/venv/scripts + if sysconfig.is_python_build(True) or not os.path.isfile(srcfn): + if basename.endswith('_d'): + ext = '_d' + ext + basename = basename[:-2] if basename == 'python': basename = 'venvlauncher' elif basename == 'pythonw': basename = 'venvwlauncher' - scripts = os.path.dirname(src) + src = os.path.join(os.path.dirname(src), basename + ext) else: - scripts = os.path.join(os.path.dirname(__file__), "scripts", "nt") - src = os.path.join(scripts, basename + ext) + src = srcfn shutil.copyfile(src, dst)