comparison env/lib/python3.9/site-packages/pip/_internal/cli/base_command.py @ 0:4f3585e2f14b draft default tip

"planemo upload commit 60cee0fc7c0cda8592644e1aad72851dec82c959"
author shellac
date Mon, 22 Mar 2021 18:12:50 +0000
parents
children
comparison
equal deleted inserted replaced
-1:000000000000 0:4f3585e2f14b
1 """Base Command class, and related routines"""
2
3 import logging
4 import logging.config
5 import optparse
6 import os
7 import sys
8 import traceback
9
10 from pip._internal.cli import cmdoptions
11 from pip._internal.cli.command_context import CommandContextMixIn
12 from pip._internal.cli.parser import ConfigOptionParser, UpdatingDefaultsHelpFormatter
13 from pip._internal.cli.status_codes import (
14 ERROR,
15 PREVIOUS_BUILD_DIR_ERROR,
16 UNKNOWN_ERROR,
17 VIRTUALENV_NOT_FOUND,
18 )
19 from pip._internal.exceptions import (
20 BadCommand,
21 CommandError,
22 InstallationError,
23 NetworkConnectionError,
24 PreviousBuildDirError,
25 UninstallationError,
26 )
27 from pip._internal.utils.deprecation import deprecated
28 from pip._internal.utils.filesystem import check_path_owner
29 from pip._internal.utils.logging import BrokenStdoutLoggingError, setup_logging
30 from pip._internal.utils.misc import get_prog, normalize_path
31 from pip._internal.utils.temp_dir import global_tempdir_manager, tempdir_registry
32 from pip._internal.utils.typing import MYPY_CHECK_RUNNING
33 from pip._internal.utils.virtualenv import running_under_virtualenv
34
35 if MYPY_CHECK_RUNNING:
36 from optparse import Values
37 from typing import Any, List, Optional, Tuple
38
39 from pip._internal.utils.temp_dir import (
40 TempDirectoryTypeRegistry as TempDirRegistry,
41 )
42
43 __all__ = ['Command']
44
45 logger = logging.getLogger(__name__)
46
47
48 class Command(CommandContextMixIn):
49 usage = None # type: str
50 ignore_require_venv = False # type: bool
51
52 def __init__(self, name, summary, isolated=False):
53 # type: (str, str, bool) -> None
54 super().__init__()
55 parser_kw = {
56 'usage': self.usage,
57 'prog': f'{get_prog()} {name}',
58 'formatter': UpdatingDefaultsHelpFormatter(),
59 'add_help_option': False,
60 'name': name,
61 'description': self.__doc__,
62 'isolated': isolated,
63 }
64
65 self.name = name
66 self.summary = summary
67 self.parser = ConfigOptionParser(**parser_kw)
68
69 self.tempdir_registry = None # type: Optional[TempDirRegistry]
70
71 # Commands should add options to this option group
72 optgroup_name = f'{self.name.capitalize()} Options'
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 self.add_options()
83
84 def add_options(self):
85 # type: () -> None
86 pass
87
88 def handle_pip_version_check(self, options):
89 # type: (Values) -> None
90 """
91 This is a no-op so that commands by default do not do the pip version
92 check.
93 """
94 # Make sure we do the pip version check if the index_group options
95 # are present.
96 assert not hasattr(options, 'no_index')
97
98 def run(self, options, args):
99 # type: (Values, List[Any]) -> int
100 raise NotImplementedError
101
102 def parse_args(self, args):
103 # type: (List[str]) -> Tuple[Any, Any]
104 # factored out for testability
105 return self.parser.parse_args(args)
106
107 def main(self, args):
108 # type: (List[str]) -> int
109 try:
110 with self.main_context():
111 return self._main(args)
112 finally:
113 logging.shutdown()
114
115 def _main(self, args):
116 # type: (List[str]) -> int
117 # We must initialize this before the tempdir manager, otherwise the
118 # configuration would not be accessible by the time we clean up the
119 # tempdir manager.
120 self.tempdir_registry = self.enter_context(tempdir_registry())
121 # Intentionally set as early as possible so globally-managed temporary
122 # directories are available to the rest of the code.
123 self.enter_context(global_tempdir_manager())
124
125 options, args = self.parse_args(args)
126
127 # Set verbosity so that it can be used elsewhere.
128 self.verbosity = options.verbose - options.quiet
129
130 level_number = setup_logging(
131 verbosity=self.verbosity,
132 no_color=options.no_color,
133 user_log_file=options.log,
134 )
135
136 # TODO: Try to get these passing down from the command?
137 # without resorting to os.environ to hold these.
138 # This also affects isolated builds and it should.
139
140 if options.no_input:
141 os.environ['PIP_NO_INPUT'] = '1'
142
143 if options.exists_action:
144 os.environ['PIP_EXISTS_ACTION'] = ' '.join(options.exists_action)
145
146 if options.require_venv and not self.ignore_require_venv:
147 # If a venv is required check if it can really be found
148 if not running_under_virtualenv():
149 logger.critical(
150 'Could not find an activated virtualenv (required).'
151 )
152 sys.exit(VIRTUALENV_NOT_FOUND)
153
154 if options.cache_dir:
155 options.cache_dir = normalize_path(options.cache_dir)
156 if not check_path_owner(options.cache_dir):
157 logger.warning(
158 "The directory '%s' or its parent directory is not owned "
159 "or is not writable by the current user. The cache "
160 "has been disabled. Check the permissions and owner of "
161 "that directory. If executing pip with sudo, you may want "
162 "sudo's -H flag.",
163 options.cache_dir,
164 )
165 options.cache_dir = None
166
167 if getattr(options, "build_dir", None):
168 deprecated(
169 reason=(
170 "The -b/--build/--build-dir/--build-directory "
171 "option is deprecated and has no effect anymore."
172 ),
173 replacement=(
174 "use the TMPDIR/TEMP/TMP environment variable, "
175 "possibly combined with --no-clean"
176 ),
177 gone_in="21.1",
178 issue=8333,
179 )
180
181 if '2020-resolver' in options.features_enabled:
182 logger.warning(
183 "--use-feature=2020-resolver no longer has any effect, "
184 "since it is now the default dependency resolver in pip. "
185 "This will become an error in pip 21.0."
186 )
187
188 try:
189 status = self.run(options, args)
190 assert isinstance(status, int)
191 return status
192 except PreviousBuildDirError as exc:
193 logger.critical(str(exc))
194 logger.debug('Exception information:', exc_info=True)
195
196 return PREVIOUS_BUILD_DIR_ERROR
197 except (InstallationError, UninstallationError, BadCommand,
198 NetworkConnectionError) as exc:
199 logger.critical(str(exc))
200 logger.debug('Exception information:', exc_info=True)
201
202 return ERROR
203 except CommandError as exc:
204 logger.critical('%s', exc)
205 logger.debug('Exception information:', exc_info=True)
206
207 return ERROR
208 except BrokenStdoutLoggingError:
209 # Bypass our logger and write any remaining messages to stderr
210 # because stdout no longer works.
211 print('ERROR: Pipe to stdout was broken', file=sys.stderr)
212 if level_number <= logging.DEBUG:
213 traceback.print_exc(file=sys.stderr)
214
215 return ERROR
216 except KeyboardInterrupt:
217 logger.critical('Operation cancelled by user')
218 logger.debug('Exception information:', exc_info=True)
219
220 return ERROR
221 except BaseException:
222 logger.critical('Exception:', exc_info=True)
223
224 return UNKNOWN_ERROR
225 finally:
226 self.handle_pip_version_check(options)