123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150 |
- import glob
- import os
- import subprocess
- import sys
- from distutils import log
- from distutils.errors import DistutilsError
- import pkg_resources
- from setuptools.command.easy_install import easy_install
- from setuptools.extern import six
- from setuptools.wheel import Wheel
- from .py31compat import TemporaryDirectory
- def _fixup_find_links(find_links):
- """Ensure find-links option end-up being a list of strings."""
- if isinstance(find_links, six.string_types):
- return find_links.split()
- assert isinstance(find_links, (tuple, list))
- return find_links
- def _legacy_fetch_build_egg(dist, req):
- """Fetch an egg needed for building.
- Legacy path using EasyInstall.
- """
- tmp_dist = dist.__class__({'script_args': ['easy_install']})
- opts = tmp_dist.get_option_dict('easy_install')
- opts.clear()
- opts.update(
- (k, v)
- for k, v in dist.get_option_dict('easy_install').items()
- if k in (
- # don't use any other settings
- 'find_links', 'site_dirs', 'index_url',
- 'optimize', 'site_dirs', 'allow_hosts',
- ))
- if dist.dependency_links:
- links = dist.dependency_links[:]
- if 'find_links' in opts:
- links = _fixup_find_links(opts['find_links'][1]) + links
- opts['find_links'] = ('setup', links)
- install_dir = dist.get_egg_cache_dir()
- cmd = easy_install(
- tmp_dist, args=["x"], install_dir=install_dir,
- exclude_scripts=True,
- always_copy=False, build_directory=None, editable=False,
- upgrade=False, multi_version=True, no_report=True, user=False
- )
- cmd.ensure_finalized()
- return cmd.easy_install(req)
- def fetch_build_egg(dist, req):
- """Fetch an egg needed for building.
- Use pip/wheel to fetch/build a wheel."""
- # Check pip is available.
- try:
- pkg_resources.get_distribution('pip')
- except pkg_resources.DistributionNotFound:
- dist.announce(
- 'WARNING: The pip package is not available, falling back '
- 'to EasyInstall for handling setup_requires/test_requires; '
- 'this is deprecated and will be removed in a future version.'
- , log.WARN
- )
- return _legacy_fetch_build_egg(dist, req)
- # Warn if wheel is not.
- 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.')
- if 'PIP_QUIET' in os.environ or 'PIP_VERBOSE' in os.environ:
- quiet = False
- else:
- quiet = True
- 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
- if 'find_links' in opts:
- find_links = _fixup_find_links(opts['find_links'][1])[:]
- else:
- find_links = []
- 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 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))
- if find_links is not None:
- for link in find_links:
- 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.
- if req.url:
- cmd.append(req.url)
- else:
- cmd.append(str(req))
- try:
- subprocess.check_call(cmd)
- except subprocess.CalledProcessError as e:
- raise DistutilsError(str(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
|