diff --git a/Lib/test/test_venv.py b/Lib/test/test_venv.py index 0b2c7a0258d..6822d567e42 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, @@ -126,7 +130,7 @@ class BasicTest(BaseTest): self.assertEqual(context.prompt, '(My prompt) ') self.assertIn("prompt = 'My prompt'\n", data) - @skipInVenv + @requireVenvCreate def test_prefixes(self): """ Test that the prefix values are as expected. @@ -262,7 +266,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. @@ -306,6 +310,7 @@ class BasicTest(BaseTest): ) self.assertEqual(out.strip(), '0') + @requireVenvCreate def test_multiprocessing(self): """ Test that the multiprocessing is able to spawn. @@ -319,7 +324,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 a309b861c5f..5e6d375e95a 100644 --- a/Lib/venv/__init__.py +++ b/Lib/venv/__init__.py @@ -178,18 +178,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)