| Index: recipe_engine/third_party/setuptools/tests/test_msvc9compiler.py
|
| diff --git a/recipe_engine/third_party/setuptools/tests/test_msvc9compiler.py b/recipe_engine/third_party/setuptools/tests/test_msvc9compiler.py
|
| new file mode 100644
|
| index 0000000000000000000000000000000000000000..970f76793db13e6d8523ddaee606b9258419bd2e
|
| --- /dev/null
|
| +++ b/recipe_engine/third_party/setuptools/tests/test_msvc9compiler.py
|
| @@ -0,0 +1,157 @@
|
| +"""msvc9compiler monkey patch test
|
| +
|
| +This test ensures that importing setuptools is sufficient to replace
|
| +the standard find_vcvarsall function with our patched version that
|
| +finds the Visual C++ for Python package.
|
| +"""
|
| +
|
| +import os
|
| +import shutil
|
| +import sys
|
| +import tempfile
|
| +import unittest
|
| +import distutils.errors
|
| +import contextlib
|
| +
|
| +# importing only setuptools should apply the patch
|
| +__import__('setuptools')
|
| +
|
| +class MockReg:
|
| + """Mock for distutils.msvc9compiler.Reg. We patch it
|
| + with an instance of this class that mocks out the
|
| + functions that access the registry.
|
| + """
|
| +
|
| + def __init__(self, hkey_local_machine={}, hkey_current_user={}):
|
| + self.hklm = hkey_local_machine
|
| + self.hkcu = hkey_current_user
|
| +
|
| + def __enter__(self):
|
| + self.original_read_keys = distutils.msvc9compiler.Reg.read_keys
|
| + self.original_read_values = distutils.msvc9compiler.Reg.read_values
|
| +
|
| + _winreg = getattr(distutils.msvc9compiler, '_winreg', None)
|
| + winreg = getattr(distutils.msvc9compiler, 'winreg', _winreg)
|
| +
|
| + hives = {
|
| + winreg.HKEY_CURRENT_USER: self.hkcu,
|
| + winreg.HKEY_LOCAL_MACHINE: self.hklm,
|
| + }
|
| +
|
| + def read_keys(cls, base, key):
|
| + """Return list of registry keys."""
|
| + hive = hives.get(base, {})
|
| + return [k.rpartition('\\')[2]
|
| + for k in hive if k.startswith(key.lower())]
|
| +
|
| + def read_values(cls, base, key):
|
| + """Return dict of registry keys and values."""
|
| + hive = hives.get(base, {})
|
| + return dict((k.rpartition('\\')[2], hive[k])
|
| + for k in hive if k.startswith(key.lower()))
|
| +
|
| + distutils.msvc9compiler.Reg.read_keys = classmethod(read_keys)
|
| + distutils.msvc9compiler.Reg.read_values = classmethod(read_values)
|
| +
|
| + return self
|
| +
|
| + def __exit__(self, exc_type, exc_value, exc_tb):
|
| + distutils.msvc9compiler.Reg.read_keys = self.original_read_keys
|
| + distutils.msvc9compiler.Reg.read_values = self.original_read_values
|
| +
|
| +@contextlib.contextmanager
|
| +def patch_env(**replacements):
|
| + """
|
| + In a context, patch the environment with replacements. Pass None values
|
| + to clear the values.
|
| + """
|
| + saved = dict(
|
| + (key, os.environ['key'])
|
| + for key in replacements
|
| + if key in os.environ
|
| + )
|
| +
|
| + # remove values that are null
|
| + remove = (key for (key, value) in replacements.items() if value is None)
|
| + for key in list(remove):
|
| + os.environ.pop(key, None)
|
| + replacements.pop(key)
|
| +
|
| + os.environ.update(replacements)
|
| +
|
| + try:
|
| + yield saved
|
| + finally:
|
| + for key in replacements:
|
| + os.environ.pop(key, None)
|
| + os.environ.update(saved)
|
| +
|
| +class TestMSVC9Compiler(unittest.TestCase):
|
| +
|
| + def test_find_vcvarsall_patch(self):
|
| + if not hasattr(distutils, 'msvc9compiler'):
|
| + # skip
|
| + return
|
| +
|
| + self.assertEqual(
|
| + "setuptools.msvc9_support",
|
| + distutils.msvc9compiler.find_vcvarsall.__module__,
|
| + "find_vcvarsall was not patched"
|
| + )
|
| +
|
| + find_vcvarsall = distutils.msvc9compiler.find_vcvarsall
|
| + query_vcvarsall = distutils.msvc9compiler.query_vcvarsall
|
| +
|
| + # No registry entries or environment variable means we should
|
| + # not find anything
|
| + with patch_env(VS90COMNTOOLS=None):
|
| + with MockReg():
|
| + self.assertIsNone(find_vcvarsall(9.0))
|
| +
|
| + try:
|
| + query_vcvarsall(9.0)
|
| + self.fail('Expected DistutilsPlatformError from query_vcvarsall()')
|
| + except distutils.errors.DistutilsPlatformError:
|
| + exc_message = str(sys.exc_info()[1])
|
| + self.assertIn('aka.ms/vcpython27', exc_message)
|
| +
|
| + key_32 = r'software\microsoft\devdiv\vcforpython\9.0\installdir'
|
| + key_64 = r'software\wow6432node\microsoft\devdiv\vcforpython\9.0\installdir'
|
| +
|
| + # Make two mock files so we can tell whether HCKU entries are
|
| + # preferred to HKLM entries.
|
| + mock_installdir_1 = tempfile.mkdtemp()
|
| + mock_vcvarsall_bat_1 = os.path.join(mock_installdir_1, 'vcvarsall.bat')
|
| + open(mock_vcvarsall_bat_1, 'w').close()
|
| + mock_installdir_2 = tempfile.mkdtemp()
|
| + mock_vcvarsall_bat_2 = os.path.join(mock_installdir_2, 'vcvarsall.bat')
|
| + open(mock_vcvarsall_bat_2, 'w').close()
|
| + try:
|
| + # Ensure we get the current user's setting first
|
| + with MockReg(
|
| + hkey_current_user={key_32: mock_installdir_1},
|
| + hkey_local_machine={
|
| + key_32: mock_installdir_2,
|
| + key_64: mock_installdir_2,
|
| + }
|
| + ):
|
| + self.assertEqual(mock_vcvarsall_bat_1, find_vcvarsall(9.0))
|
| +
|
| + # Ensure we get the local machine value if it's there
|
| + with MockReg(hkey_local_machine={key_32: mock_installdir_2}):
|
| + self.assertEqual(mock_vcvarsall_bat_2, find_vcvarsall(9.0))
|
| +
|
| + # Ensure we prefer the 64-bit local machine key
|
| + # (*not* the Wow6432Node key)
|
| + with MockReg(
|
| + hkey_local_machine={
|
| + # This *should* only exist on 32-bit machines
|
| + key_32: mock_installdir_1,
|
| + # This *should* only exist on 64-bit machines
|
| + key_64: mock_installdir_2,
|
| + }
|
| + ):
|
| + self.assertEqual(mock_vcvarsall_bat_1, find_vcvarsall(9.0))
|
| + finally:
|
| + shutil.rmtree(mock_installdir_1)
|
| + shutil.rmtree(mock_installdir_2)
|
|
|