diff options
author | Jason R. Coombs <jaraco@jaraco.com> | 2020-09-05 11:06:10 -0400 |
---|---|---|
committer | Jason R. Coombs <jaraco@jaraco.com> | 2020-09-05 11:06:10 -0400 |
commit | 0a665b2a2f2c0cfbc5badad138feb762c720c15c (patch) | |
tree | 43d5ae3a05a749390c95501dd5c77aebc95cd9f1 | |
parent | 03d36b9edb53e266a0b4b836e1e3178f989a0781 (diff) | |
parent | 2888d3c08e1c34254f726bc331dc33d419e636dc (diff) | |
download | python-setuptools-git-0a665b2a2f2c0cfbc5badad138feb762c720c15c.tar.gz |
Merge https://github.com/pypa/distutils into master
-rw-r--r-- | setuptools/_distutils/_msvccompiler.py | 26 | ||||
-rw-r--r-- | setuptools/_distutils/tests/test_msvccompiler.py | 20 |
2 files changed, 45 insertions, 1 deletions
diff --git a/setuptools/_distutils/_msvccompiler.py b/setuptools/_distutils/_msvccompiler.py index 2d56ee0a..e9af4cf5 100644 --- a/setuptools/_distutils/_msvccompiler.py +++ b/setuptools/_distutils/_msvccompiler.py @@ -16,6 +16,8 @@ for older versions in distutils.msvc9compiler and distutils.msvccompiler. import os import subprocess import contextlib +import warnings +import unittest.mock with contextlib.suppress(ImportError): import winreg @@ -504,7 +506,29 @@ class MSVCCompiler(CCompiler) : def spawn(self, cmd): env = dict(os.environ, PATH=self._paths) - return super().spawn(cmd, env=env) + with self._fallback_spawn(cmd, env) as fallback: + return super().spawn(cmd, env=env) + return fallback.value + + @contextlib.contextmanager + def _fallback_spawn(self, cmd, env): + """ + Discovered in pypa/distutils#15, some tools monkeypatch the compiler, + so the 'env' kwarg causes a TypeError. Detect this condition and + restore the legacy, unsafe behavior. + """ + bag = type('Bag', (), {})() + try: + yield bag + except TypeError as exc: + if "unexpected keyword argument 'env'" not in str(exc): + raise + else: + return + warnings.warn( + "Fallback spawn triggered. Please update distutils monkeypatch.") + with unittest.mock.patch('os.environ', env): + bag.value = super().spawn(cmd) # -- Miscellaneous methods ----------------------------------------- # These are all used by the 'gen_lib_options() function, in diff --git a/setuptools/_distutils/tests/test_msvccompiler.py b/setuptools/_distutils/tests/test_msvccompiler.py index 88d912b1..46a51cd0 100644 --- a/setuptools/_distutils/tests/test_msvccompiler.py +++ b/setuptools/_distutils/tests/test_msvccompiler.py @@ -110,6 +110,26 @@ class TestSpawn(unittest.TestCase): 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) |