Mercurial > repos > shellac > sam_consensus_v3
comparison env/lib/python3.9/site-packages/argcomplete/my_argparse.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 # Copyright 2012-2019, Andrey Kislyuk and argcomplete contributors. | |
| 2 # Licensed under the Apache License. See https://github.com/kislyuk/argcomplete for more info. | |
| 3 | |
| 4 from argparse import ArgumentParser, ArgumentError, SUPPRESS, _SubParsersAction | |
| 5 from argparse import OPTIONAL, ZERO_OR_MORE, ONE_OR_MORE, REMAINDER, PARSER | |
| 6 from argparse import _get_action_name, _ | |
| 7 | |
| 8 _num_consumed_args = {} | |
| 9 | |
| 10 | |
| 11 def action_is_satisfied(action): | |
| 12 ''' Returns False if the parse would raise an error if no more arguments are given to this action, True otherwise. | |
| 13 ''' | |
| 14 num_consumed_args = _num_consumed_args.get(action, 0) | |
| 15 | |
| 16 if action.nargs in [OPTIONAL, ZERO_OR_MORE, REMAINDER]: | |
| 17 return True | |
| 18 if action.nargs == ONE_OR_MORE: | |
| 19 return num_consumed_args >= 1 | |
| 20 if action.nargs == PARSER: | |
| 21 # Not sure what this should be, but this previously always returned False | |
| 22 # so at least this won't break anything that wasn't already broken. | |
| 23 return False | |
| 24 if action.nargs is None: | |
| 25 return num_consumed_args == 1 | |
| 26 | |
| 27 assert isinstance(action.nargs, int), 'failed to handle a possible nargs value: %r' % action.nargs | |
| 28 return num_consumed_args == action.nargs | |
| 29 | |
| 30 | |
| 31 def action_is_open(action): | |
| 32 ''' Returns True if action could consume more arguments (i.e., its pattern is open). | |
| 33 ''' | |
| 34 num_consumed_args = _num_consumed_args.get(action, 0) | |
| 35 | |
| 36 if action.nargs in [ZERO_OR_MORE, ONE_OR_MORE, PARSER, REMAINDER]: | |
| 37 return True | |
| 38 if action.nargs == OPTIONAL or action.nargs is None: | |
| 39 return num_consumed_args == 0 | |
| 40 | |
| 41 assert isinstance(action.nargs, int), 'failed to handle a possible nargs value: %r' % action.nargs | |
| 42 return num_consumed_args < action.nargs | |
| 43 | |
| 44 | |
| 45 def action_is_greedy(action, isoptional=False): | |
| 46 ''' Returns True if action will necessarily consume the next argument. | |
| 47 isoptional indicates whether the argument is an optional (starts with -). | |
| 48 ''' | |
| 49 num_consumed_args = _num_consumed_args.get(action, 0) | |
| 50 | |
| 51 if action.option_strings: | |
| 52 if not isoptional and not action_is_satisfied(action): | |
| 53 return True | |
| 54 return action.nargs == REMAINDER | |
| 55 else: | |
| 56 return action.nargs == REMAINDER and num_consumed_args >= 1 | |
| 57 | |
| 58 | |
| 59 class IntrospectiveArgumentParser(ArgumentParser): | |
| 60 ''' The following is a verbatim copy of ArgumentParser._parse_known_args (Python 2.7.3), | |
| 61 except for the lines that contain the string "Added by argcomplete". | |
| 62 ''' | |
| 63 | |
| 64 def _parse_known_args(self, arg_strings, namespace): | |
| 65 _num_consumed_args.clear() # Added by argcomplete | |
| 66 self._argcomplete_namespace = namespace | |
| 67 self.active_actions = [] # Added by argcomplete | |
| 68 # replace arg strings that are file references | |
| 69 if self.fromfile_prefix_chars is not None: | |
| 70 arg_strings = self._read_args_from_files(arg_strings) | |
| 71 | |
| 72 # map all mutually exclusive arguments to the other arguments | |
| 73 # they can't occur with | |
| 74 action_conflicts = {} | |
| 75 self._action_conflicts = action_conflicts # Added by argcomplete | |
| 76 for mutex_group in self._mutually_exclusive_groups: | |
| 77 group_actions = mutex_group._group_actions | |
| 78 for i, mutex_action in enumerate(mutex_group._group_actions): | |
| 79 conflicts = action_conflicts.setdefault(mutex_action, []) | |
| 80 conflicts.extend(group_actions[:i]) | |
| 81 conflicts.extend(group_actions[i + 1:]) | |
| 82 | |
| 83 # find all option indices, and determine the arg_string_pattern | |
| 84 # which has an 'O' if there is an option at an index, | |
| 85 # an 'A' if there is an argument, or a '-' if there is a '--' | |
| 86 option_string_indices = {} | |
| 87 arg_string_pattern_parts = [] | |
| 88 arg_strings_iter = iter(arg_strings) | |
| 89 for i, arg_string in enumerate(arg_strings_iter): | |
| 90 | |
| 91 # all args after -- are non-options | |
| 92 if arg_string == '--': | |
| 93 arg_string_pattern_parts.append('-') | |
| 94 for arg_string in arg_strings_iter: | |
| 95 arg_string_pattern_parts.append('A') | |
| 96 | |
| 97 # otherwise, add the arg to the arg strings | |
| 98 # and note the index if it was an option | |
| 99 else: | |
| 100 option_tuple = self._parse_optional(arg_string) | |
| 101 if option_tuple is None: | |
| 102 pattern = 'A' | |
| 103 else: | |
| 104 option_string_indices[i] = option_tuple | |
| 105 pattern = 'O' | |
| 106 arg_string_pattern_parts.append(pattern) | |
| 107 | |
| 108 # join the pieces together to form the pattern | |
| 109 arg_strings_pattern = ''.join(arg_string_pattern_parts) | |
| 110 | |
| 111 # converts arg strings to the appropriate and then takes the action | |
| 112 seen_actions = set() | |
| 113 seen_non_default_actions = set() | |
| 114 self._seen_non_default_actions = seen_non_default_actions # Added by argcomplete | |
| 115 | |
| 116 def take_action(action, argument_strings, option_string=None): | |
| 117 seen_actions.add(action) | |
| 118 argument_values = self._get_values(action, argument_strings) | |
| 119 | |
| 120 # error if this argument is not allowed with other previously | |
| 121 # seen arguments, assuming that actions that use the default | |
| 122 # value don't really count as "present" | |
| 123 if argument_values is not action.default: | |
| 124 seen_non_default_actions.add(action) | |
| 125 for conflict_action in action_conflicts.get(action, []): | |
| 126 if conflict_action in seen_non_default_actions: | |
| 127 msg = _('not allowed with argument %s') | |
| 128 action_name = _get_action_name(conflict_action) | |
| 129 raise ArgumentError(action, msg % action_name) | |
| 130 | |
| 131 # take the action if we didn't receive a SUPPRESS value | |
| 132 # (e.g. from a default) | |
| 133 if argument_values is not SUPPRESS \ | |
| 134 or isinstance(action, _SubParsersAction): | |
| 135 try: | |
| 136 action(self, namespace, argument_values, option_string) | |
| 137 except: | |
| 138 # Begin added by argcomplete | |
| 139 # When a subparser action is taken and fails due to incomplete arguments, it does not merge the | |
| 140 # contents of its parsed namespace into the parent namespace. Do that here to allow completers to | |
| 141 # access the partially parsed arguments for the subparser. | |
| 142 if isinstance(action, _SubParsersAction): | |
| 143 subnamespace = action._name_parser_map[argument_values[0]]._argcomplete_namespace | |
| 144 for key, value in vars(subnamespace).items(): | |
| 145 setattr(namespace, key, value) | |
| 146 # End added by argcomplete | |
| 147 raise | |
| 148 | |
| 149 # function to convert arg_strings into an optional action | |
| 150 def consume_optional(start_index): | |
| 151 | |
| 152 # get the optional identified at this index | |
| 153 option_tuple = option_string_indices[start_index] | |
| 154 action, option_string, explicit_arg = option_tuple | |
| 155 | |
| 156 # identify additional optionals in the same arg string | |
| 157 # (e.g. -xyz is the same as -x -y -z if no args are required) | |
| 158 match_argument = self._match_argument | |
| 159 action_tuples = [] | |
| 160 while True: | |
| 161 | |
| 162 # if we found no optional action, skip it | |
| 163 if action is None: | |
| 164 extras.append(arg_strings[start_index]) | |
| 165 return start_index + 1 | |
| 166 | |
| 167 # if there is an explicit argument, try to match the | |
| 168 # optional's string arguments to only this | |
| 169 if explicit_arg is not None: | |
| 170 arg_count = match_argument(action, 'A') | |
| 171 | |
| 172 # if the action is a single-dash option and takes no | |
| 173 # arguments, try to parse more single-dash options out | |
| 174 # of the tail of the option string | |
| 175 chars = self.prefix_chars | |
| 176 if arg_count == 0 and option_string[1] not in chars: | |
| 177 action_tuples.append((action, [], option_string)) | |
| 178 char = option_string[0] | |
| 179 option_string = char + explicit_arg[0] | |
| 180 new_explicit_arg = explicit_arg[1:] or None | |
| 181 optionals_map = self._option_string_actions | |
| 182 if option_string in optionals_map: | |
| 183 action = optionals_map[option_string] | |
| 184 explicit_arg = new_explicit_arg | |
| 185 else: | |
| 186 msg = _('ignored explicit argument %r') | |
| 187 raise ArgumentError(action, msg % explicit_arg) | |
| 188 | |
| 189 # if the action expect exactly one argument, we've | |
| 190 # successfully matched the option; exit the loop | |
| 191 elif arg_count == 1: | |
| 192 stop = start_index + 1 | |
| 193 args = [explicit_arg] | |
| 194 action_tuples.append((action, args, option_string)) | |
| 195 break | |
| 196 | |
| 197 # error if a double-dash option did not use the | |
| 198 # explicit argument | |
| 199 else: | |
| 200 msg = _('ignored explicit argument %r') | |
| 201 raise ArgumentError(action, msg % explicit_arg) | |
| 202 | |
| 203 # if there is no explicit argument, try to match the | |
| 204 # optional's string arguments with the following strings | |
| 205 # if successful, exit the loop | |
| 206 else: | |
| 207 start = start_index + 1 | |
| 208 selected_patterns = arg_strings_pattern[start:] | |
| 209 self.active_actions = [action] # Added by argcomplete | |
| 210 _num_consumed_args[action] = 0 # Added by argcomplete | |
| 211 arg_count = match_argument(action, selected_patterns) | |
| 212 stop = start + arg_count | |
| 213 args = arg_strings[start:stop] | |
| 214 | |
| 215 # Begin added by argcomplete | |
| 216 # If the pattern is not open (e.g. no + at the end), remove the action from active actions (since | |
| 217 # it wouldn't be able to consume any more args) | |
| 218 _num_consumed_args[action] = len(args) | |
| 219 if not action_is_open(action): | |
| 220 self.active_actions.remove(action) | |
| 221 # End added by argcomplete | |
| 222 | |
| 223 action_tuples.append((action, args, option_string)) | |
| 224 break | |
| 225 | |
| 226 # add the Optional to the list and return the index at which | |
| 227 # the Optional's string args stopped | |
| 228 assert action_tuples | |
| 229 for action, args, option_string in action_tuples: | |
| 230 take_action(action, args, option_string) | |
| 231 return stop | |
| 232 | |
| 233 # the list of Positionals left to be parsed; this is modified | |
| 234 # by consume_positionals() | |
| 235 positionals = self._get_positional_actions() | |
| 236 | |
| 237 # function to convert arg_strings into positional actions | |
| 238 def consume_positionals(start_index): | |
| 239 # match as many Positionals as possible | |
| 240 match_partial = self._match_arguments_partial | |
| 241 selected_pattern = arg_strings_pattern[start_index:] | |
| 242 arg_counts = match_partial(positionals, selected_pattern) | |
| 243 | |
| 244 # slice off the appropriate arg strings for each Positional | |
| 245 # and add the Positional and its args to the list | |
| 246 for action, arg_count in zip(positionals, arg_counts): # Added by argcomplete | |
| 247 self.active_actions.append(action) # Added by argcomplete | |
| 248 for action, arg_count in zip(positionals, arg_counts): | |
| 249 args = arg_strings[start_index: start_index + arg_count] | |
| 250 start_index += arg_count | |
| 251 _num_consumed_args[action] = len(args) # Added by argcomplete | |
| 252 take_action(action, args) | |
| 253 | |
| 254 # slice off the Positionals that we just parsed and return the | |
| 255 # index at which the Positionals' string args stopped | |
| 256 positionals[:] = positionals[len(arg_counts):] | |
| 257 return start_index | |
| 258 | |
| 259 # consume Positionals and Optionals alternately, until we have | |
| 260 # passed the last option string | |
| 261 extras = [] | |
| 262 start_index = 0 | |
| 263 if option_string_indices: | |
| 264 max_option_string_index = max(option_string_indices) | |
| 265 else: | |
| 266 max_option_string_index = -1 | |
| 267 while start_index <= max_option_string_index: | |
| 268 | |
| 269 # consume any Positionals preceding the next option | |
| 270 next_option_string_index = min([ | |
| 271 index | |
| 272 for index in option_string_indices | |
| 273 if index >= start_index]) | |
| 274 if start_index != next_option_string_index: | |
| 275 positionals_end_index = consume_positionals(start_index) | |
| 276 | |
| 277 # only try to parse the next optional if we didn't consume | |
| 278 # the option string during the positionals parsing | |
| 279 if positionals_end_index > start_index: | |
| 280 start_index = positionals_end_index | |
| 281 continue | |
| 282 else: | |
| 283 start_index = positionals_end_index | |
| 284 | |
| 285 # if we consumed all the positionals we could and we're not | |
| 286 # at the index of an option string, there were extra arguments | |
| 287 if start_index not in option_string_indices: | |
| 288 strings = arg_strings[start_index:next_option_string_index] | |
| 289 extras.extend(strings) | |
| 290 start_index = next_option_string_index | |
| 291 | |
| 292 # consume the next optional and any arguments for it | |
| 293 start_index = consume_optional(start_index) | |
| 294 | |
| 295 # consume any positionals following the last Optional | |
| 296 stop_index = consume_positionals(start_index) | |
| 297 | |
| 298 # if we didn't consume all the argument strings, there were extras | |
| 299 extras.extend(arg_strings[stop_index:]) | |
| 300 | |
| 301 # if we didn't use all the Positional objects, there were too few | |
| 302 # arg strings supplied. | |
| 303 | |
| 304 if positionals: | |
| 305 self.active_actions.append(positionals[0]) # Added by argcomplete | |
| 306 self.error(_('too few arguments')) | |
| 307 | |
| 308 # make sure all required actions were present | |
| 309 for action in self._actions: | |
| 310 if action.required: | |
| 311 if action not in seen_actions: | |
| 312 name = _get_action_name(action) | |
| 313 self.error(_('argument %s is required') % name) | |
| 314 | |
| 315 # make sure all required groups had one option present | |
| 316 for group in self._mutually_exclusive_groups: | |
| 317 if group.required: | |
| 318 for action in group._group_actions: | |
| 319 if action in seen_non_default_actions: | |
| 320 break | |
| 321 | |
| 322 # if no actions were used, report the error | |
| 323 else: | |
| 324 names = [_get_action_name(action) | |
| 325 for action in group._group_actions | |
| 326 if action.help is not SUPPRESS] | |
| 327 msg = _('one of the arguments %s is required') | |
| 328 self.error(msg % ' '.join(names)) | |
| 329 | |
| 330 # return the updated namespace and the extra arguments | |
| 331 return namespace, extras |
