8000 Fixes tests requiring extra environment values on Windows (GH-9463) · python/cpython@6c9e109 · GitHub
[go: up one dir, main page]

Skip to content

Commit 6c9e109

Browse files
authored
Fixes tests requiring extra environment values on Windows (GH-9463)
1 parent 4fb672f commit 6c9e109

File tree

7 files changed

+120
-89
lines changed

7 files changed

+120
-89
lines changed

Lib/distutils/tests/test_bdist.py

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -39,6 +39,9 @@ def test_skip_build(self):
3939

4040
for name in names:
4141
subcmd = cmd.get_finalized_command(name)
42+
if getattr(subcmd, '_unsupported', False):
43+
# command is not supported on this build
44+
continue
4245
self.assertTrue(subcmd.skip_build,
4346
'%s should take --skip-build from bdist' % name)
4447

Lib/distutils/tests/test_bdist_wininst.py

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,8 @@
55
from distutils.command.bdist_wininst import bdist_wininst
66
from distutils.tests import support
77

8+
@unittest.skipIf(getattr(bdist_wininst, '_unsupported', False),
9+
'bdist_wininst is not supported in this install')
810
class BuildWinInstTestCase(support.TempdirManager,
911
support.LoggingSilencer,
1012
unittest.TestCase):

Lib/test/test_platform.py

Lines changed: 21 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33
import platform
44
import subprocess
55
import sys
6+
import sysconfig
67
import tempfile
78
import unittest
89
import warnings
@@ -16,29 +17,34 @@ def test_architecture(self):
1617
@support.skip_unless_symlink
1718
def test_architecture_via_symlink(self): # issue3762
1819
# On Windows, the EXE needs to know where pythonXY.dll and *.pyd is at
19-
# so we add the directory to the path and PYTHONPATH.
20+
# so we add the directory to the path, PYTHONHOME and PYTHONPATH.
21+
env = None
2022
if sys.platform == "win32":
21-
def restore_environ(old_env):
22-
os.environ.clear()
23-
os.environ.update(old_env)
24-
25-
self.addCleanup(restore_environ, dict(os.environ))
26-
27-
os.environ["Path"] = "{};{}".format(
28-
os.path.dirname(sys.executable), os.environ["Path"])
29-
os.environ["PYTHONPATH"] = os.path.dirname(sys.executable)
30-
31-
def get(python):
23+
env = {k.upper(): os.environ[k] for k in os.environ}
24+
env["PATH"] = "{};{}".format(
25+
os.path.dirname(sys.executable), env.get("PATH", ""))
26+
env["PYTHONHOME"] = os.path.dirname(sys.executable)
27+
if sysconfig.is_python_build(True):
28+
env["PYTHONPATH"] = os.path.dirname(os.__file__)
29+
30+
def get(python, env=None):
3231
cmd = [python, '-c',
3332
'import platform; print(platform.architecture())']
34-
p = subprocess.Popen(cmd, stdout=subprocess.PIPE)
35-
return p.communicate()
33+
p = subprocess.Popen(cmd, stdout=subprocess.PIPE,
34+
stderr=subprocess.PIPE, env=env)
35+
r = p.communicate()
36+
if p.returncode:
37+
print(repr(r[0]))
38+
print(repr(r[1]), file=sys.stderr)
39+
self.fail('unexpected return code: {0} (0x{0:08X})'
40+
.format(p.returncode))
41+
return r
3642

3743
real = os.path.realpath(sys.executable)
3844
link = os.path.abspath(support.TESTFN)
3945
os.symlink(real, link)
4046
try:
41-
self.assertEqual(get(real), get(link))
47+
self.assertEqual(get(real), get(link, env=env))
4248
finally:
4349
os.remove(link)
4450

Lib/test/test_site.py

