Path: blob/master/venv/Lib/site-packages/pip/_internal/build_env.py
811 views
"""Build Environment used for isolation during sdist building1"""23# The following comment should be removed at some point in the future.4# mypy: strict-optional=False5# mypy: disallow-untyped-defs=False67import logging8import os9import sys10import textwrap11from collections import OrderedDict12from distutils.sysconfig import get_python_lib13from sysconfig import get_paths1415from pip._vendor.pkg_resources import Requirement, VersionConflict, WorkingSet1617from pip import __file__ as pip_location18from pip._internal.cli.spinners import open_spinner19from pip._internal.utils.subprocess import call_subprocess20from pip._internal.utils.temp_dir import TempDirectory, tempdir_kinds21from pip._internal.utils.typing import MYPY_CHECK_RUNNING2223if MYPY_CHECK_RUNNING:24from typing import Tuple, Set, Iterable, Optional, List25from pip._internal.index.package_finder import PackageFinder2627logger = logging.getLogger(__name__)282930class _Prefix:3132def __init__(self, path):33# type: (str) -> None34self.path = path35self.setup = False36self.bin_dir = get_paths(37'nt' if os.name == 'nt' else 'posix_prefix',38vars={'base': path, 'platbase': path}39)['scripts']40# Note: prefer distutils' sysconfig to get the41# library paths so PyPy is correctly supported.42purelib = get_python_lib(plat_specific=False, prefix=path)43platlib = get_python_lib(plat_specific=True, prefix=path)44if purelib == platlib:45self.lib_dirs = [purelib]46else:47self.lib_dirs = [purelib, platlib]484950class BuildEnvironment(object):51"""Creates and manages an isolated environment to install build deps52"""5354def __init__(self):55# type: () -> None56temp_dir = TempDirectory(57kind=tempdir_kinds.BUILD_ENV, globally_managed=True58)5960self._prefixes = OrderedDict((61(name, _Prefix(os.path.join(temp_dir.path, name)))62for name in ('normal', 'overlay')63))6465self._bin_dirs = [] # type: List[str]66self._lib_dirs = [] # type: List[str]67for prefix in reversed(list(self._prefixes.values())):68self._bin_dirs.append(prefix.bin_dir)69self._lib_dirs.extend(prefix.lib_dirs)7071# Customize site to:72# - ensure .pth files are honored73# - prevent access to system site packages74system_sites = {75os.path.normcase(site) for site in (76get_python_lib(plat_specific=False),77get_python_lib(plat_specific=True),78)79}80self._site_dir = os.path.join(temp_dir.path, 'site')81if not os.path.exists(self._site_dir):82os.mkdir(self._site_dir)83with open(os.path.join(self._site_dir, 'sitecustomize.py'), 'w') as fp:84fp.write(textwrap.dedent(85'''86import os, site, sys8788# First, drop system-sites related paths.89original_sys_path = sys.path[:]90known_paths = set()91for path in {system_sites!r}:92site.addsitedir(path, known_paths=known_paths)93system_paths = set(94os.path.normcase(path)95for path in sys.path[len(original_sys_path):]96)97original_sys_path = [98path for path in original_sys_path99if os.path.normcase(path) not in system_paths100]101sys.path = original_sys_path102103# Second, add lib directories.104# ensuring .pth file are processed.105for path in {lib_dirs!r}:106assert not path in sys.path107site.addsitedir(path)108'''109).format(system_sites=system_sites, lib_dirs=self._lib_dirs))110111def __enter__(self):112self._save_env = {113name: os.environ.get(name, None)114for name in ('PATH', 'PYTHONNOUSERSITE', 'PYTHONPATH')115}116117path = self._bin_dirs[:]118old_path = self._save_env['PATH']119if old_path:120path.extend(old_path.split(os.pathsep))121122pythonpath = [self._site_dir]123124os.environ.update({125'PATH': os.pathsep.join(path),126'PYTHONNOUSERSITE': '1',127'PYTHONPATH': os.pathsep.join(pythonpath),128})129130def __exit__(self, exc_type, exc_val, exc_tb):131for varname, old_value in self._save_env.items():132if old_value is None:133os.environ.pop(varname, None)134else:135os.environ[varname] = old_value136137def check_requirements(self, reqs):138# type: (Iterable[str]) -> Tuple[Set[Tuple[str, str]], Set[str]]139"""Return 2 sets:140- conflicting requirements: set of (installed, wanted) reqs tuples141- missing requirements: set of reqs142"""143missing = set()144conflicting = set()145if reqs:146ws = WorkingSet(self._lib_dirs)147for req in reqs:148try:149if ws.find(Requirement.parse(req)) is None:150missing.add(req)151except VersionConflict as e:152conflicting.add((str(e.args[0].as_requirement()),153str(e.args[1])))154return conflicting, missing155156def install_requirements(157self,158finder, # type: PackageFinder159requirements, # type: Iterable[str]160prefix_as_string, # type: str161message # type: Optional[str]162):163# type: (...) -> None164prefix = self._prefixes[prefix_as_string]165assert not prefix.setup166prefix.setup = True167if not requirements:168return169args = [170sys.executable, os.path.dirname(pip_location), 'install',171'--ignore-installed', '--no-user', '--prefix', prefix.path,172'--no-warn-script-location',173] # type: List[str]174if logger.getEffectiveLevel() <= logging.DEBUG:175args.append('-v')176for format_control in ('no_binary', 'only_binary'):177formats = getattr(finder.format_control, format_control)178args.extend(('--' + format_control.replace('_', '-'),179','.join(sorted(formats or {':none:'}))))180181index_urls = finder.index_urls182if index_urls:183args.extend(['-i', index_urls[0]])184for extra_index in index_urls[1:]:185args.extend(['--extra-index-url', extra_index])186else:187args.append('--no-index')188for link in finder.find_links:189args.extend(['--find-links', link])190191for host in finder.trusted_hosts:192args.extend(['--trusted-host', host])193if finder.allow_all_prereleases:194args.append('--pre')195args.append('--')196args.extend(requirements)197with open_spinner(message) as spinner:198call_subprocess(args, spinner=spinner)199200201class NoOpBuildEnvironment(BuildEnvironment):202"""A no-op drop-in replacement for BuildEnvironment203"""204205def __init__(self):206pass207208def __enter__(self):209pass210211def __exit__(self, exc_type, exc_val, exc_tb):212pass213214def cleanup(self):215pass216217def install_requirements(self, finder, requirements, prefix, message):218raise NotImplementedError()219220221