1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
|
"""Tests for distutils._msvccompiler."""
import sys
import unittest
import os
import threading
from distutils.errors import DistutilsPlatformError
from distutils.tests import support
from test.support import run_unittest
SKIP_MESSAGE = (None if sys.platform == "win32" else
"These tests are only for win32")
@unittest.skipUnless(SKIP_MESSAGE is None, SKIP_MESSAGE)
class msvccompilerTestCase(support.TempdirManager,
unittest.TestCase):
def test_no_compiler(self):
import distutils._msvccompiler as _msvccompiler
# makes sure query_vcvarsall raises
# a DistutilsPlatformError if the compiler
# is not found
def _find_vcvarsall(plat_spec):
return None, None
old_find_vcvarsall = _msvccompiler._find_vcvarsall
_msvccompiler._find_vcvarsall = _find_vcvarsall
try:
self.assertRaises(DistutilsPlatformError,
_msvccompiler._get_vc_env,
'wont find this version')
finally:
_msvccompiler._find_vcvarsall = old_find_vcvarsall
def test_get_vc_env_unicode(self):
import distutils._msvccompiler as _msvccompiler
test_var = 'ṰḖṤṪ┅ṼẨṜ'
test_value = '₃⁴₅'
# Ensure we don't early exit from _get_vc_env
old_distutils_use_sdk = os.environ.pop('DISTUTILS_USE_SDK', None)
os.environ[test_var] = test_value
try:
env = _msvccompiler._get_vc_env('x86')
self.assertIn(test_var.lower(), env)
self.assertEqual(test_value, env[test_var.lower()])
finally:
os.environ.pop(test_var)
if old_distutils_use_sdk:
os.environ['DISTUTILS_USE_SDK'] = old_distutils_use_sdk
def test_get_vc2017(self):
import distutils._msvccompiler as _msvccompiler
# This function cannot be mocked, so pass it if we find VS 2017
# and mark it skipped if we do not.
version, path = _msvccompiler._find_vc2017()
if version:
self.assertGreaterEqual(version, 15)
self.assertTrue(os.path.isdir(path))
else:
raise unittest.SkipTest("VS 2017 is not installed")
def test_get_vc2015(self):
import distutils._msvccompiler as _msvccompiler
# This function cannot be mocked, so pass it if we find VS 2015
# and mark it skipped if we do not.
version, path = _msvccompiler._find_vc2015()
if version:
self.assertGreaterEqual(version, 14)
self.assertTrue(os.path.isdir(path))
else:
raise unittest.SkipTest("VS 2015 is not installed")
class CheckThread(threading.Thread):
exc_info = None
def run(self):
try:
super().run()
except Exception:
self.exc_info = sys.exc_info()
def __bool__(self):
return not self.exc_info
class TestSpawn(unittest.TestCase):
def test_concurrent_safe(self):
"""
Concurrent calls to spawn should have consistent results.
"""
import distutils._msvccompiler as _msvccompiler
compiler = _msvccompiler.MSVCCompiler()
compiler._paths = "expected"
inner_cmd = 'import os; assert os.environ["PATH"] == "expected"'
command = ['python', '-c', inner_cmd]
threads = [
CheckThread(target=compiler.spawn, args=[command])
for n in range(100)
]
for thread in threads:
thread.start()
for thread in threads:
thread.join()
assert all(threads)
def test_concurrent_safe_fallback(self):
"""
If CCompiler.spawn has been monkey-patched without support
for an env, it should still execute.
"""
import distutils._msvccompiler as _msvccompiler
from distutils import ccompiler
compiler = _msvccompiler.MSVCCompiler()
compiler._paths = "expected"
def CCompiler_spawn(self, cmd):
"A spawn without an env argument."
assert os.environ["PATH"] == "expected"
with unittest.mock.patch.object(
ccompiler.CCompiler, 'spawn', CCompiler_spawn):
compiler.spawn(["n/a"])
assert os.environ.get("PATH") != "expected"
def test_suite():
return unittest.makeSuite(msvccompilerTestCase)
if __name__ == "__main__":
run_unittest(test_suite())
|