aboutsummaryrefslogtreecommitdiffstats
path: root/setuptools/tests/test_msvc9compiler.py
diff options
context:
space:
mode:
authorJason R. Coombs <jaraco@jaraco.com>2015-01-02 18:38:36 -0500
committerJason R. Coombs <jaraco@jaraco.com>2015-01-02 18:38:36 -0500
commit16ee10c47583a4a2b7480af6fc5a205343acfdfd (patch)
tree7cfbb6d488a92fa01ddb86d6f226f549ad26a01e /setuptools/tests/test_msvc9compiler.py
parent866ff739f6e64aaaefcf7816263410527c9f55f7 (diff)
parent41f2c5ec8dd669747f3cfd8d6b2ae9a40d219545 (diff)
downloadexternal_python_setuptools-16ee10c47583a4a2b7480af6fc5a205343acfdfd.tar.gz
external_python_setuptools-16ee10c47583a4a2b7480af6fc5a205343acfdfd.tar.bz2
external_python_setuptools-16ee10c47583a4a2b7480af6fc5a205343acfdfd.zip
Merge with 10.2.1
--HG-- branch : feature/issue-229
Diffstat (limited to 'setuptools/tests/test_msvc9compiler.py')
-rw-r--r--setuptools/tests/test_msvc9compiler.py286
1 files changed, 151 insertions, 135 deletions
diff --git a/setuptools/tests/test_msvc9compiler.py b/setuptools/tests/test_msvc9compiler.py
index 970f7679..a0820fff 100644
--- a/setuptools/tests/test_msvc9compiler.py
+++ b/setuptools/tests/test_msvc9compiler.py
@@ -1,157 +1,173 @@
-"""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.
+"""
+Tests for msvc9compiler.
"""
import os
-import shutil
-import sys
-import tempfile
-import unittest
-import distutils.errors
import contextlib
+import distutils.errors
-# 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
+import pytest
+import mock
- def __enter__(self):
- self.original_read_keys = distutils.msvc9compiler.Reg.read_keys
- self.original_read_values = distutils.msvc9compiler.Reg.read_values
+from . import contexts
- _winreg = getattr(distutils.msvc9compiler, '_winreg', None)
- winreg = getattr(distutils.msvc9compiler, 'winreg', _winreg)
+# importing only setuptools should apply the patch
+__import__('setuptools')
- hives = {
- winreg.HKEY_CURRENT_USER: self.hkcu,
- winreg.HKEY_LOCAL_MACHINE: self.hklm,
- }
+pytest.importorskip("distutils.msvc9compiler")
- 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()))
+def mock_reg(hkcu=None, hklm=None):
+ """
+ Return a mock for distutils.msvc9compiler.Reg, patched
+ to mock out the functions that access the registry.
+ """
- distutils.msvc9compiler.Reg.read_keys = classmethod(read_keys)
- distutils.msvc9compiler.Reg.read_values = classmethod(read_values)
+ _winreg = getattr(distutils.msvc9compiler, '_winreg', None)
+ winreg = getattr(distutils.msvc9compiler, 'winreg', _winreg)
+
+ hives = {
+ winreg.HKEY_CURRENT_USER: hkcu or {},
+ winreg.HKEY_LOCAL_MACHINE: hklm or {},
+ }
+
+ @classmethod
+ 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())
+ ]
+
+ @classmethod
+ 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())
+ )
- return self
+ return mock.patch.multiple(distutils.msvc9compiler.Reg,
+ read_keys=read_keys, read_values=read_values)
- 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):
+class TestModulePatch:
"""
- In a context, patch the environment with replacements. Pass None values
- to clear the values.
+ Ensure that importing setuptools is sufficient to replace
+ the standard find_vcvarsall function with a version that
+ recognizes the "Visual C++ for Python" package.
"""
- 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"
- )
+ key_32 = r'software\microsoft\devdiv\vcforpython\9.0\installdir'
+ key_64 = r'software\wow6432node\microsoft\devdiv\vcforpython\9.0\installdir'
+
+ def test_patched(self):
+ "Test the module is actually patched"
+ mod_name = distutils.msvc9compiler.find_vcvarsall.__module__
+ assert mod_name == "setuptools.msvc9_support", "find_vcvarsall unpatched"
+
+ def test_no_registry_entryies_means_nothing_found(self):
+ """
+ No registry entries or environment variable should lead to an error
+ directing the user to download vcpython27.
+ """
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))
+ with contexts.environment(VS90COMNTOOLS=None):
+ with mock_reg():
+ assert find_vcvarsall(9.0) is None
- try:
+ expected = distutils.errors.DistutilsPlatformError
+ with pytest.raises(expected) as exc:
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)
+ assert 'aka.ms/vcpython27' in str(exc)
+
+ @pytest.yield_fixture
+ def user_preferred_setting(self):
+ """
+ Set up environment with different install dirs for user vs. system
+ and yield the user_install_dir for the expected result.
+ """
+ with self.mock_install_dir() as user_install_dir:
+ with self.mock_install_dir() as system_install_dir:
+ reg = mock_reg(
+ hkcu={
+ self.key_32: user_install_dir,
+ },
+ hklm={
+ self.key_32: system_install_dir,
+ self.key_64: system_install_dir,
+ },
+ )
+ with reg:
+ yield user_install_dir
+
+ def test_prefer_current_user(self, user_preferred_setting):
+ """
+ Ensure user's settings are preferred.
+ """
+ result = distutils.msvc9compiler.find_vcvarsall(9.0)
+ assert user_preferred_setting == result
+
+ @pytest.yield_fixture
+ def local_machine_setting(self):
+ """
+ Set up environment with only the system environment configured.
+ """
+ with self.mock_install_dir() as system_install_dir:
+ reg = mock_reg(
+ hklm={
+ self.key_32: system_install_dir,
+ },
+ )
+ with reg:
+ yield system_install_dir
+
+ def test_local_machine_recognized(self, local_machine_setting):
+ """
+ Ensure machine setting is honored if user settings are not present.
+ """
+ result = distutils.msvc9compiler.find_vcvarsall(9.0)
+ assert local_machine_setting == result
+
+ @pytest.yield_fixture
+ def x64_preferred_setting(self):
+ """
+ Set up environment with 64-bit and 32-bit system settings configured
+ and yield the 64-bit location.
+ """
+ with self.mock_install_dir() as x32_dir:
+ with self.mock_install_dir() as x64_dir:
+ reg = mock_reg(
+ hklm={
+ # This *should* only exist on 32-bit machines
+ self.key_32: x32_dir,
+ # This *should* only exist on 64-bit machines
+ self.key_64: x64_dir,
+ },
+ )
+ with reg:
+ yield x64_dir
+
+ def test_ensure_64_bit_preferred(self, x64_preferred_setting):
+ """
+ Ensure 64-bit system key is preferred.
+ """
+ result = distutils.msvc9compiler.find_vcvarsall(9.0)
+ assert x64_preferred_setting == result
+
+ @staticmethod
+ @contextlib.contextmanager
+ def mock_install_dir():
+ """
+ Make a mock install dir in a unique location so that tests can
+ distinguish which dir was detected in a given scenario.
+ """
+ with contexts.tempdir() as result:
+ vcvarsall = os.path.join(result, 'vcvarsall.bat')
+ with open(vcvarsall, 'w'):
+ pass
+ yield