Mercurial > repos > guerler > hhblits
comparison lib/python3.8/site-packages/pip/_internal/cli/base_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 """Base Command class, and related routines""" | |
| 2 | |
| 3 from __future__ import absolute_import, print_function | |
| 4 | |
| 5 import logging | |
| 6 import logging.config | |
| 7 import optparse | |
| 8 import os | |
| 9 import platform | |
| 10 import sys | |
| 11 import traceback | |
| 12 | |
| 13 from pip._internal.cli import cmdoptions | |
| 14 from pip._internal.cli.command_context import CommandContextMixIn | |
| 15 from pip._internal.cli.parser import ( | |
| 16 ConfigOptionParser, | |
| 17 UpdatingDefaultsHelpFormatter, | |
| 18 ) | |
| 19 from pip._internal.cli.status_codes import ( | |
| 20 ERROR, | |
| 21 PREVIOUS_BUILD_DIR_ERROR, | |
| 22 SUCCESS, | |
| 23 UNKNOWN_ERROR, | |
| 24 VIRTUALENV_NOT_FOUND, | |
| 25 ) | |
| 26 from pip._internal.exceptions import ( | |
| 27 BadCommand, | |
| 28 CommandError, | |
| 29 InstallationError, | |
| 30 PreviousBuildDirError, | |
| 31 UninstallationError, | |
| 32 ) | |
| 33 from pip._internal.utils.deprecation import deprecated | |
| 34 from pip._internal.utils.filesystem import check_path_owner | |
| 35 from pip._internal.utils.logging import BrokenStdoutLoggingError, setup_logging | |
| 36 from pip._internal.utils.misc import get_prog, normalize_path | |
| 37 from pip._internal.utils.temp_dir import global_tempdir_manager | |
| 38 from pip._internal.utils.typing import MYPY_CHECK_RUNNING | |
| 39 from pip._internal.utils.virtualenv import running_under_virtualenv | |
| 40 | |
| 41 if MYPY_CHECK_RUNNING: | |
| 42 from typing import List, Tuple, Any | |
| 43 from optparse import Values | |
| 44 | |
| 45 __all__ = ['Command'] | |
| 46 | |
| 47 logger = logging.getLogger(__name__) | |
| 48 | |
| 49 | |
| 50 class Command(CommandContextMixIn): | |
| 51 usage = None # type: str | |
| 52 ignore_require_venv = False # type: bool | |
| 53 | |
| 54 def __init__(self, name, summary, isolated=False): | |
| 55 # type: (str, str, bool) -> None | |
| 56 super(Command, self).__init__() | |
| 57 parser_kw = { | |
| 58 'usage': self.usage, | |
| 59 'prog': '%s %s' % (get_prog(), name), | |
| 60 'formatter': UpdatingDefaultsHelpFormatter(), | |
| 61 'add_help_option': False, | |
| 62 'name': name, | |
| 63 'description': self.__doc__, | |
| 64 'isolated': isolated, | |
| 65 } | |
| 66 | |
| 67 self.name = name | |
| 68 self.summary = summary | |
| 69 self.parser = ConfigOptionParser(**parser_kw) | |
| 70 | |
| 71 # Commands should add options to this option group | |
| 72 optgroup_name = '%s Options' % self.name.capitalize() | |
| 73 self.cmd_opts = optparse.OptionGroup(self.parser, optgroup_name) | |
| 74 | |
| 75 # Add the general options | |
| 76 gen_opts = cmdoptions.make_option_group( | |
| 77 cmdoptions.general_group, | |
| 78 self.parser, | |
| 79 ) | |
| 80 self.parser.add_option_group(gen_opts) | |
| 81 | |
| 82 def handle_pip_version_check(self, options): | |
| 83 # type: (Values) -> None | |
| 84 """ | |
| 85 This is a no-op so that commands by default do not do the pip version | |
| 86 check. | |
| 87 """ | |
| 88 # Make sure we do the pip version check if the index_group options | |
| 89 # are present. | |
| 90 assert not hasattr(options, 'no_index') | |
| 91 | |
| 92 def run(self, options, args): | |
| 93 # type: (Values, List[Any]) -> Any | |
| 94 raise NotImplementedError | |
| 95 | |
| 96 def parse_args(self, args): | |
| 97 # type: (List[str]) -> Tuple[Any, Any] | |
| 98 # factored out for testability | |
| 99 return self.parser.parse_args(args) | |
| 100 | |
| 101 def main(self, args): | |
| 102 # type: (List[str]) -> int | |
| 103 try: | |
| 104 with self.main_context(): | |
| 105 return self._main(args) | |
| 106 finally: | |
| 107 logging.shutdown() | |
| 108 | |
| 109 def _main(self, args): | |
| 110 # type: (List[str]) -> int | |
| 111 # Intentionally set as early as possible so globally-managed temporary | |
| 112 # directories are available to the rest of the code. | |
| 113 self.enter_context(global_tempdir_manager()) | |
| 114 | |
| 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 level_number = setup_logging( | |
| 121 verbosity=self.verbosity, | |
| 122 no_color=options.no_color, | |
| 123 user_log_file=options.log, | |
| 124 ) | |
| 125 | |
| 126 if ( | |
| 127 sys.version_info[:2] == (2, 7) and | |
| 128 not options.no_python_version_warning | |
| 129 ): | |
| 130 message = ( | |
| 131 "A future version of pip will drop support for Python 2.7. " | |
| 132 "More details about Python 2 support in pip, can be found at " | |
| 133 "https://pip.pypa.io/en/latest/development/release-process/#python-2-support" # noqa | |
| 134 ) | |
| 135 if platform.python_implementation() == "CPython": | |
| 136 message = ( | |
| 137 "Python 2.7 reached the end of its life on January " | |
| 138 "1st, 2020. Please upgrade your Python as Python 2.7 " | |
| 139 "is no longer maintained. " | |
| 140 ) + message | |
| 141 deprecated(message, replacement=None, gone_in=None) | |
| 142 | |
| 143 if options.skip_requirements_regex: | |
| 144 deprecated( | |
| 145 "--skip-requirements-regex is unsupported and will be removed", | |
| 146 replacement=( | |
| 147 "manage requirements/constraints files explicitly, " | |
| 148 "possibly generating them from metadata" | |
| 149 ), | |
| 150 gone_in="20.1", | |
| 151 issue=7297, | |
| 152 ) | |
| 153 | |
| 154 # TODO: Try to get these passing down from the command? | |
| 155 # without resorting to os.environ to hold these. | |
| 156 # This also affects isolated builds and it should. | |
| 157 | |
| 158 if options.no_input: | |
| 159 os.environ['PIP_NO_INPUT'] = '1' | |
| 160 | |
| 161 if options.exists_action: | |
| 162 os.environ['PIP_EXISTS_ACTION'] = ' '.join(options.exists_action) | |
| 163 | |
| 164 if options.require_venv and not self.ignore_require_venv: | |
| 165 # If a venv is required check if it can really be found | |
| 166 if not running_under_virtualenv(): | |
| 167 logger.critical( | |
| 168 'Could not find an activated virtualenv (required).' | |
| 169 ) | |
| 170 sys.exit(VIRTUALENV_NOT_FOUND) | |
| 171 | |
| 172 if options.cache_dir: | |
| 173 options.cache_dir = normalize_path(options.cache_dir) | |
| 174 if not check_path_owner(options.cache_dir): | |
| 175 logger.warning( | |
| 176 "The directory '%s' or its parent directory is not owned " | |
| 177 "or is not writable by the current user. The cache " | |
| 178 "has been disabled. Check the permissions and owner of " | |
| 179 "that directory. If executing pip with sudo, you may want " | |
| 180 "sudo's -H flag.", | |
| 181 options.cache_dir, | |
| 182 ) | |
| 183 options.cache_dir = None | |
| 184 | |
| 185 try: | |
| 186 status = self.run(options, args) | |
| 187 # FIXME: all commands should return an exit status | |
| 188 # and when it is done, isinstance is not needed anymore | |
| 189 if isinstance(status, int): | |
| 190 return status | |
| 191 except PreviousBuildDirError as exc: | |
| 192 logger.critical(str(exc)) | |
| 193 logger.debug('Exception information:', exc_info=True) | |
| 194 | |
| 195 return PREVIOUS_BUILD_DIR_ERROR | |
| 196 except (InstallationError, UninstallationError, BadCommand) as exc: | |
| 197 logger.critical(str(exc)) | |
| 198 logger.debug('Exception information:', exc_info=True) | |
| 199 | |
| 200 return ERROR | |
| 201 except CommandError as exc: | |
| 202 logger.critical('%s', exc) | |
| 203 logger.debug('Exception information:', exc_info=True) | |
| 204 | |
| 205 return ERROR | |
| 206 except BrokenStdoutLoggingError: | |
| 207 # Bypass our logger and write any remaining messages to stderr | |
| 208 # because stdout no longer works. | |
| 209 print('ERROR: Pipe to stdout was broken', file=sys.stderr) | |
| 210 if level_number <= logging.DEBUG: | |
| 211 traceback.print_exc(file=sys.stderr) | |
| 212 | |
| 213 return ERROR | |
| 214 except KeyboardInterrupt: | |
| 215 logger.critical('Operation cancelled by user') | |
| 216 logger.debug('Exception information:', exc_info=True) | |
| 217 | |
| 218 return ERROR | |
| 219 except BaseException: | |
| 220 logger.critical('Exception:', exc_info=True) | |
| 221 | |
| 222 return UNKNOWN_ERROR | |
| 223 finally: | |
| 224 self.handle_pip_version_check(options) | |
| 225 | |
| 226 return SUCCESS |
