summaryrefslogtreecommitdiff
path: root/venv/lib/python3.7/site-packages/pip-10.0.1-py3.7.egg/pip/_internal/basecommand.py
diff options
context:
space:
mode:
Diffstat (limited to 'venv/lib/python3.7/site-packages/pip-10.0.1-py3.7.egg/pip/_internal/basecommand.py')
-rw-r--r--venv/lib/python3.7/site-packages/pip-10.0.1-py3.7.egg/pip/_internal/basecommand.py373
1 files changed, 373 insertions, 0 deletions
diff --git a/venv/lib/python3.7/site-packages/pip-10.0.1-py3.7.egg/pip/_internal/basecommand.py b/venv/lib/python3.7/site-packages/pip-10.0.1-py3.7.egg/pip/_internal/basecommand.py
new file mode 100644
index 0000000..e900928
--- /dev/null
+++ b/venv/lib/python3.7/site-packages/pip-10.0.1-py3.7.egg/pip/_internal/basecommand.py
@@ -0,0 +1,373 @@
1"""Base Command class, and related routines"""
2from __future__ import absolute_import
3
4import logging
5import logging.config
6import optparse
7import os
8import sys
9import warnings
10
11from pip._internal import cmdoptions
12from pip._internal.baseparser import (
13 ConfigOptionParser, UpdatingDefaultsHelpFormatter,
14)
15from pip._internal.compat import WINDOWS
16from pip._internal.download import PipSession
17from pip._internal.exceptions import (
18 BadCommand, CommandError, InstallationError, PreviousBuildDirError,
19 UninstallationError,
20)
21from pip._internal.index import PackageFinder
22from pip._internal.locations import running_under_virtualenv
23from pip._internal.req.req_file import parse_requirements
24from pip._internal.req.req_install import InstallRequirement
25from pip._internal.status_codes import (
26 ERROR, PREVIOUS_BUILD_DIR_ERROR, SUCCESS, UNKNOWN_ERROR,
27 VIRTUALENV_NOT_FOUND,
28)
29from pip._internal.utils import deprecation
30from pip._internal.utils.logging import IndentingFormatter
31from pip._internal.utils.misc import get_prog, normalize_path
32from pip._internal.utils.outdated import pip_version_check
33from pip._internal.utils.typing import MYPY_CHECK_RUNNING
34
35if MYPY_CHECK_RUNNING:
36 from typing import Optional
37
38__all__ = ['Command']
39
40logger = logging.getLogger(__name__)
41
42
43class Command(object):
44 name = None # type: Optional[str]
45 usage = None # type: Optional[str]
46 hidden = False # type: bool
47 ignore_require_venv = False # type: bool
48 log_streams = ("ext://sys.stdout", "ext://sys.stderr")
49
50 def __init__(self, isolated=False):
51 parser_kw = {
52 'usage': self.usage,
53 'prog': '%s %s' % (get_prog(), self.name),
54 'formatter': UpdatingDefaultsHelpFormatter(),
55 'add_help_option': False,
56 'name': self.name,
57 'description': self.__doc__,
58 'isolated': isolated,
59 }
60
61 self.parser = ConfigOptionParser(**parser_kw)
62
63 # Commands should add options to this option group
64 optgroup_name = '%s Options' % self.name.capitalize()
65 self.cmd_opts = optparse.OptionGroup(self.parser, optgroup_name)
66
67 # Add the general options
68 gen_opts = cmdoptions.make_option_group(
69 cmdoptions.general_group,
70 self.parser,
71 )
72 self.parser.add_option_group(gen_opts)
73
74 def _build_session(self, options, retries=None, timeout=None):
75 session = PipSession(
76 cache=(
77 normalize_path(os.path.join(options.cache_dir, "http"))
78 if options.cache_dir else None
79 ),
80 retries=retries if retries is not None else options.retries,
81 insecure_hosts=options.trusted_hosts,
82 )
83
84 # Handle custom ca-bundles from the user
85 if options.cert:
86 session.verify = options.cert
87
88 # Handle SSL client certificate
89 if options.client_cert:
90 session.cert = options.client_cert
91
92 # Handle timeouts
93 if options.timeout or timeout:
94 session.timeout = (
95 timeout if timeout is not None else options.timeout
96 )
97
98 # Handle configured proxies
99 if options.proxy:
100 session.proxies = {
101 "http": options.proxy,
102 "https": options.proxy,
103 }
104
105 # Determine if we can prompt the user for authentication or not
106 session.auth.prompting = not options.no_input
107
108 return session
109
110 def parse_args(self, args):
111 # factored out for testability
112 return self.parser.parse_args(args)
113
114 def main(self, args):
115 options, args = self.parse_args(args)
116
117 # Set verbosity so that it can be used elsewhere.
118 self.verbosity = options.verbose - options.quiet
119
120 if self.verbosity >= 1:
121 level = "DEBUG"
122 elif self.verbosity == -1:
123 level = "WARNING"
124 elif self.verbosity == -2:
125 level = "ERROR"
126 elif self.verbosity <= -3:
127 level = "CRITICAL"
128 else:
129 level = "INFO"
130
131 # The root logger should match the "console" level *unless* we
132 # specified "--log" to send debug logs to a file.
133 root_level = level
134 if options.log:
135 root_level = "DEBUG"
136
137 logger_class = "pip._internal.utils.logging.ColorizedStreamHandler"
138 handler_class = "pip._internal.utils.logging.BetterRotatingFileHandler"
139
140 logging.config.dictConfig({
141 "version": 1,
142 "disable_existing_loggers": False,
143 "filters": {
144 "exclude_warnings": {
145 "()": "pip._internal.utils.logging.MaxLevelFilter",
146 "level": logging.WARNING,
147 },
148 },
149 "formatters": {
150 "indent": {
151 "()": IndentingFormatter,
152 "format": "%(message)s",
153 },
154 },
155 "handlers": {
156 "console": {
157 "level": level,
158 "class": logger_class,
159 "no_color": options.no_color,
160 "stream": self.log_streams[0],
161 "filters": ["exclude_warnings"],
162 "formatter": "indent",
163 },
164 "console_errors": {
165 "level": "WARNING",
166 "class": logger_class,
167 "no_color": options.no_color,
168 "stream": self.log_streams[1],
169 "formatter": "indent",
170 },
171 "user_log": {
172 "level": "DEBUG",
173 "class": handler_class,
174 "filename": options.log or "/dev/null",
175 "delay": True,
176 "formatter": "indent",
177 },
178 },
179 "root": {
180 "level": root_level,
181 "handlers": list(filter(None, [
182 "console",
183 "console_errors",
184 "user_log" if options.log else None,
185 ])),
186 },
187 # Disable any logging besides WARNING unless we have DEBUG level
188 # logging enabled. These use both pip._vendor and the bare names
189 # for the case where someone unbundles our libraries.
190 "loggers": {
191 name: {
192 "level": (
193 "WARNING" if level in ["INFO", "ERROR"] else "DEBUG"
194 )
195 } for name in [
196 "pip._vendor", "distlib", "requests", "urllib3"
197 ]
198 },
199 })
200
201 if sys.version_info[:2] == (3, 3):
202 warnings.warn(
203 "Python 3.3 supported has been deprecated and support for it "
204 "will be dropped in the future. Please upgrade your Python.",
205 deprecation.RemovedInPip11Warning,
206 )
207
208 # TODO: try to get these passing down from the command?
209 # without resorting to os.environ to hold these.
210
211 if options.no_input:
212 os.environ['PIP_NO_INPUT'] = '1'
213
214 if options.exists_action:
215 os.environ['PIP_EXISTS_ACTION'] = ' '.join(options.exists_action)
216
217 if options.require_venv and not self.ignore_require_venv:
218 # If a venv is required check if it can really be found
219 if not running_under_virtualenv():
220 logger.critical(
221 'Could not find an activated virtualenv (required).'
222 )
223 sys.exit(VIRTUALENV_NOT_FOUND)
224
225 original_root_handlers = set(logging.root.handlers)
226
227 try:
228 status = self.run(options, args)
229 # FIXME: all commands should return an exit status
230 # and when it is done, isinstance is not needed anymore
231 if isinstance(status, int):
232 return status
233 except PreviousBuildDirError as exc:
234 logger.critical(str(exc))
235 logger.debug('Exception information:', exc_info=True)
236
237 return PREVIOUS_BUILD_DIR_ERROR
238 except (InstallationError, UninstallationError, BadCommand) as exc:
239 logger.critical(str(exc))
240 logger.debug('Exception information:', exc_info=True)
241
242 return ERROR
243 except CommandError as exc:
244 logger.critical('ERROR: %s', exc)
245 logger.debug('Exception information:', exc_info=True)
246
247 return ERROR
248 except KeyboardInterrupt:
249 logger.critical('Operation cancelled by user')
250 logger.debug('Exception information:', exc_info=True)
251
252 return ERROR
253 except:
254 logger.critical('Exception:', exc_info=True)
255
256 return UNKNOWN_ERROR
257 finally:
258 # Check if we're using the latest version of pip available
259 if (not options.disable_pip_version_check and not
260 getattr(options, "no_index", False)):
261 with self._build_session(
262 options,
263 retries=0,
264 timeout=min(5, options.timeout)) as session:
265 pip_version_check(session, options)
266 # Avoid leaking loggers
267 for handler in set(logging.root.handlers) - original_root_handlers:
268 # this method benefit from the Logger class internal lock
269 logging.root.removeHandler(handler)
270
271 return SUCCESS
272
273
274class RequirementCommand(Command):
275
276 @staticmethod
277 def populate_requirement_set(requirement_set, args, options, finder,
278 session, name, wheel_cache):
279 """
280 Marshal cmd line args into a requirement set.
281 """
282 # NOTE: As a side-effect, options.require_hashes and
283 # requirement_set.require_hashes may be updated
284
285 for filename in options.constraints:
286 for req_to_add in parse_requirements(
287 filename,
288 constraint=True, finder=finder, options=options,
289 session=session, wheel_cache=wheel_cache):
290 req_to_add.is_direct = True
291 requirement_set.add_requirement(req_to_add)
292
293 for req in args:
294 req_to_add = InstallRequirement.from_line(
295 req, None, isolated=options.isolated_mode,
296 wheel_cache=wheel_cache
297 )
298 req_to_add.is_direct = True
299 requirement_set.add_requirement(req_to_add)
300
301 for req in options.editables:
302 req_to_add = InstallRequirement.from_editable(
303 req,
304 isolated=options.isolated_mode,
305 wheel_cache=wheel_cache
306 )
307 req_to_add.is_direct = True
308 requirement_set.add_requirement(req_to_add)
309
310 for filename in options.requirements:
311 for req_to_add in parse_requirements(
312 filename,
313 finder=finder, options=options, session=session,
314 wheel_cache=wheel_cache):
315 req_to_add.is_direct = True
316 requirement_set.add_requirement(req_to_add)
317 # If --require-hashes was a line in a requirements file, tell
318 # RequirementSet about it:
319 requirement_set.require_hashes = options.require_hashes
320
321 if not (args or options.editables or options.requirements):
322 opts = {'name': name}
323 if options.find_links:
324 raise CommandError(
325 'You must give at least one requirement to %(name)s '
326 '(maybe you meant "pip %(name)s %(links)s"?)' %
327 dict(opts, links=' '.join(options.find_links)))
328 else:
329 raise CommandError(
330 'You must give at least one requirement to %(name)s '
331 '(see "pip help %(name)s")' % opts)
332
333 # On Windows, any operation modifying pip should be run as:
334 # python -m pip ...
335 # See https://github.com/pypa/pip/issues/1299 for more discussion
336 should_show_use_python_msg = (
337 WINDOWS and
338 requirement_set.has_requirement("pip") and
339 os.path.basename(sys.argv[0]).startswith("pip")
340 )
341 if should_show_use_python_msg:
342 new_command = [
343 sys.executable, "-m", "pip"
344 ] + sys.argv[1:]
345 raise CommandError(
346 'To modify pip, please run the following command:\n{}'
347 .format(" ".join(new_command))
348 )
349
350 def _build_package_finder(self, options, session,
351 platform=None, python_versions=None,
352 abi=None, implementation=None):
353 """
354 Create a package finder appropriate to this requirement command.
355 """
356 index_urls = [options.index_url] + options.extra_index_urls
357 if options.no_index:
358 logger.debug('Ignoring indexes: %s', ','.join(index_urls))
359 index_urls = []
360
361 return PackageFinder(
362 find_links=options.find_links,
363 format_control=options.format_control,
364 index_urls=index_urls,
365 trusted_hosts=options.trusted_hosts,
366 allow_all_prereleases=options.pre,
367 process_dependency_links=options.process_dependency_links,
368 session=session,
369 platform=platform,
370 versions=python_versions,
371 abi=abi,
372 implementation=implementation,
373 )