comparison lib/python3.8/site-packages/pip/_internal/cli/req_command.py @ 0:9e54283cc701 draft

"planemo upload commit d12c32a45bcd441307e632fca6d9af7d60289d44"
author guerler
date Mon, 27 Jul 2020 03:47:31 -0400
parents
children
comparison
equal deleted inserted replaced
-1:000000000000 0:9e54283cc701
1 """Contains the Command base classes that depend on PipSession.
2
3 The classes in this module are in a separate module so the commands not
4 needing download / PackageFinder capability don't unnecessarily import the
5 PackageFinder machinery and all its vendored dependencies, etc.
6 """
7
8 import logging
9 import os
10 from functools import partial
11
12 from pip._internal.cli.base_command import Command
13 from pip._internal.cli.command_context import CommandContextMixIn
14 from pip._internal.exceptions import CommandError
15 from pip._internal.index.package_finder import PackageFinder
16 from pip._internal.legacy_resolve import Resolver
17 from pip._internal.models.selection_prefs import SelectionPreferences
18 from pip._internal.network.download import Downloader
19 from pip._internal.network.session import PipSession
20 from pip._internal.operations.prepare import RequirementPreparer
21 from pip._internal.req.constructors import (
22 install_req_from_editable,
23 install_req_from_line,
24 install_req_from_req_string,
25 )
26 from pip._internal.req.req_file import parse_requirements
27 from pip._internal.self_outdated_check import (
28 make_link_collector,
29 pip_self_version_check,
30 )
31 from pip._internal.utils.typing import MYPY_CHECK_RUNNING
32
33 if MYPY_CHECK_RUNNING:
34 from optparse import Values
35 from typing import List, Optional, Tuple
36 from pip._internal.cache import WheelCache
37 from pip._internal.models.target_python import TargetPython
38 from pip._internal.req.req_set import RequirementSet
39 from pip._internal.req.req_tracker import RequirementTracker
40 from pip._internal.utils.temp_dir import TempDirectory
41
42 logger = logging.getLogger(__name__)
43
44
45 class SessionCommandMixin(CommandContextMixIn):
46
47 """
48 A class mixin for command classes needing _build_session().
49 """
50 def __init__(self):
51 # type: () -> None
52 super(SessionCommandMixin, self).__init__()
53 self._session = None # Optional[PipSession]
54
55 @classmethod
56 def _get_index_urls(cls, options):
57 # type: (Values) -> Optional[List[str]]
58 """Return a list of index urls from user-provided options."""
59 index_urls = []
60 if not getattr(options, "no_index", False):
61 url = getattr(options, "index_url", None)
62 if url:
63 index_urls.append(url)
64 urls = getattr(options, "extra_index_urls", None)
65 if urls:
66 index_urls.extend(urls)
67 # Return None rather than an empty list
68 return index_urls or None
69
70 def get_default_session(self, options):
71 # type: (Values) -> PipSession
72 """Get a default-managed session."""
73 if self._session is None:
74 self._session = self.enter_context(self._build_session(options))
75 # there's no type annotation on requests.Session, so it's
76 # automatically ContextManager[Any] and self._session becomes Any,
77 # then https://github.com/python/mypy/issues/7696 kicks in
78 assert self._session is not None
79 return self._session
80
81 def _build_session(self, options, retries=None, timeout=None):
82 # type: (Values, Optional[int], Optional[int]) -> PipSession
83 assert not options.cache_dir or os.path.isabs(options.cache_dir)
84 session = PipSession(
85 cache=(
86 os.path.join(options.cache_dir, "http")
87 if options.cache_dir else None
88 ),
89 retries=retries if retries is not None else options.retries,
90 trusted_hosts=options.trusted_hosts,
91 index_urls=self._get_index_urls(options),
92 )
93
94 # Handle custom ca-bundles from the user
95 if options.cert:
96 session.verify = options.cert
97
98 # Handle SSL client certificate
99 if options.client_cert:
100 session.cert = options.client_cert
101
102 # Handle timeouts
103 if options.timeout or timeout:
104 session.timeout = (
105 timeout if timeout is not None else options.timeout
106 )
107
108 # Handle configured proxies
109 if options.proxy:
110 session.proxies = {
111 "http": options.proxy,
112 "https": options.proxy,
113 }
114
115 # Determine if we can prompt the user for authentication or not
116 session.auth.prompting = not options.no_input
117
118 return session
119
120
121 class IndexGroupCommand(Command, SessionCommandMixin):
122
123 """
124 Abstract base class for commands with the index_group options.
125
126 This also corresponds to the commands that permit the pip version check.
127 """
128
129 def handle_pip_version_check(self, options):
130 # type: (Values) -> None
131 """
132 Do the pip version check if not disabled.
133
134 This overrides the default behavior of not doing the check.
135 """
136 # Make sure the index_group options are present.
137 assert hasattr(options, 'no_index')
138
139 if options.disable_pip_version_check or options.no_index:
140 return
141
142 # Otherwise, check if we're using the latest version of pip available.
143 session = self._build_session(
144 options,
145 retries=0,
146 timeout=min(5, options.timeout)
147 )
148 with session:
149 pip_self_version_check(session, options)
150
151
152 class RequirementCommand(IndexGroupCommand):
153
154 @staticmethod
155 def make_requirement_preparer(
156 temp_build_dir, # type: TempDirectory
157 options, # type: Values
158 req_tracker, # type: RequirementTracker
159 session, # type: PipSession
160 finder, # type: PackageFinder
161 use_user_site, # type: bool
162 download_dir=None, # type: str
163 wheel_download_dir=None, # type: str
164 ):
165 # type: (...) -> RequirementPreparer
166 """
167 Create a RequirementPreparer instance for the given parameters.
168 """
169 downloader = Downloader(session, progress_bar=options.progress_bar)
170
171 temp_build_dir_path = temp_build_dir.path
172 assert temp_build_dir_path is not None
173
174 return RequirementPreparer(
175 build_dir=temp_build_dir_path,
176 src_dir=options.src_dir,
177 download_dir=download_dir,
178 wheel_download_dir=wheel_download_dir,
179 build_isolation=options.build_isolation,
180 req_tracker=req_tracker,
181 downloader=downloader,
182 finder=finder,
183 require_hashes=options.require_hashes,
184 use_user_site=use_user_site,
185 )
186
187 @staticmethod
188 def make_resolver(
189 preparer, # type: RequirementPreparer
190 finder, # type: PackageFinder
191 options, # type: Values
192 wheel_cache=None, # type: Optional[WheelCache]
193 use_user_site=False, # type: bool
194 ignore_installed=True, # type: bool
195 ignore_requires_python=False, # type: bool
196 force_reinstall=False, # type: bool
197 upgrade_strategy="to-satisfy-only", # type: str
198 use_pep517=None, # type: Optional[bool]
199 py_version_info=None # type: Optional[Tuple[int, ...]]
200 ):
201 # type: (...) -> Resolver
202 """
203 Create a Resolver instance for the given parameters.
204 """
205 make_install_req = partial(
206 install_req_from_req_string,
207 isolated=options.isolated_mode,
208 wheel_cache=wheel_cache,
209 use_pep517=use_pep517,
210 )
211 return Resolver(
212 preparer=preparer,
213 finder=finder,
214 make_install_req=make_install_req,
215 use_user_site=use_user_site,
216 ignore_dependencies=options.ignore_dependencies,
217 ignore_installed=ignore_installed,
218 ignore_requires_python=ignore_requires_python,
219 force_reinstall=force_reinstall,
220 upgrade_strategy=upgrade_strategy,
221 py_version_info=py_version_info,
222 )
223
224 def populate_requirement_set(
225 self,
226 requirement_set, # type: RequirementSet
227 args, # type: List[str]
228 options, # type: Values
229 finder, # type: PackageFinder
230 session, # type: PipSession
231 wheel_cache, # type: Optional[WheelCache]
232 ):
233 # type: (...) -> None
234 """
235 Marshal cmd line args into a requirement set.
236 """
237 for filename in options.constraints:
238 for req_to_add in parse_requirements(
239 filename,
240 constraint=True, finder=finder, options=options,
241 session=session, wheel_cache=wheel_cache):
242 req_to_add.is_direct = True
243 requirement_set.add_requirement(req_to_add)
244
245 for req in args:
246 req_to_add = install_req_from_line(
247 req, None, isolated=options.isolated_mode,
248 use_pep517=options.use_pep517,
249 wheel_cache=wheel_cache
250 )
251 req_to_add.is_direct = True
252 requirement_set.add_requirement(req_to_add)
253
254 for req in options.editables:
255 req_to_add = install_req_from_editable(
256 req,
257 isolated=options.isolated_mode,
258 use_pep517=options.use_pep517,
259 wheel_cache=wheel_cache
260 )
261 req_to_add.is_direct = True
262 requirement_set.add_requirement(req_to_add)
263
264 # NOTE: options.require_hashes may be set if --require-hashes is True
265 for filename in options.requirements:
266 for req_to_add in parse_requirements(
267 filename,
268 finder=finder, options=options, session=session,
269 wheel_cache=wheel_cache,
270 use_pep517=options.use_pep517):
271 req_to_add.is_direct = True
272 requirement_set.add_requirement(req_to_add)
273
274 # If any requirement has hash options, enable hash checking.
275 requirements = (
276 requirement_set.unnamed_requirements +
277 list(requirement_set.requirements.values())
278 )
279 if any(req.has_hash_options for req in requirements):
280 options.require_hashes = True
281
282 if not (args or options.editables or options.requirements):
283 opts = {'name': self.name}
284 if options.find_links:
285 raise CommandError(
286 'You must give at least one requirement to %(name)s '
287 '(maybe you meant "pip %(name)s %(links)s"?)' %
288 dict(opts, links=' '.join(options.find_links)))
289 else:
290 raise CommandError(
291 'You must give at least one requirement to %(name)s '
292 '(see "pip help %(name)s")' % opts)
293
294 @staticmethod
295 def trace_basic_info(finder):
296 # type: (PackageFinder) -> None
297 """
298 Trace basic information about the provided objects.
299 """
300 # Display where finder is looking for packages
301 search_scope = finder.search_scope
302 locations = search_scope.get_formatted_locations()
303 if locations:
304 logger.info(locations)
305
306 def _build_package_finder(
307 self,
308 options, # type: Values
309 session, # type: PipSession
310 target_python=None, # type: Optional[TargetPython]
311 ignore_requires_python=None, # type: Optional[bool]
312 ):
313 # type: (...) -> PackageFinder
314 """
315 Create a package finder appropriate to this requirement command.
316
317 :param ignore_requires_python: Whether to ignore incompatible
318 "Requires-Python" values in links. Defaults to False.
319 """
320 link_collector = make_link_collector(session, options=options)
321 selection_prefs = SelectionPreferences(
322 allow_yanked=True,
323 format_control=options.format_control,
324 allow_all_prereleases=options.pre,
325 prefer_binary=options.prefer_binary,
326 ignore_requires_python=ignore_requires_python,
327 )
328
329 return PackageFinder.create(
330 link_collector=link_collector,
331 selection_prefs=selection_prefs,
332 target_python=target_python,
333 )