Lines changed: 43 additions & 35 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,8 @@
66
"""
77
import unittest
88
import test.support
9-
from test.support import captured_stderr, TESTFN, EnvironmentVarGuard
9+
from test.support import (captured_stderr, TESTFN, EnvironmentVarGuard,
10+
change_cwd)
1011
import builtins
1112
import os
1213
import sys
@@ -345,40 +346,47 @@ def test_abs_paths(self):
345346
# __file__ if abs_paths() does not get run. sys and builtins (the
346347
# only other modules imported before site.py runs) do not have
347348
# __file__ or __cached__ because they are built-in.
348-
parent = os.path.relpath(os.path.dirname(os.__file__))
349-
env = os.environ.copy()
350-
env['PYTHONPATH'] = parent
351-
code = ('import os, sys',
352-
# use ASCII to avoid locale issues with non-ASCII directories
353-
'os_file = os.__file__.encode("ascii", "backslashreplace")',
354-
r'sys.stdout.buffer.write(os_file + b"\n")',
355-
'os_cached = os.__cached__.encode("ascii", "backslashreplace")',
356-
r'sys.stdout.buffer.write(os_cached + b"\n")')
357-
command = '\n'.join(code)
358-
# First, prove that with -S (no 'import site'), the paths are
359-
# relative.
360-
proc = subprocess.Popen([sys.executable, '-S', '-c', command],
361-
env=env,
362-
stdout=subprocess.PIPE)
363-
stdout, stderr = proc.communicate()
364-
365-
self.assertEqual(proc.returncode, 0)
366-
os__file__, os__cached__ = stdout.splitlines()[:2]
367-
self.assertFalse(os.path.isabs(os__file__))
368-
self.assertFalse(os.path.isabs(os__cached__))
369-
# Now, with 'import site', it works.
370-
proc = subprocess.Popen([sys.executable, '-c', command],
371-
env=env,
372-
stdout=subprocess.PIPE)
373-
stdout, stderr = proc.communicate()
374-
self.assertEqual(proc.returncode, 0)
375-
os__file__, os__cached__ = stdout.splitlines()[:2]
376-
self.assertTrue(os.path.isabs(os__file__),
377-
"expected absolute path, got {}"
378-
.format(os__file__.decode('ascii')))
379-
self.assertTrue(os.path.isabs(os__cached__),
380-
"expected absolute path, got {}"
381-
.format(os__cached__.decode('ascii')))
349+
try:
350+
parent = os.path.relpath(os.path.dirname(os.__file__))
351+
cwd = os.getcwd()
352+
except ValueError:
353+
# Failure to get relpath probably means we need to chdir
354+
# to the same drive.
355+
cwd, parent = os.path.split(os.path.dirname(os.__file__))
356+
with change_cwd(cwd):
357+
env = os.environ.copy()
358+
env['PYTHONPATH'] = parent
359+
code = ('import os, sys',
360+
# use ASCII to avoid locale issues with non-ASCII directories
361+
'os_file = os.__file__.encode("ascii", "backslashreplace")',
362+
r'sys.stdout.buffer.write(os_file + b"\n")',
363+
'os_cached = os.__cached__.encode("ascii", "backslashreplace")',
364+
r'sys.stdout.buffer.write(os_cached + b"\n")')
365+
command = '\n'.join(code)
366+
# First, prove that with -S (no 'import site'), the paths are
367+
# relative.
368+
proc = subprocess.Popen([sys.executable, '-S', '-c', command],
369+
env=env,
370+
stdout=subprocess.PIPE)
371+
stdout, stderr = proc.communicate()
372+
373+
self.assertEqual(proc.returncode, 0)
374+
os__file__, os__cached__ = stdout.splitlines()[:2]
375+
self.assertFalse(os.path.isabs(os__file__))
376+
self.assertFalse(os.path.isabs(os__cached__))
377+
# Now, with 'import site', it works.
378+
proc = subprocess.Popen([sys.executable, '-c', command],
379+
env=env,
380+
stdout=subprocess.PIPE)
381+
stdout, stderr = proc.communicate()
382+
self.assertEqual(proc.returncode, 0)
383+
os__file__, os__cached__ = stdout.splitlines()[:2]
384+
self.assertTrue(os.path.isabs(os__file__),
385+
"expected absolute path, got {}"
386+
.format(os__file__.decode('ascii')))
387+
self.assertTrue(os.path.isabs(os__cached__),
388+
"expected absolute path, got {}"
389+
.format(os__cached__.decode('ascii')))
382390

383391
def test_no_duplicate_paths(self):
384392
# No duplicate paths should exist in sys.path

Lib/test/test_sysconfig.py

Lines changed: 19 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -243,21 +243,34 @@ def test_get_scheme_names(self):
243243
def test_symlink(self):
244244
# On Windows, the EXE needs to know where pythonXY.dll is at so we have
245245
# to add the directory to the path.
246+
env = None
246247
if sys.platform == "win32":
247-
os.environ["PATH"] = "{};{}".format(
248-
os.path.dirname(sys.executable), os.environ["PATH"])
248+
env = {k.upper(): os.environ[k] for k in os.environ}
249+
env["PATH"] = "{};{}".format(
250+
os.path.dirname(sys.executable), env.get("PATH", ""))
251+
# Requires PYTHONHOME as well since we locate stdlib from the
252+
# EXE path and not the DLL path (which should be fixed)
253+
env["PYTHONHOME"] = os.path.dirname(sys.executable)
254+
if sysconfig.is_python_build(True):
255+
env["PYTHONPATH"] = os.path.dirname(os.__file__)
249256

250257
# Issue 7880
251-
def get(python):
258+
def get(python, env=None):
252259
cmd = [python, '-c',
253260
'import sysconfig; print(sysconfig.get_platform())']
254-
p = subprocess.Popen(cmd, stdout=subprocess.PIPE, env=os.environ)
255-
return p.communicate()
261+
p = subprocess.Popen(cmd, stdout=subprocess.PIPE,
262+
stderr=subprocess.PIPE, env=env)
263+
out, err = p.communicate()
264+
if p.returncode:
265+
print((out, err))
266+
self.fail('Non-zero return code {0} (0x{0:08X})'
267+
.format(p.returncode))
268+
return out, err
256269
real = os.path.realpath(sys.executable)
257270
link = os.path.abspath(TESTFN)
258271
os.symlink(real, link)
259272
try:
260-
self.assertEqual(get(real), get(link))
273+
self.assertEqual(get(real), get(link, env))
261274
finally:
262275
unlink(link)
263276

Lib/test/test_venv.py

Lines changed: 29 additions & 33 deletions
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,17 @@
3232
skipInVenv = unittest.skipIf(sys.prefix != sys.base_prefix,
3333
'Test not appropriate in a venv')
3434

35+
def check_output(cmd, encoding=None):
36+
p = subprocess.Popen(cmd,
37+
stdout=subprocess.PIPE,
38+
stderr=subprocess.PIPE,
39+
encoding=encoding)
40+
out, err = p.communicate()
41+
if p.returncode:
42+
raise subprocess.CalledProcessError(
43+
p.returncode, cmd, None, out, err)
44+
return out, err
45+
3546
class BaseTest(unittest.TestCase):
3647
"""Base class for venv tests."""
3748
maxDiff = 80 * 50
@@ -139,9 +150,7 @@ def test_prefixes(self):
139150
('base_prefix', sys.prefix),
140151
('base_exec_prefix', sys.exec_prefix)):
141152
cmd[2] = 'import sys; print(sys.%s)' % prefix
142-
p = subprocess.Popen(cmd, stdout=subprocess.PIPE,
143-
stderr=subprocess.PIPE)
144-
out, err = p.communicate()
153+
out, err = check_output(cmd)
145154
self.assertEqual(out.strip(), expected.encode())
146155

147156
if sys.platform == 'win32':
@@ -264,11 +273,10 @@ def test_executable(self):
264273
"""
265274
rmtree(self.env_dir)
266275
self.run_with_capture(venv.create, self.env_dir)
267-
envpy = os.path.join(os.path.realpath(self.env_dir), self.bindir, self.exe)
268-
cmd = [envpy, '-c', 'import sys; print(sys.executable)']
269-
p = subprocess.Popen(cmd, stdout=subprocess.PIPE,
270-
stderr=subprocess.PIPE)
271-
out, err = p.communicate()
276+
envpy = os.path.join(os.path.realpath(self.env_dir),
277+
self.bindir, self.exe)
278+
out, err = check_output([envpy, '-c',
279+
'import sys; print(sys.executable)'])
272280
self.assertEqual(out.strip(), envpy.encode())
273281

