Path: blob/main/test/lib/python3.9/site-packages/setuptools/monkey.py
4798 views
"""1Monkey patching of distutils.2"""34import sys5import distutils.filelist6import platform7import types8import functools9from importlib import import_module10import inspect1112import setuptools1314__all__ = []15"""16Everything is private. Contact the project team17if you think you need this functionality.18"""192021def _get_mro(cls):22"""23Returns the bases classes for cls sorted by the MRO.2425Works around an issue on Jython where inspect.getmro will not return all26base classes if multiple classes share the same name. Instead, this27function will return a tuple containing the class itself, and the contents28of cls.__bases__. See https://github.com/pypa/setuptools/issues/1024.29"""30if platform.python_implementation() == "Jython":31return (cls,) + cls.__bases__32return inspect.getmro(cls)333435def get_unpatched(item):36lookup = (37get_unpatched_class if isinstance(item, type) else38get_unpatched_function if isinstance(item, types.FunctionType) else39lambda item: None40)41return lookup(item)424344def get_unpatched_class(cls):45"""Protect against re-patching the distutils if reloaded4647Also ensures that no other distutils extension monkeypatched the distutils48first.49"""50external_bases = (51cls52for cls in _get_mro(cls)53if not cls.__module__.startswith('setuptools')54)55base = next(external_bases)56if not base.__module__.startswith('distutils'):57msg = "distutils has already been patched by %r" % cls58raise AssertionError(msg)59return base606162def patch_all():63# we can't patch distutils.cmd, alas64distutils.core.Command = setuptools.Command6566has_issue_12885 = sys.version_info <= (3, 5, 3)6768if has_issue_12885:69# fix findall bug in distutils (http://bugs.python.org/issue12885)70distutils.filelist.findall = setuptools.findall7172needs_warehouse = (73sys.version_info < (2, 7, 13)74or75(3, 4) < sys.version_info < (3, 4, 6)76or77(3, 5) < sys.version_info <= (3, 5, 3)78)7980if needs_warehouse:81warehouse = 'https://upload.pypi.org/legacy/'82distutils.config.PyPIRCCommand.DEFAULT_REPOSITORY = warehouse8384_patch_distribution_metadata()8586# Install Distribution throughout the distutils87for module in distutils.dist, distutils.core, distutils.cmd:88module.Distribution = setuptools.dist.Distribution8990# Install the patched Extension91distutils.core.Extension = setuptools.extension.Extension92distutils.extension.Extension = setuptools.extension.Extension93if 'distutils.command.build_ext' in sys.modules:94sys.modules['distutils.command.build_ext'].Extension = (95setuptools.extension.Extension96)9798patch_for_msvc_specialized_compiler()99100101def _patch_distribution_metadata():102"""Patch write_pkg_file and read_pkg_file for higher metadata standards"""103for attr in ('write_pkg_file', 'read_pkg_file', 'get_metadata_version'):104new_val = getattr(setuptools.dist, attr)105setattr(distutils.dist.DistributionMetadata, attr, new_val)106107108def patch_func(replacement, target_mod, func_name):109"""110Patch func_name in target_mod with replacement111112Important - original must be resolved by name to avoid113patching an already patched function.114"""115original = getattr(target_mod, func_name)116117# set the 'unpatched' attribute on the replacement to118# point to the original.119vars(replacement).setdefault('unpatched', original)120121# replace the function in the original module122setattr(target_mod, func_name, replacement)123124125def get_unpatched_function(candidate):126return getattr(candidate, 'unpatched')127128129def patch_for_msvc_specialized_compiler():130"""131Patch functions in distutils to use standalone Microsoft Visual C++132compilers.133"""134# import late to avoid circular imports on Python < 3.5135msvc = import_module('setuptools.msvc')136137if platform.system() != 'Windows':138# Compilers only available on Microsoft Windows139return140141def patch_params(mod_name, func_name):142"""143Prepare the parameters for patch_func to patch indicated function.144"""145repl_prefix = 'msvc9_' if 'msvc9' in mod_name else 'msvc14_'146repl_name = repl_prefix + func_name.lstrip('_')147repl = getattr(msvc, repl_name)148mod = import_module(mod_name)149if not hasattr(mod, func_name):150raise ImportError(func_name)151return repl, mod, func_name152153# Python 2.7 to 3.4154msvc9 = functools.partial(patch_params, 'distutils.msvc9compiler')155156# Python 3.5+157msvc14 = functools.partial(patch_params, 'distutils._msvccompiler')158159try:160# Patch distutils.msvc9compiler161patch_func(*msvc9('find_vcvarsall'))162patch_func(*msvc9('query_vcvarsall'))163except ImportError:164pass165166try:167# Patch distutils._msvccompiler._get_vc_env168patch_func(*msvc14('_get_vc_env'))169except ImportError:170pass171172try:173# Patch distutils._msvccompiler.gen_lib_options for Numpy174patch_func(*msvc14('gen_lib_options'))175except ImportError:176pass177178179