[metadata]
name = setuptools
-version = 50.2.0
+version = 50.3.0
description = Easily download, build, install, upgrade, and uninstall Python packages
author = Python Packaging Authority
author_email = distutils-sig@python.org
import os
import subprocess
import contextlib
+import warnings
+import unittest.mock
with contextlib.suppress(ImportError):
import winreg
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
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)