comparison venv/lib/python2.7/site-packages/pip/basecommand.py @ 0:d67268158946 draft

planemo upload commit a3f181f5f126803c654b3a66dd4e83a48f7e203b
author bcclaywell
date Mon, 12 Oct 2015 17:43:33 -0400
parents
children
comparison
equal deleted inserted replaced
-1:000000000000 0:d67268158946
1 """Base Command class, and related routines"""
2 from __future__ import absolute_import
3
4 import logging
5 import os
6 import sys
7 import traceback
8 import optparse
9 import warnings
10
11 from pip._vendor.six import StringIO
12
13 from pip import cmdoptions
14 from pip.locations import running_under_virtualenv
15 from pip.download import PipSession
16 from pip.exceptions import (BadCommand, InstallationError, UninstallationError,
17 CommandError, PreviousBuildDirError)
18 from pip.compat import logging_dictConfig
19 from pip.baseparser import ConfigOptionParser, UpdatingDefaultsHelpFormatter
20 from pip.status_codes import (
21 SUCCESS, ERROR, UNKNOWN_ERROR, VIRTUALENV_NOT_FOUND,
22 PREVIOUS_BUILD_DIR_ERROR,
23 )
24 from pip.utils import appdirs, get_prog, normalize_path
25 from pip.utils.deprecation import RemovedInPip8Warning
26 from pip.utils.filesystem import check_path_owner
27 from pip.utils.logging import IndentingFormatter
28 from pip.utils.outdated import pip_version_check
29
30
31 __all__ = ['Command']
32
33
34 logger = logging.getLogger(__name__)
35
36
37 class Command(object):
38 name = None
39 usage = None
40 hidden = False
41 log_streams = ("ext://sys.stdout", "ext://sys.stderr")
42
43 def __init__(self, isolated=False):
44 parser_kw = {
45 'usage': self.usage,
46 'prog': '%s %s' % (get_prog(), self.name),
47 'formatter': UpdatingDefaultsHelpFormatter(),
48 'add_help_option': False,
49 'name': self.name,
50 'description': self.__doc__,
51 'isolated': isolated,
52 }
53
54 self.parser = ConfigOptionParser(**parser_kw)
55
56 # Commands should add options to this option group
57 optgroup_name = '%s Options' % self.name.capitalize()
58 self.cmd_opts = optparse.OptionGroup(self.parser, optgroup_name)
59
60 # Add the general options
61 gen_opts = cmdoptions.make_option_group(
62 cmdoptions.general_group,
63 self.parser,
64 )
65 self.parser.add_option_group(gen_opts)
66
67 def _build_session(self, options, retries=None, timeout=None):
68 session = PipSession(
69 cache=(
70 normalize_path(os.path.join(options.cache_dir, "http"))
71 if options.cache_dir else None
72 ),
73 retries=retries if retries is not None else options.retries,
74 insecure_hosts=options.trusted_hosts,
75 )
76
77 # Handle custom ca-bundles from the user
78 if options.cert:
79 session.verify = options.cert
80
81 # Handle SSL client certificate
82 if options.client_cert:
83 session.cert = options.client_cert
84
85 # Handle timeouts
86 if options.timeout or timeout:
87 session.timeout = (
88 timeout if timeout is not None else options.timeout
89 )
90
91 # Handle configured proxies
92 if options.proxy:
93 session.proxies = {
94 "http": options.proxy,
95 "https": options.proxy,
96 }
97
98 # Determine if we can prompt the user for authentication or not
99 session.auth.prompting = not options.no_input
100
101 return session
102
103 def parse_args(self, args):
104 # factored out for testability
105 return self.parser.parse_args(args)
106
107 def main(self, args):
108 options, args = self.parse_args(args)
109
110 if options.quiet:
111 level = "WARNING"
112 elif options.verbose:
113 level = "DEBUG"
114 else:
115 level = "INFO"
116
117 # Compute the path for our debug log.
118 debug_log_path = os.path.join(appdirs.user_log_dir("pip"), "debug.log")
119
120 # Ensure that the path for our debug log is owned by the current user
121 # and if it is not, disable the debug log.
122 write_debug_log = check_path_owner(debug_log_path)
123
124 logging_dictConfig({
125 "version": 1,
126 "disable_existing_loggers": False,
127 "filters": {
128 "exclude_warnings": {
129 "()": "pip.utils.logging.MaxLevelFilter",
130 "level": logging.WARNING,
131 },
132 },
133 "formatters": {
134 "indent": {
135 "()": IndentingFormatter,
136 "format": (
137 "%(message)s"
138 if not options.log_explicit_levels
139 else "[%(levelname)s] %(message)s"
140 ),
141 },
142 },
143 "handlers": {
144 "console": {
145 "level": level,
146 "class": "pip.utils.logging.ColorizedStreamHandler",
147 "stream": self.log_streams[0],
148 "filters": ["exclude_warnings"],
149 "formatter": "indent",
150 },
151 "console_errors": {
152 "level": "WARNING",
153 "class": "pip.utils.logging.ColorizedStreamHandler",
154 "stream": self.log_streams[1],
155 "formatter": "indent",
156 },
157 "debug_log": {
158 "level": "DEBUG",
159 "class": "pip.utils.logging.BetterRotatingFileHandler",
160 "filename": debug_log_path,
161 "maxBytes": 10 * 1000 * 1000, # 10 MB
162 "backupCount": 1,
163 "delay": True,
164 "formatter": "indent",
165 },
166 "user_log": {
167 "level": "DEBUG",
168 "class": "pip.utils.logging.BetterRotatingFileHandler",
169 "filename": options.log or "/dev/null",
170 "delay": True,
171 "formatter": "indent",
172 },
173 },
174 "root": {
175 "level": level,
176 "handlers": list(filter(None, [
177 "console",
178 "console_errors",
179 "debug_log" if write_debug_log else None,
180 "user_log" if options.log else None,
181 ])),
182 },
183 # Disable any logging besides WARNING unless we have DEBUG level
184 # logging enabled. These use both pip._vendor and the bare names
185 # for the case where someone unbundles our libraries.
186 "loggers": dict(
187 (
188 name,
189 {
190 "level": (
191 "WARNING"
192 if level in ["INFO", "ERROR"]
193 else "DEBUG"
194 ),
195 },
196 )
197 for name in ["pip._vendor", "distlib", "requests", "urllib3"]
198 ),
199 })
200
201 # We add this warning here instead of up above, because the logger
202 # hasn't been configured until just now.
203 if not write_debug_log:
204 logger.warning(
205 "The directory '%s' or its parent directory is not owned by "
206 "the current user and the debug log has been disabled. Please "
207 "check the permissions and owner of that directory. If "
208 "executing pip with sudo, you may want sudo's -H flag.",
209 os.path.dirname(debug_log_path),
210 )
211
212 if options.log_explicit_levels:
213 warnings.warn(
214 "--log-explicit-levels has been deprecated and will be removed"
215 " in a future version.",
216 RemovedInPip8Warning,
217 )
218
219 # TODO: try to get these passing down from the command?
220 # without resorting to os.environ to hold these.
221
222 if options.no_input:
223 os.environ['PIP_NO_INPUT'] = '1'
224
225 if options.exists_action:
226 os.environ['PIP_EXISTS_ACTION'] = ' '.join(options.exists_action)
227
228 if options.require_venv:
229 # If a venv is required check if it can really be found
230 if not running_under_virtualenv():
231 logger.critical(
232 'Could not find an activated virtualenv (required).'
233 )
234 sys.exit(VIRTUALENV_NOT_FOUND)
235
236 # Check if we're using the latest version of pip available
237 if (not options.disable_pip_version_check and not
238 getattr(options, "no_index", False)):
239 with self._build_session(
240 options,
241 retries=0,
242 timeout=min(5, options.timeout)) as session:
243 pip_version_check(session)
244
245 try:
246 status = self.run(options, args)
247 # FIXME: all commands should return an exit status
248 # and when it is done, isinstance is not needed anymore
249 if isinstance(status, int):
250 return status
251 except PreviousBuildDirError as exc:
252 logger.critical(str(exc))
253 logger.debug('Exception information:\n%s', format_exc())
254
255 return PREVIOUS_BUILD_DIR_ERROR
256 except (InstallationError, UninstallationError, BadCommand) as exc:
257 logger.critical(str(exc))
258 logger.debug('Exception information:\n%s', format_exc())
259
260 return ERROR
261 except CommandError as exc:
262 logger.critical('ERROR: %s', exc)
263 logger.debug('Exception information:\n%s', format_exc())
264
265 return ERROR
266 except KeyboardInterrupt:
267 logger.critical('Operation cancelled by user')
268 logger.debug('Exception information:\n%s', format_exc())
269
270 return ERROR
271 except:
272 logger.critical('Exception:\n%s', format_exc())
273
274 return UNKNOWN_ERROR
275
276 return SUCCESS
277
278
279 def format_exc(exc_info=None):
280 if exc_info is None:
281 exc_info = sys.exc_info()
282 out = StringIO()
283 traceback.print_exception(*exc_info, **dict(file=out))
284 return out.getvalue()