summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJason R. Coombs <jaraco@jaraco.com>2020-09-05 11:06:10 -0400
committerJason R. Coombs <jaraco@jaraco.com>2020-09-05 11:06:10 -0400
commit0a665b2a2f2c0cfbc5badad138feb762c720c15c (patch)
tree43d5ae3a05a749390c95501dd5c77aebc95cd9f1
parent03d36b9edb53e266a0b4b836e1e3178f989a0781 (diff)
parent2888d3c08e1c34254f726bc331dc33d419e636dc (diff)
downloadpython-setuptools-git-0a665b2a2f2c0cfbc5badad138feb762c720c15c.tar.gz
Merge https://github.com/pypa/distutils into master
-rw-r--r--setuptools/_distutils/_msvccompiler.py26
-rw-r--r--setuptools/_distutils/tests/test_msvccompiler.py20
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)