98 lines
		
	
	
		
			3.5 KiB
		
	
	
	
		
			Python
		
	
	
	
	
	
			
		
		
	
	
			98 lines
		
	
	
		
			3.5 KiB
		
	
	
	
		
			Python
		
	
	
	
	
	
import glob
 | 
						|
import os
 | 
						|
import subprocess
 | 
						|
import sys
 | 
						|
import tempfile
 | 
						|
from distutils import log
 | 
						|
from distutils.errors import DistutilsError
 | 
						|
 | 
						|
import pkg_resources
 | 
						|
from setuptools.wheel import Wheel
 | 
						|
 | 
						|
 | 
						|
def _fixup_find_links(find_links):
 | 
						|
    """Ensure find-links option end-up being a list of strings."""
 | 
						|
    if isinstance(find_links, str):
 | 
						|
        return find_links.split()
 | 
						|
    assert isinstance(find_links, (tuple, list))
 | 
						|
    return find_links
 | 
						|
 | 
						|
 | 
						|
def fetch_build_egg(dist, req):  # noqa: C901  # is too complex (16)  # FIXME
 | 
						|
    """Fetch an egg needed for building.
 | 
						|
 | 
						|
    Use pip/wheel to fetch/build a wheel."""
 | 
						|
    # Warn if wheel is not available
 | 
						|
    try:
 | 
						|
        pkg_resources.get_distribution('wheel')
 | 
						|
    except pkg_resources.DistributionNotFound:
 | 
						|
        dist.announce('WARNING: The wheel package is not available.', log.WARN)
 | 
						|
    # Ignore environment markers; if supplied, it is required.
 | 
						|
    req = strip_marker(req)
 | 
						|
    # Take easy_install options into account, but do not override relevant
 | 
						|
    # pip environment variables (like PIP_INDEX_URL or PIP_QUIET); they'll
 | 
						|
    # take precedence.
 | 
						|
    opts = dist.get_option_dict('easy_install')
 | 
						|
    if 'allow_hosts' in opts:
 | 
						|
        raise DistutilsError('the `allow-hosts` option is not supported '
 | 
						|
                             'when using pip to install requirements.')
 | 
						|
    quiet = 'PIP_QUIET' not in os.environ and 'PIP_VERBOSE' not in os.environ
 | 
						|
    if 'PIP_INDEX_URL' in os.environ:
 | 
						|
        index_url = None
 | 
						|
    elif 'index_url' in opts:
 | 
						|
        index_url = opts['index_url'][1]
 | 
						|
    else:
 | 
						|
        index_url = None
 | 
						|
    find_links = (
 | 
						|
        _fixup_find_links(opts['find_links'][1])[:] if 'find_links' in opts
 | 
						|
        else []
 | 
						|
    )
 | 
						|
    if dist.dependency_links:
 | 
						|
        find_links.extend(dist.dependency_links)
 | 
						|
    eggs_dir = os.path.realpath(dist.get_egg_cache_dir())
 | 
						|
    environment = pkg_resources.Environment()
 | 
						|
    for egg_dist in pkg_resources.find_distributions(eggs_dir):
 | 
						|
        if egg_dist in req and environment.can_add(egg_dist):
 | 
						|
            return egg_dist
 | 
						|
    with tempfile.TemporaryDirectory() as tmpdir:
 | 
						|
        cmd = [
 | 
						|
            sys.executable, '-m', 'pip',
 | 
						|
            '--disable-pip-version-check',
 | 
						|
            'wheel', '--no-deps',
 | 
						|
            '-w', tmpdir,
 | 
						|
        ]
 | 
						|
        if quiet:
 | 
						|
            cmd.append('--quiet')
 | 
						|
        if index_url is not None:
 | 
						|
            cmd.extend(('--index-url', index_url))
 | 
						|
        for link in find_links or []:
 | 
						|
            cmd.extend(('--find-links', link))
 | 
						|
        # If requirement is a PEP 508 direct URL, directly pass
 | 
						|
        # the URL to pip, as `req @ url` does not work on the
 | 
						|
        # command line.
 | 
						|
        cmd.append(req.url or str(req))
 | 
						|
        try:
 | 
						|
            subprocess.check_call(cmd)
 | 
						|
        except subprocess.CalledProcessError as e:
 | 
						|
            raise DistutilsError(str(e)) from e
 | 
						|
        wheel = Wheel(glob.glob(os.path.join(tmpdir, '*.whl'))[0])
 | 
						|
        dist_location = os.path.join(eggs_dir, wheel.egg_name())
 | 
						|
        wheel.install_as_egg(dist_location)
 | 
						|
        dist_metadata = pkg_resources.PathMetadata(
 | 
						|
            dist_location, os.path.join(dist_location, 'EGG-INFO'))
 | 
						|
        dist = pkg_resources.Distribution.from_filename(
 | 
						|
            dist_location, metadata=dist_metadata)
 | 
						|
        return dist
 | 
						|
 | 
						|
 | 
						|
def strip_marker(req):
 | 
						|
    """
 | 
						|
    Return a new requirement without the environment marker to avoid
 | 
						|
    calling pip with something like `babel; extra == "i18n"`, which
 | 
						|
    would always be ignored.
 | 
						|
    """
 | 
						|
    # create a copy to avoid mutating the input
 | 
						|
    req = pkg_resources.Requirement.parse(str(req))
 | 
						|
    req.marker = None
 | 
						|
    return req
 |