This repository has been archived on 2026-10-10. You can view files and clone it. You cannot open issues or pull requests or push a commit.
Files
2022-12-10 21:17:54 -06:00

172 lines
5.4 KiB
Python

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