274282
@unittest.skipUnless(can_symlink(), 'Needs symlinks')
@@ -279,30 +287,27 @@ def test_executable_symlinks(self):
279287
rmtree(self.env_dir)
280288
builder = venv.EnvBuilder(clear=True, symlinks=True)
281289
builder.create(self.env_dir)
282-
envpy = os.path.join(os.path.realpath(self.env_dir), self.bindir, self.exe)
283-
cmd = [envpy, '-c', 'import sys; print(sys.executable)']
284-
p = subprocess.Popen(cmd, stdout=subprocess.PIPE,
285-
stderr=subprocess.PIPE)
286-
out, err = p.communicate()
290+
envpy = os.path.join(os.path.realpath(self.env_dir),
291+
self.bindir, self.exe)
292+
out, err = check_output([envpy, '-c',
293+
'import sys; print(sys.executable)'])
287294
self.assertEqual(out.strip(), envpy.encode())
288295

289296
@unittest.skipUnless(os.name == 'nt', 'only relevant on Windows')
290297
def test_unicode_in_batch_file(self):
291298
"""
292-
Test isolation from system site-packages
299+
Test handling of Unicode paths
293300
"""
294301
rmtree(self.env_dir)
295302
env_dir = os.path.join(os.path.realpath(self.env_dir), 'ϼўТλФЙ')
296303
builder = venv.EnvBuilder(clear=True)
297304
builder.create(env_dir)
298305
activate = os.path.join(env_dir, self.bindir, 'activate.bat')
299306
envpy = os.path.join(env_dir, self.bindir, self.exe)
300-
cmd = [activate, '&', self.exe, '-c', 'print(0)']
301-
p = subprocess.Popen(cmd, stdout=subprocess.PIPE,
302-
stderr=subprocess.PIPE, encoding='oem',
303-
shell=True)
304-
out, err = p.communicate()
305-
print(err)
307+
out, err = check_output(
308+
[activate, '&', self.exe, '-c', 'print(0)'],
309+
encoding='oem',
310+
)
306311
self.assertEqual(out.strip(), '0')
307312

