Skip to content

Commit b0967fe

Browse files
bpo-35978: Correctly skips venv tests in venvs (GH-12220)
Also fixes venvs from the build directory on Windows. (cherry picked from commit 8bba81f) Co-authored-by: Steve Dower <[email protected]>
1 parent b058a97 commit b0967fe

File tree

2 files changed

+22
-12
lines changed

2 files changed

+22
-12
lines changed

Lib/test/test_venv.py

Lines changed: 10 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -24,8 +24,12 @@
2424
except ImportError:
2525
ctypes = None
2626

27-
skipInVenv = unittest.skipIf(sys.prefix != sys.base_prefix,
28-
'Test not appropriate in a venv')
27+
# Platforms that set sys._base_executable can create venvs from within
28+
# another venv, so no need to skip tests that require venv.create().
29+
requireVenvCreate = unittest.skipUnless(
30+
hasattr(sys, '_base_executable')
31+
or sys.prefix == sys.base_prefix,
32+
'cannot run venv.create from within a venv on this platform')
2933

3034
def check_output(cmd, encoding=None):
3135
p = subprocess.Popen(cmd,
@@ -118,7 +122,7 @@ def test_prompt(self):
118122
context = builder.ensure_directories(self.env_dir)
119123
self.assertEqual(context.prompt, '(My prompt) ')
120124

121-
@skipInVenv
125+
@requireVenvCreate
122126
def test_prefixes(self):
123127
"""
124128
Test that the prefix values are as expected.
@@ -254,7 +258,7 @@ def test_symlinking(self):
254258
# run the test, the pyvenv.cfg in the venv created in the test will
255259
# point to the venv being used to run the test, and we lose the link
256260
# to the source build - so Python can't initialise properly.
257-
@skipInVenv
261+
@requireVenvCreate
258262
def test_executable(self):
259263
"""
260264
Test that the sys.executable value is as expected.
@@ -298,6 +302,7 @@ def test_unicode_in_batch_file(self):
298302
)
299303
self.assertEqual(out.strip(), '0')
300304

305+
@requireVenvCreate
301306
def test_multiprocessing(self):
302307
"""
303308
Test that the multiprocessing is able to spawn.
@@ -311,7 +316,7 @@ def test_multiprocessing(self):
311316
'print(Pool(1).apply_async("Python".lower).get(3))'])
312317
self.assertEqual(out.strip(), "python".encode())
313318

314-
@skipInVenv
319+
@requireVenvCreate
315320
class EnsurePipTest(BaseTest):
316321
"""Test venv module installation of pip."""
317322
def assert_pip_not_installed(self):

Lib/venv/__init__.py

Lines changed: 12 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -176,18 +176,23 @@ def symlink_or_copy(self, src, dst, relative_symlinks_ok=False):
176176
# On Windows, we rewrite symlinks to our base python.exe into
177177
# copies of venvlauncher.exe
178178
basename, ext = os.path.splitext(os.path.basename(src))
179-
if basename.endswith('_d'):
180-
ext = '_d' + ext
181-
basename = basename[:-2]
182-
if sysconfig.is_python_build(True):
179+
srcfn = os.path.join(os.path.dirname(__file__),
180+
"scripts",
181+
"nt",
182+
basename + ext)
183+
# Builds or venv's from builds need to remap source file
184+
# locations, as we do not put them into Lib/venv/scripts
185+
if sysconfig.is_python_build(True) or not os.path.isfile(srcfn):
186+
if basename.endswith('_d'):
187+
ext = '_d' + ext
188+
basename = basename[:-2]
183189
if basename == 'python':
184190
basename = 'venvlauncher'
185191
elif basename == 'pythonw':
186192
basename = 'venvwlauncher'
187-
scripts = os.path.dirname(src)
193+
src = os.path.join(os.path.dirname(src), basename + ext)
188194
else:
189-
scripts = os.path.join(os.path.dirname(__file__), "scripts", "nt")
190-
src = os.path.join(scripts, basename + ext)
195+
src = srcfn
191196

192197
shutil.copyfile(src, dst)
193198

0 commit comments

Comments
 (0)