Mercurial > repos > guerler > springsuite
comparison planemo/lib/python3.7/site-packages/pip/_internal/cli/parser.py @ 1:56ad4e20f292 draft
"planemo upload commit 6eee67778febed82ddd413c3ca40b3183a3898f1"
| author | guerler |
|---|---|
| date | Fri, 31 Jul 2020 00:32:28 -0400 |
| parents | |
| children |
comparison
equal
deleted
inserted
replaced
| 0:d30785e31577 | 1:56ad4e20f292 |
|---|---|
| 1 """Base option parser setup""" | |
| 2 from __future__ import absolute_import | |
| 3 | |
| 4 import logging | |
| 5 import optparse | |
| 6 import sys | |
| 7 import textwrap | |
| 8 from distutils.util import strtobool | |
| 9 | |
| 10 from pip._vendor.six import string_types | |
| 11 | |
| 12 from pip._internal.cli.status_codes import UNKNOWN_ERROR | |
| 13 from pip._internal.configuration import Configuration, ConfigurationError | |
| 14 from pip._internal.utils.compat import get_terminal_size | |
| 15 | |
| 16 logger = logging.getLogger(__name__) | |
| 17 | |
| 18 | |
| 19 class PrettyHelpFormatter(optparse.IndentedHelpFormatter): | |
| 20 """A prettier/less verbose help formatter for optparse.""" | |
| 21 | |
| 22 def __init__(self, *args, **kwargs): | |
| 23 # help position must be aligned with __init__.parseopts.description | |
| 24 kwargs['max_help_position'] = 30 | |
| 25 kwargs['indent_increment'] = 1 | |
| 26 kwargs['width'] = get_terminal_size()[0] - 2 | |
| 27 optparse.IndentedHelpFormatter.__init__(self, *args, **kwargs) | |
| 28 | |
| 29 def format_option_strings(self, option): | |
| 30 return self._format_option_strings(option, ' <%s>', ', ') | |
| 31 | |
| 32 def _format_option_strings(self, option, mvarfmt=' <%s>', optsep=', '): | |
| 33 """ | |
| 34 Return a comma-separated list of option strings and metavars. | |
| 35 | |
| 36 :param option: tuple of (short opt, long opt), e.g: ('-f', '--format') | |
| 37 :param mvarfmt: metavar format string - evaluated as mvarfmt % metavar | |
| 38 :param optsep: separator | |
| 39 """ | |
| 40 opts = [] | |
| 41 | |
| 42 if option._short_opts: | |
| 43 opts.append(option._short_opts[0]) | |
| 44 if option._long_opts: | |
| 45 opts.append(option._long_opts[0]) | |
| 46 if len(opts) > 1: | |
| 47 opts.insert(1, optsep) | |
| 48 | |
| 49 if option.takes_value(): | |
| 50 metavar = option.metavar or option.dest.lower() | |
| 51 opts.append(mvarfmt % metavar.lower()) | |
| 52 | |
| 53 return ''.join(opts) | |
| 54 | |
| 55 def format_heading(self, heading): | |
| 56 if heading == 'Options': | |
| 57 return '' | |
| 58 return heading + ':\n' | |
| 59 | |
| 60 def format_usage(self, usage): | |
| 61 """ | |
| 62 Ensure there is only one newline between usage and the first heading | |
| 63 if there is no description. | |
| 64 """ | |
| 65 msg = '\nUsage: %s\n' % self.indent_lines(textwrap.dedent(usage), " ") | |
| 66 return msg | |
| 67 | |
| 68 def format_description(self, description): | |
| 69 # leave full control over description to us | |
| 70 if description: | |
| 71 if hasattr(self.parser, 'main'): | |
| 72 label = 'Commands' | |
| 73 else: | |
| 74 label = 'Description' | |
| 75 # some doc strings have initial newlines, some don't | |
| 76 description = description.lstrip('\n') | |
| 77 # some doc strings have final newlines and spaces, some don't | |
| 78 description = description.rstrip() | |
| 79 # dedent, then reindent | |
| 80 description = self.indent_lines(textwrap.dedent(description), " ") | |
| 81 description = '%s:\n%s\n' % (label, description) | |
| 82 return description | |
| 83 else: | |
| 84 return '' | |
| 85 | |
| 86 def format_epilog(self, epilog): | |
| 87 # leave full control over epilog to us | |
| 88 if epilog: | |
| 89 return epilog | |
| 90 else: | |
| 91 return '' | |
| 92 | |
| 93 def indent_lines(self, text, indent): | |
| 94 new_lines = [indent + line for line in text.split('\n')] | |
| 95 return "\n".join(new_lines) | |
| 96 | |
| 97 | |
| 98 class UpdatingDefaultsHelpFormatter(PrettyHelpFormatter): | |
| 99 """Custom help formatter for use in ConfigOptionParser. | |
| 100 | |
| 101 This is updates the defaults before expanding them, allowing | |
| 102 them to show up correctly in the help listing. | |
| 103 """ | |
| 104 | |
| 105 def expand_default(self, option): | |
| 106 if self.parser is not None: | |
| 107 self.parser._update_defaults(self.parser.defaults) | |
| 108 return optparse.IndentedHelpFormatter.expand_default(self, option) | |
| 109 | |
| 110 | |
| 111 class CustomOptionParser(optparse.OptionParser): | |
| 112 | |
| 113 def insert_option_group(self, idx, *args, **kwargs): | |
| 114 """Insert an OptionGroup at a given position.""" | |
| 115 group = self.add_option_group(*args, **kwargs) | |
| 116 | |
| 117 self.option_groups.pop() | |
| 118 self.option_groups.insert(idx, group) | |
| 119 | |
| 120 return group | |
| 121 | |
| 122 @property | |
| 123 def option_list_all(self): | |
| 124 """Get a list of all options, including those in option groups.""" | |
| 125 res = self.option_list[:] | |
| 126 for i in self.option_groups: | |
| 127 res.extend(i.option_list) | |
| 128 | |
| 129 return res | |
| 130 | |
| 131 | |
| 132 class ConfigOptionParser(CustomOptionParser): | |
| 133 """Custom option parser which updates its defaults by checking the | |
| 134 configuration files and environmental variables""" | |
| 135 | |
| 136 def __init__(self, *args, **kwargs): | |
| 137 self.name = kwargs.pop('name') | |
| 138 | |
| 139 isolated = kwargs.pop("isolated", False) | |
| 140 self.config = Configuration(isolated) | |
| 141 | |
| 142 assert self.name | |
| 143 optparse.OptionParser.__init__(self, *args, **kwargs) | |
| 144 | |
| 145 def check_default(self, option, key, val): | |
| 146 try: | |
| 147 return option.check_value(key, val) | |
| 148 except optparse.OptionValueError as exc: | |
| 149 print("An error occurred during configuration: %s" % exc) | |
| 150 sys.exit(3) | |
| 151 | |
| 152 def _get_ordered_configuration_items(self): | |
| 153 # Configuration gives keys in an unordered manner. Order them. | |
| 154 override_order = ["global", self.name, ":env:"] | |
| 155 | |
| 156 # Pool the options into different groups | |
| 157 section_items = {name: [] for name in override_order} | |
| 158 for section_key, val in self.config.items(): | |
| 159 # ignore empty values | |
| 160 if not val: | |
| 161 logger.debug( | |
| 162 "Ignoring configuration key '%s' as it's value is empty.", | |
| 163 section_key | |
| 164 ) | |
| 165 continue | |
| 166 | |
| 167 section, key = section_key.split(".", 1) | |
| 168 if section in override_order: | |
| 169 section_items[section].append((key, val)) | |
| 170 | |
| 171 # Yield each group in their override order | |
| 172 for section in override_order: | |
| 173 for key, val in section_items[section]: | |
| 174 yield key, val | |
| 175 | |
| 176 def _update_defaults(self, defaults): | |
| 177 """Updates the given defaults with values from the config files and | |
| 178 the environ. Does a little special handling for certain types of | |
| 179 options (lists).""" | |
| 180 | |
| 181 # Accumulate complex default state. | |
| 182 self.values = optparse.Values(self.defaults) | |
| 183 late_eval = set() | |
| 184 # Then set the options with those values | |
| 185 for key, val in self._get_ordered_configuration_items(): | |
| 186 # '--' because configuration supports only long names | |
| 187 option = self.get_option('--' + key) | |
| 188 | |
| 189 # Ignore options not present in this parser. E.g. non-globals put | |
| 190 # in [global] by users that want them to apply to all applicable | |
| 191 # commands. | |
| 192 if option is None: | |
| 193 continue | |
| 194 | |
| 195 if option.action in ('store_true', 'store_false', 'count'): | |
| 196 try: | |
| 197 val = strtobool(val) | |
| 198 except ValueError: | |
| 199 error_msg = invalid_config_error_message( | |
| 200 option.action, key, val | |
| 201 ) | |
| 202 self.error(error_msg) | |
| 203 | |
| 204 elif option.action == 'append': | |
| 205 val = val.split() | |
| 206 val = [self.check_default(option, key, v) for v in val] | |
| 207 elif option.action == 'callback': | |
| 208 late_eval.add(option.dest) | |
| 209 opt_str = option.get_opt_string() | |
| 210 val = option.convert_value(opt_str, val) | |
| 211 # From take_action | |
| 212 args = option.callback_args or () | |
| 213 kwargs = option.callback_kwargs or {} | |
| 214 option.callback(option, opt_str, val, self, *args, **kwargs) | |
| 215 else: | |
| 216 val = self.check_default(option, key, val) | |
| 217 | |
| 218 defaults[option.dest] = val | |
| 219 | |
| 220 for key in late_eval: | |
| 221 defaults[key] = getattr(self.values, key) | |
| 222 self.values = None | |
| 223 return defaults | |
| 224 | |
| 225 def get_default_values(self): | |
| 226 """Overriding to make updating the defaults after instantiation of | |
| 227 the option parser possible, _update_defaults() does the dirty work.""" | |
| 228 if not self.process_default_values: | |
| 229 # Old, pre-Optik 1.5 behaviour. | |
| 230 return optparse.Values(self.defaults) | |
| 231 | |
| 232 # Load the configuration, or error out in case of an error | |
| 233 try: | |
| 234 self.config.load() | |
| 235 except ConfigurationError as err: | |
| 236 self.exit(UNKNOWN_ERROR, str(err)) | |
| 237 | |
| 238 defaults = self._update_defaults(self.defaults.copy()) # ours | |
| 239 for option in self._get_all_options(): | |
| 240 default = defaults.get(option.dest) | |
| 241 if isinstance(default, string_types): | |
| 242 opt_str = option.get_opt_string() | |
| 243 defaults[option.dest] = option.check_value(opt_str, default) | |
| 244 return optparse.Values(defaults) | |
| 245 | |
| 246 def error(self, msg): | |
| 247 self.print_usage(sys.stderr) | |
| 248 self.exit(UNKNOWN_ERROR, "%s\n" % msg) | |
| 249 | |
| 250 | |
| 251 def invalid_config_error_message(action, key, val): | |
| 252 """Returns a better error message when invalid configuration option | |
| 253 is provided.""" | |
| 254 if action in ('store_true', 'store_false'): | |
| 255 return ("{0} is not a valid value for {1} option, " | |
| 256 "please specify a boolean value like yes/no, " | |
| 257 "true/false or 1/0 instead.").format(val, key) | |
| 258 | |
| 259 return ("{0} is not a valid value for {1} option, " | |
| 260 "please specify a numerical value like 1/0 " | |
| 261 "instead.").format(val, key) |