308313
@skipInVenv
@@ -311,11 +316,8 @@ class EnsurePipTest(BaseTest):
311316
def assert_pip_not_installed(self):
312317
envpy = os.path.join(os.path.realpath(self.env_dir),
313318
self.bindir, self.exe)
314-
try_import = 'try:\n import pip\nexcept ImportError:\n print("OK")'
315-
cmd = [envpy, '-c', try_import]
316-
p = subprocess.Popen(cmd, stdout=subprocess.PIPE,
317-
stderr=subprocess.PIPE)
318-
out, err = p.communicate()
319+
out, err = check_output([envpy, '-c',
320+
'try:\n import pip\nexcept ImportError:\n print("OK")'])
319321
# We force everything to text, so unittest gives the detailed diff
320322
# if we get unexpected results
321323
err = err.decode("latin-1") # Force to text, prevent decoding errors
@@ -392,10 +394,7 @@ def do_test_with_pip(self, system_site_packages):
392394
self.fail(msg.format(exc, details))
393395
# Ensure pip is available in the virtual environment
394396
envpy = os.path.join(os.path.realpath(self.env_dir), self.bindir, self.exe)
395-
cmd = [envpy, '-Im', 'pip', '--version']
396-
p = subprocess.Popen(cmd, stdout=subprocess.PIPE,
397-
stderr=subprocess.PIPE)
398-
out, err = p.communicate()
397+
out, err = check_output([envpy, '-Im', 'pip', '--version'])
399398
# We force everything to text, so unittest gives the detailed diff
400399
# if we get unexpected results
401400
err = err.decode("latin-1") # Force to text, prevent decoding errors
@@ -409,11 +408,8 @@ def do_test_with_pip(self, system_site_packages):
409408
# http://bugs.python.org/issue19728
410409
# Check the private uninstall command provided for the Windows
411410
# installers works (at least in a virtual environment)
412-
cmd = [envpy, '-Im', 'ensurepip._uninstall']
413411
with EnvironmentVarGuard() as envvars:
414-
p = subprocess.Popen(cmd, stdout=subprocess.PIPE,
415-
stderr=subprocess.PIPE)
416-
out, err = p.communicate()
412+
out, err = check_output([envpy, '-Im', 'ensurepip._uninstall'])
417413
# We force everything to text, so unittest gives the detailed diff
418414
# if we get unexpected results
419415
err = err.decode("latin-1") # Force to text, prevent decoding errors

Tools/msi/distutils.command.bdist_wininst.py

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,9 @@
99
class bdist_wininst(Command):
1010
description = "create an executable installer for MS Windows"
1111

12+
# Marker for tests that we have the unsupported bdist_wininst
13+
_unsupported = True
14+
1215
def initialize_options(self):
1316
pass
1417

0 commit comments

Comments
 (0)
0