jpayne@69
|
1 import glob
|
jpayne@69
|
2 import os
|
jpayne@69
|
3 import subprocess
|
jpayne@69
|
4 import sys
|
jpayne@69
|
5 import tempfile
|
jpayne@69
|
6 from functools import partial
|
jpayne@69
|
7
|
jpayne@69
|
8 from . import _reqs
|
jpayne@69
|
9 from ._reqs import _StrOrIter
|
jpayne@69
|
10 from .warnings import SetuptoolsDeprecationWarning
|
jpayne@69
|
11 from .wheel import Wheel
|
jpayne@69
|
12
|
jpayne@69
|
13 from distutils import log
|
jpayne@69
|
14 from distutils.errors import DistutilsError
|
jpayne@69
|
15
|
jpayne@69
|
16
|
jpayne@69
|
17 def _fixup_find_links(find_links):
|
jpayne@69
|
18 """Ensure find-links option end-up being a list of strings."""
|
jpayne@69
|
19 if isinstance(find_links, str):
|
jpayne@69
|
20 return find_links.split()
|
jpayne@69
|
21 assert isinstance(find_links, (tuple, list))
|
jpayne@69
|
22 return find_links
|
jpayne@69
|
23
|
jpayne@69
|
24
|
jpayne@69
|
25 def fetch_build_egg(dist, req):
|
jpayne@69
|
26 """Fetch an egg needed for building.
|
jpayne@69
|
27
|
jpayne@69
|
28 Use pip/wheel to fetch/build a wheel."""
|
jpayne@69
|
29 _DeprecatedInstaller.emit()
|
jpayne@69
|
30 _warn_wheel_not_available(dist)
|
jpayne@69
|
31 return _fetch_build_egg_no_warn(dist, req)
|
jpayne@69
|
32
|
jpayne@69
|
33
|
jpayne@69
|
34 def _fetch_build_eggs(dist, requires: _StrOrIter):
|
jpayne@69
|
35 import pkg_resources # Delay import to avoid unnecessary side-effects
|
jpayne@69
|
36
|
jpayne@69
|
37 _DeprecatedInstaller.emit(stacklevel=3)
|
jpayne@69
|
38 _warn_wheel_not_available(dist)
|
jpayne@69
|
39
|
jpayne@69
|
40 resolved_dists = pkg_resources.working_set.resolve(
|
jpayne@69
|
41 _reqs.parse(requires, pkg_resources.Requirement), # required for compatibility
|
jpayne@69
|
42 installer=partial(_fetch_build_egg_no_warn, dist), # avoid warning twice
|
jpayne@69
|
43 replace_conflicting=True,
|
jpayne@69
|
44 )
|
jpayne@69
|
45 for dist in resolved_dists:
|
jpayne@69
|
46 pkg_resources.working_set.add(dist, replace=True)
|
jpayne@69
|
47 return resolved_dists
|
jpayne@69
|
48
|
jpayne@69
|
49
|
jpayne@69
|
50 def _fetch_build_egg_no_warn(dist, req): # noqa: C901 # is too complex (16) # FIXME
|
jpayne@69
|
51 import pkg_resources # Delay import to avoid unnecessary side-effects
|
jpayne@69
|
52
|
jpayne@69
|
53 # Ignore environment markers; if supplied, it is required.
|
jpayne@69
|
54 req = strip_marker(req)
|
jpayne@69
|
55 # Take easy_install options into account, but do not override relevant
|
jpayne@69
|
56 # pip environment variables (like PIP_INDEX_URL or PIP_QUIET); they'll
|
jpayne@69
|
57 # take precedence.
|
jpayne@69
|
58 opts = dist.get_option_dict('easy_install')
|
jpayne@69
|
59 if 'allow_hosts' in opts:
|
jpayne@69
|
60 raise DistutilsError(
|
jpayne@69
|
61 'the `allow-hosts` option is not supported '
|
jpayne@69
|
62 'when using pip to install requirements.'
|
jpayne@69
|
63 )
|
jpayne@69
|
64 quiet = 'PIP_QUIET' not in os.environ and 'PIP_VERBOSE' not in os.environ
|
jpayne@69
|
65 if 'PIP_INDEX_URL' in os.environ:
|
jpayne@69
|
66 index_url = None
|
jpayne@69
|
67 elif 'index_url' in opts:
|
jpayne@69
|
68 index_url = opts['index_url'][1]
|
jpayne@69
|
69 else:
|
jpayne@69
|
70 index_url = None
|
jpayne@69
|
71 find_links = (
|
jpayne@69
|
72 _fixup_find_links(opts['find_links'][1])[:] if 'find_links' in opts else []
|
jpayne@69
|
73 )
|
jpayne@69
|
74 if dist.dependency_links:
|
jpayne@69
|
75 find_links.extend(dist.dependency_links)
|
jpayne@69
|
76 eggs_dir = os.path.realpath(dist.get_egg_cache_dir())
|
jpayne@69
|
77 environment = pkg_resources.Environment()
|
jpayne@69
|
78 for egg_dist in pkg_resources.find_distributions(eggs_dir):
|
jpayne@69
|
79 if egg_dist in req and environment.can_add(egg_dist):
|
jpayne@69
|
80 return egg_dist
|
jpayne@69
|
81 with tempfile.TemporaryDirectory() as tmpdir:
|
jpayne@69
|
82 cmd = [
|
jpayne@69
|
83 sys.executable,
|
jpayne@69
|
84 '-m',
|
jpayne@69
|
85 'pip',
|
jpayne@69
|
86 '--disable-pip-version-check',
|
jpayne@69
|
87 'wheel',
|
jpayne@69
|
88 '--no-deps',
|
jpayne@69
|
89 '-w',
|
jpayne@69
|
90 tmpdir,
|
jpayne@69
|
91 ]
|
jpayne@69
|
92 if quiet:
|
jpayne@69
|
93 cmd.append('--quiet')
|
jpayne@69
|
94 if index_url is not None:
|
jpayne@69
|
95 cmd.extend(('--index-url', index_url))
|
jpayne@69
|
96 for link in find_links or []:
|
jpayne@69
|
97 cmd.extend(('--find-links', link))
|
jpayne@69
|
98 # If requirement is a PEP 508 direct URL, directly pass
|
jpayne@69
|
99 # the URL to pip, as `req @ url` does not work on the
|
jpayne@69
|
100 # command line.
|
jpayne@69
|
101 cmd.append(req.url or str(req))
|
jpayne@69
|
102 try:
|
jpayne@69
|
103 subprocess.check_call(cmd)
|
jpayne@69
|
104 except subprocess.CalledProcessError as e:
|
jpayne@69
|
105 raise DistutilsError(str(e)) from e
|
jpayne@69
|
106 wheel = Wheel(glob.glob(os.path.join(tmpdir, '*.whl'))[0])
|
jpayne@69
|
107 dist_location = os.path.join(eggs_dir, wheel.egg_name())
|
jpayne@69
|
108 wheel.install_as_egg(dist_location)
|
jpayne@69
|
109 dist_metadata = pkg_resources.PathMetadata(
|
jpayne@69
|
110 dist_location, os.path.join(dist_location, 'EGG-INFO')
|
jpayne@69
|
111 )
|
jpayne@69
|
112 return pkg_resources.Distribution.from_filename(
|
jpayne@69
|
113 dist_location, metadata=dist_metadata
|
jpayne@69
|
114 )
|
jpayne@69
|
115
|
jpayne@69
|
116
|
jpayne@69
|
117 def strip_marker(req):
|
jpayne@69
|
118 """
|
jpayne@69
|
119 Return a new requirement without the environment marker to avoid
|
jpayne@69
|
120 calling pip with something like `babel; extra == "i18n"`, which
|
jpayne@69
|
121 would always be ignored.
|
jpayne@69
|
122 """
|
jpayne@69
|
123 import pkg_resources # Delay import to avoid unnecessary side-effects
|
jpayne@69
|
124
|
jpayne@69
|
125 # create a copy to avoid mutating the input
|
jpayne@69
|
126 req = pkg_resources.Requirement.parse(str(req))
|
jpayne@69
|
127 req.marker = None
|
jpayne@69
|
128 return req
|
jpayne@69
|
129
|
jpayne@69
|
130
|
jpayne@69
|
131 def _warn_wheel_not_available(dist):
|
jpayne@69
|
132 import pkg_resources # Delay import to avoid unnecessary side-effects
|
jpayne@69
|
133
|
jpayne@69
|
134 try:
|
jpayne@69
|
135 pkg_resources.get_distribution('wheel')
|
jpayne@69
|
136 except pkg_resources.DistributionNotFound:
|
jpayne@69
|
137 dist.announce('WARNING: The wheel package is not available.', log.WARN)
|
jpayne@69
|
138
|
jpayne@69
|
139
|
jpayne@69
|
140 class _DeprecatedInstaller(SetuptoolsDeprecationWarning):
|
jpayne@69
|
141 _SUMMARY = "setuptools.installer and fetch_build_eggs are deprecated."
|
jpayne@69
|
142 _DETAILS = """
|
jpayne@69
|
143 Requirements should be satisfied by a PEP 517 installer.
|
jpayne@69
|
144 If you are using pip, you can try `pip install --use-pep517`.
|
jpayne@69
|
145 """
|
jpayne@69
|
146 # _DUE_DATE not decided yet
|