1*cda5da8dSAndroid Build Coastguard Worker# Author: Steven J. Bethard <[email protected]>. 2*cda5da8dSAndroid Build Coastguard Worker# New maintainer as of 29 August 2019: Raymond Hettinger <[email protected]> 3*cda5da8dSAndroid Build Coastguard Worker 4*cda5da8dSAndroid Build Coastguard Worker"""Command-line parsing library 5*cda5da8dSAndroid Build Coastguard Worker 6*cda5da8dSAndroid Build Coastguard WorkerThis module is an optparse-inspired command-line parsing library that: 7*cda5da8dSAndroid Build Coastguard Worker 8*cda5da8dSAndroid Build Coastguard Worker - handles both optional and positional arguments 9*cda5da8dSAndroid Build Coastguard Worker - produces highly informative usage messages 10*cda5da8dSAndroid Build Coastguard Worker - supports parsers that dispatch to sub-parsers 11*cda5da8dSAndroid Build Coastguard Worker 12*cda5da8dSAndroid Build Coastguard WorkerThe following is a simple usage example that sums integers from the 13*cda5da8dSAndroid Build Coastguard Workercommand-line and writes the result to a file:: 14*cda5da8dSAndroid Build Coastguard Worker 15*cda5da8dSAndroid Build Coastguard Worker parser = argparse.ArgumentParser( 16*cda5da8dSAndroid Build Coastguard Worker description='sum the integers at the command line') 17*cda5da8dSAndroid Build Coastguard Worker parser.add_argument( 18*cda5da8dSAndroid Build Coastguard Worker 'integers', metavar='int', nargs='+', type=int, 19*cda5da8dSAndroid Build Coastguard Worker help='an integer to be summed') 20*cda5da8dSAndroid Build Coastguard Worker parser.add_argument( 21*cda5da8dSAndroid Build Coastguard Worker '--log', default=sys.stdout, type=argparse.FileType('w'), 22*cda5da8dSAndroid Build Coastguard Worker help='the file where the sum should be written') 23*cda5da8dSAndroid Build Coastguard Worker args = parser.parse_args() 24*cda5da8dSAndroid Build Coastguard Worker args.log.write('%s' % sum(args.integers)) 25*cda5da8dSAndroid Build Coastguard Worker args.log.close() 26*cda5da8dSAndroid Build Coastguard Worker 27*cda5da8dSAndroid Build Coastguard WorkerThe module contains the following public classes: 28*cda5da8dSAndroid Build Coastguard Worker 29*cda5da8dSAndroid Build Coastguard Worker - ArgumentParser -- The main entry point for command-line parsing. As the 30*cda5da8dSAndroid Build Coastguard Worker example above shows, the add_argument() method is used to populate 31*cda5da8dSAndroid Build Coastguard Worker the parser with actions for optional and positional arguments. Then 32*cda5da8dSAndroid Build Coastguard Worker the parse_args() method is invoked to convert the args at the 33*cda5da8dSAndroid Build Coastguard Worker command-line into an object with attributes. 34*cda5da8dSAndroid Build Coastguard Worker 35*cda5da8dSAndroid Build Coastguard Worker - ArgumentError -- The exception raised by ArgumentParser objects when 36*cda5da8dSAndroid Build Coastguard Worker there are errors with the parser's actions. Errors raised while 37*cda5da8dSAndroid Build Coastguard Worker parsing the command-line are caught by ArgumentParser and emitted 38*cda5da8dSAndroid Build Coastguard Worker as command-line messages. 39*cda5da8dSAndroid Build Coastguard Worker 40*cda5da8dSAndroid Build Coastguard Worker - FileType -- A factory for defining types of files to be created. As the 41*cda5da8dSAndroid Build Coastguard Worker example above shows, instances of FileType are typically passed as 42*cda5da8dSAndroid Build Coastguard Worker the type= argument of add_argument() calls. 43*cda5da8dSAndroid Build Coastguard Worker 44*cda5da8dSAndroid Build Coastguard Worker - Action -- The base class for parser actions. Typically actions are 45*cda5da8dSAndroid Build Coastguard Worker selected by passing strings like 'store_true' or 'append_const' to 46*cda5da8dSAndroid Build Coastguard Worker the action= argument of add_argument(). However, for greater 47*cda5da8dSAndroid Build Coastguard Worker customization of ArgumentParser actions, subclasses of Action may 48*cda5da8dSAndroid Build Coastguard Worker be defined and passed as the action= argument. 49*cda5da8dSAndroid Build Coastguard Worker 50*cda5da8dSAndroid Build Coastguard Worker - HelpFormatter, RawDescriptionHelpFormatter, RawTextHelpFormatter, 51*cda5da8dSAndroid Build Coastguard Worker ArgumentDefaultsHelpFormatter -- Formatter classes which 52*cda5da8dSAndroid Build Coastguard Worker may be passed as the formatter_class= argument to the 53*cda5da8dSAndroid Build Coastguard Worker ArgumentParser constructor. HelpFormatter is the default, 54*cda5da8dSAndroid Build Coastguard Worker RawDescriptionHelpFormatter and RawTextHelpFormatter tell the parser 55*cda5da8dSAndroid Build Coastguard Worker not to change the formatting for help text, and 56*cda5da8dSAndroid Build Coastguard Worker ArgumentDefaultsHelpFormatter adds information about argument defaults 57*cda5da8dSAndroid Build Coastguard Worker to the help. 58*cda5da8dSAndroid Build Coastguard Worker 59*cda5da8dSAndroid Build Coastguard WorkerAll other classes in this module are considered implementation details. 60*cda5da8dSAndroid Build Coastguard Worker(Also note that HelpFormatter and RawDescriptionHelpFormatter are only 61*cda5da8dSAndroid Build Coastguard Workerconsidered public as object names -- the API of the formatter objects is 62*cda5da8dSAndroid Build Coastguard Workerstill considered an implementation detail.) 63*cda5da8dSAndroid Build Coastguard Worker""" 64*cda5da8dSAndroid Build Coastguard Worker 65*cda5da8dSAndroid Build Coastguard Worker__version__ = '1.1' 66*cda5da8dSAndroid Build Coastguard Worker__all__ = [ 67*cda5da8dSAndroid Build Coastguard Worker 'ArgumentParser', 68*cda5da8dSAndroid Build Coastguard Worker 'ArgumentError', 69*cda5da8dSAndroid Build Coastguard Worker 'ArgumentTypeError', 70*cda5da8dSAndroid Build Coastguard Worker 'BooleanOptionalAction', 71*cda5da8dSAndroid Build Coastguard Worker 'FileType', 72*cda5da8dSAndroid Build Coastguard Worker 'HelpFormatter', 73*cda5da8dSAndroid Build Coastguard Worker 'ArgumentDefaultsHelpFormatter', 74*cda5da8dSAndroid Build Coastguard Worker 'RawDescriptionHelpFormatter', 75*cda5da8dSAndroid Build Coastguard Worker 'RawTextHelpFormatter', 76*cda5da8dSAndroid Build Coastguard Worker 'MetavarTypeHelpFormatter', 77*cda5da8dSAndroid Build Coastguard Worker 'Namespace', 78*cda5da8dSAndroid Build Coastguard Worker 'Action', 79*cda5da8dSAndroid Build Coastguard Worker 'ONE_OR_MORE', 80*cda5da8dSAndroid Build Coastguard Worker 'OPTIONAL', 81*cda5da8dSAndroid Build Coastguard Worker 'PARSER', 82*cda5da8dSAndroid Build Coastguard Worker 'REMAINDER', 83*cda5da8dSAndroid Build Coastguard Worker 'SUPPRESS', 84*cda5da8dSAndroid Build Coastguard Worker 'ZERO_OR_MORE', 85*cda5da8dSAndroid Build Coastguard Worker] 86*cda5da8dSAndroid Build Coastguard Worker 87*cda5da8dSAndroid Build Coastguard Worker 88*cda5da8dSAndroid Build Coastguard Workerimport os as _os 89*cda5da8dSAndroid Build Coastguard Workerimport re as _re 90*cda5da8dSAndroid Build Coastguard Workerimport sys as _sys 91*cda5da8dSAndroid Build Coastguard Worker 92*cda5da8dSAndroid Build Coastguard Workerimport warnings 93*cda5da8dSAndroid Build Coastguard Worker 94*cda5da8dSAndroid Build Coastguard Workerfrom gettext import gettext as _, ngettext 95*cda5da8dSAndroid Build Coastguard Worker 96*cda5da8dSAndroid Build Coastguard WorkerSUPPRESS = '==SUPPRESS==' 97*cda5da8dSAndroid Build Coastguard Worker 98*cda5da8dSAndroid Build Coastguard WorkerOPTIONAL = '?' 99*cda5da8dSAndroid Build Coastguard WorkerZERO_OR_MORE = '*' 100*cda5da8dSAndroid Build Coastguard WorkerONE_OR_MORE = '+' 101*cda5da8dSAndroid Build Coastguard WorkerPARSER = 'A...' 102*cda5da8dSAndroid Build Coastguard WorkerREMAINDER = '...' 103*cda5da8dSAndroid Build Coastguard Worker_UNRECOGNIZED_ARGS_ATTR = '_unrecognized_args' 104*cda5da8dSAndroid Build Coastguard Worker 105*cda5da8dSAndroid Build Coastguard Worker# ============================= 106*cda5da8dSAndroid Build Coastguard Worker# Utility functions and classes 107*cda5da8dSAndroid Build Coastguard Worker# ============================= 108*cda5da8dSAndroid Build Coastguard Worker 109*cda5da8dSAndroid Build Coastguard Workerclass _AttributeHolder(object): 110*cda5da8dSAndroid Build Coastguard Worker """Abstract base class that provides __repr__. 111*cda5da8dSAndroid Build Coastguard Worker 112*cda5da8dSAndroid Build Coastguard Worker The __repr__ method returns a string in the format:: 113*cda5da8dSAndroid Build Coastguard Worker ClassName(attr=name, attr=name, ...) 114*cda5da8dSAndroid Build Coastguard Worker The attributes are determined either by a class-level attribute, 115*cda5da8dSAndroid Build Coastguard Worker '_kwarg_names', or by inspecting the instance __dict__. 116*cda5da8dSAndroid Build Coastguard Worker """ 117*cda5da8dSAndroid Build Coastguard Worker 118*cda5da8dSAndroid Build Coastguard Worker def __repr__(self): 119*cda5da8dSAndroid Build Coastguard Worker type_name = type(self).__name__ 120*cda5da8dSAndroid Build Coastguard Worker arg_strings = [] 121*cda5da8dSAndroid Build Coastguard Worker star_args = {} 122*cda5da8dSAndroid Build Coastguard Worker for arg in self._get_args(): 123*cda5da8dSAndroid Build Coastguard Worker arg_strings.append(repr(arg)) 124*cda5da8dSAndroid Build Coastguard Worker for name, value in self._get_kwargs(): 125*cda5da8dSAndroid Build Coastguard Worker if name.isidentifier(): 126*cda5da8dSAndroid Build Coastguard Worker arg_strings.append('%s=%r' % (name, value)) 127*cda5da8dSAndroid Build Coastguard Worker else: 128*cda5da8dSAndroid Build Coastguard Worker star_args[name] = value 129*cda5da8dSAndroid Build Coastguard Worker if star_args: 130*cda5da8dSAndroid Build Coastguard Worker arg_strings.append('**%s' % repr(star_args)) 131*cda5da8dSAndroid Build Coastguard Worker return '%s(%s)' % (type_name, ', '.join(arg_strings)) 132*cda5da8dSAndroid Build Coastguard Worker 133*cda5da8dSAndroid Build Coastguard Worker def _get_kwargs(self): 134*cda5da8dSAndroid Build Coastguard Worker return list(self.__dict__.items()) 135*cda5da8dSAndroid Build Coastguard Worker 136*cda5da8dSAndroid Build Coastguard Worker def _get_args(self): 137*cda5da8dSAndroid Build Coastguard Worker return [] 138*cda5da8dSAndroid Build Coastguard Worker 139*cda5da8dSAndroid Build Coastguard Worker 140*cda5da8dSAndroid Build Coastguard Workerdef _copy_items(items): 141*cda5da8dSAndroid Build Coastguard Worker if items is None: 142*cda5da8dSAndroid Build Coastguard Worker return [] 143*cda5da8dSAndroid Build Coastguard Worker # The copy module is used only in the 'append' and 'append_const' 144*cda5da8dSAndroid Build Coastguard Worker # actions, and it is needed only when the default value isn't a list. 145*cda5da8dSAndroid Build Coastguard Worker # Delay its import for speeding up the common case. 146*cda5da8dSAndroid Build Coastguard Worker if type(items) is list: 147*cda5da8dSAndroid Build Coastguard Worker return items[:] 148*cda5da8dSAndroid Build Coastguard Worker import copy 149*cda5da8dSAndroid Build Coastguard Worker return copy.copy(items) 150*cda5da8dSAndroid Build Coastguard Worker 151*cda5da8dSAndroid Build Coastguard Worker 152*cda5da8dSAndroid Build Coastguard Worker# =============== 153*cda5da8dSAndroid Build Coastguard Worker# Formatting Help 154*cda5da8dSAndroid Build Coastguard Worker# =============== 155*cda5da8dSAndroid Build Coastguard Worker 156*cda5da8dSAndroid Build Coastguard Worker 157*cda5da8dSAndroid Build Coastguard Workerclass HelpFormatter(object): 158*cda5da8dSAndroid Build Coastguard Worker """Formatter for generating usage messages and argument help strings. 159*cda5da8dSAndroid Build Coastguard Worker 160*cda5da8dSAndroid Build Coastguard Worker Only the name of this class is considered a public API. All the methods 161*cda5da8dSAndroid Build Coastguard Worker provided by the class are considered an implementation detail. 162*cda5da8dSAndroid Build Coastguard Worker """ 163*cda5da8dSAndroid Build Coastguard Worker 164*cda5da8dSAndroid Build Coastguard Worker def __init__(self, 165*cda5da8dSAndroid Build Coastguard Worker prog, 166*cda5da8dSAndroid Build Coastguard Worker indent_increment=2, 167*cda5da8dSAndroid Build Coastguard Worker max_help_position=24, 168*cda5da8dSAndroid Build Coastguard Worker width=None): 169*cda5da8dSAndroid Build Coastguard Worker 170*cda5da8dSAndroid Build Coastguard Worker # default setting for width 171*cda5da8dSAndroid Build Coastguard Worker if width is None: 172*cda5da8dSAndroid Build Coastguard Worker import shutil 173*cda5da8dSAndroid Build Coastguard Worker width = shutil.get_terminal_size().columns 174*cda5da8dSAndroid Build Coastguard Worker width -= 2 175*cda5da8dSAndroid Build Coastguard Worker 176*cda5da8dSAndroid Build Coastguard Worker self._prog = prog 177*cda5da8dSAndroid Build Coastguard Worker self._indent_increment = indent_increment 178*cda5da8dSAndroid Build Coastguard Worker self._max_help_position = min(max_help_position, 179*cda5da8dSAndroid Build Coastguard Worker max(width - 20, indent_increment * 2)) 180*cda5da8dSAndroid Build Coastguard Worker self._width = width 181*cda5da8dSAndroid Build Coastguard Worker 182*cda5da8dSAndroid Build Coastguard Worker self._current_indent = 0 183*cda5da8dSAndroid Build Coastguard Worker self._level = 0 184*cda5da8dSAndroid Build Coastguard Worker self._action_max_length = 0 185*cda5da8dSAndroid Build Coastguard Worker 186*cda5da8dSAndroid Build Coastguard Worker self._root_section = self._Section(self, None) 187*cda5da8dSAndroid Build Coastguard Worker self._current_section = self._root_section 188*cda5da8dSAndroid Build Coastguard Worker 189*cda5da8dSAndroid Build Coastguard Worker self._whitespace_matcher = _re.compile(r'\s+', _re.ASCII) 190*cda5da8dSAndroid Build Coastguard Worker self._long_break_matcher = _re.compile(r'\n\n\n+') 191*cda5da8dSAndroid Build Coastguard Worker 192*cda5da8dSAndroid Build Coastguard Worker # =============================== 193*cda5da8dSAndroid Build Coastguard Worker # Section and indentation methods 194*cda5da8dSAndroid Build Coastguard Worker # =============================== 195*cda5da8dSAndroid Build Coastguard Worker def _indent(self): 196*cda5da8dSAndroid Build Coastguard Worker self._current_indent += self._indent_increment 197*cda5da8dSAndroid Build Coastguard Worker self._level += 1 198*cda5da8dSAndroid Build Coastguard Worker 199*cda5da8dSAndroid Build Coastguard Worker def _dedent(self): 200*cda5da8dSAndroid Build Coastguard Worker self._current_indent -= self._indent_increment 201*cda5da8dSAndroid Build Coastguard Worker assert self._current_indent >= 0, 'Indent decreased below 0.' 202*cda5da8dSAndroid Build Coastguard Worker self._level -= 1 203*cda5da8dSAndroid Build Coastguard Worker 204*cda5da8dSAndroid Build Coastguard Worker class _Section(object): 205*cda5da8dSAndroid Build Coastguard Worker 206*cda5da8dSAndroid Build Coastguard Worker def __init__(self, formatter, parent, heading=None): 207*cda5da8dSAndroid Build Coastguard Worker self.formatter = formatter 208*cda5da8dSAndroid Build Coastguard Worker self.parent = parent 209*cda5da8dSAndroid Build Coastguard Worker self.heading = heading 210*cda5da8dSAndroid Build Coastguard Worker self.items = [] 211*cda5da8dSAndroid Build Coastguard Worker 212*cda5da8dSAndroid Build Coastguard Worker def format_help(self): 213*cda5da8dSAndroid Build Coastguard Worker # format the indented section 214*cda5da8dSAndroid Build Coastguard Worker if self.parent is not None: 215*cda5da8dSAndroid Build Coastguard Worker self.formatter._indent() 216*cda5da8dSAndroid Build Coastguard Worker join = self.formatter._join_parts 217*cda5da8dSAndroid Build Coastguard Worker item_help = join([func(*args) for func, args in self.items]) 218*cda5da8dSAndroid Build Coastguard Worker if self.parent is not None: 219*cda5da8dSAndroid Build Coastguard Worker self.formatter._dedent() 220*cda5da8dSAndroid Build Coastguard Worker 221*cda5da8dSAndroid Build Coastguard Worker # return nothing if the section was empty 222*cda5da8dSAndroid Build Coastguard Worker if not item_help: 223*cda5da8dSAndroid Build Coastguard Worker return '' 224*cda5da8dSAndroid Build Coastguard Worker 225*cda5da8dSAndroid Build Coastguard Worker # add the heading if the section was non-empty 226*cda5da8dSAndroid Build Coastguard Worker if self.heading is not SUPPRESS and self.heading is not None: 227*cda5da8dSAndroid Build Coastguard Worker current_indent = self.formatter._current_indent 228*cda5da8dSAndroid Build Coastguard Worker heading = '%*s%s:\n' % (current_indent, '', self.heading) 229*cda5da8dSAndroid Build Coastguard Worker else: 230*cda5da8dSAndroid Build Coastguard Worker heading = '' 231*cda5da8dSAndroid Build Coastguard Worker 232*cda5da8dSAndroid Build Coastguard Worker # join the section-initial newline, the heading and the help 233*cda5da8dSAndroid Build Coastguard Worker return join(['\n', heading, item_help, '\n']) 234*cda5da8dSAndroid Build Coastguard Worker 235*cda5da8dSAndroid Build Coastguard Worker def _add_item(self, func, args): 236*cda5da8dSAndroid Build Coastguard Worker self._current_section.items.append((func, args)) 237*cda5da8dSAndroid Build Coastguard Worker 238*cda5da8dSAndroid Build Coastguard Worker # ======================== 239*cda5da8dSAndroid Build Coastguard Worker # Message building methods 240*cda5da8dSAndroid Build Coastguard Worker # ======================== 241*cda5da8dSAndroid Build Coastguard Worker def start_section(self, heading): 242*cda5da8dSAndroid Build Coastguard Worker self._indent() 243*cda5da8dSAndroid Build Coastguard Worker section = self._Section(self, self._current_section, heading) 244*cda5da8dSAndroid Build Coastguard Worker self._add_item(section.format_help, []) 245*cda5da8dSAndroid Build Coastguard Worker self._current_section = section 246*cda5da8dSAndroid Build Coastguard Worker 247*cda5da8dSAndroid Build Coastguard Worker def end_section(self): 248*cda5da8dSAndroid Build Coastguard Worker self._current_section = self._current_section.parent 249*cda5da8dSAndroid Build Coastguard Worker self._dedent() 250*cda5da8dSAndroid Build Coastguard Worker 251*cda5da8dSAndroid Build Coastguard Worker def add_text(self, text): 252*cda5da8dSAndroid Build Coastguard Worker if text is not SUPPRESS and text is not None: 253*cda5da8dSAndroid Build Coastguard Worker self._add_item(self._format_text, [text]) 254*cda5da8dSAndroid Build Coastguard Worker 255*cda5da8dSAndroid Build Coastguard Worker def add_usage(self, usage, actions, groups, prefix=None): 256*cda5da8dSAndroid Build Coastguard Worker if usage is not SUPPRESS: 257*cda5da8dSAndroid Build Coastguard Worker args = usage, actions, groups, prefix 258*cda5da8dSAndroid Build Coastguard Worker self._add_item(self._format_usage, args) 259*cda5da8dSAndroid Build Coastguard Worker 260*cda5da8dSAndroid Build Coastguard Worker def add_argument(self, action): 261*cda5da8dSAndroid Build Coastguard Worker if action.help is not SUPPRESS: 262*cda5da8dSAndroid Build Coastguard Worker 263*cda5da8dSAndroid Build Coastguard Worker # find all invocations 264*cda5da8dSAndroid Build Coastguard Worker get_invocation = self._format_action_invocation 265*cda5da8dSAndroid Build Coastguard Worker invocations = [get_invocation(action)] 266*cda5da8dSAndroid Build Coastguard Worker for subaction in self._iter_indented_subactions(action): 267*cda5da8dSAndroid Build Coastguard Worker invocations.append(get_invocation(subaction)) 268*cda5da8dSAndroid Build Coastguard Worker 269*cda5da8dSAndroid Build Coastguard Worker # update the maximum item length 270*cda5da8dSAndroid Build Coastguard Worker invocation_length = max(map(len, invocations)) 271*cda5da8dSAndroid Build Coastguard Worker action_length = invocation_length + self._current_indent 272*cda5da8dSAndroid Build Coastguard Worker self._action_max_length = max(self._action_max_length, 273*cda5da8dSAndroid Build Coastguard Worker action_length) 274*cda5da8dSAndroid Build Coastguard Worker 275*cda5da8dSAndroid Build Coastguard Worker # add the item to the list 276*cda5da8dSAndroid Build Coastguard Worker self._add_item(self._format_action, [action]) 277*cda5da8dSAndroid Build Coastguard Worker 278*cda5da8dSAndroid Build Coastguard Worker def add_arguments(self, actions): 279*cda5da8dSAndroid Build Coastguard Worker for action in actions: 280*cda5da8dSAndroid Build Coastguard Worker self.add_argument(action) 281*cda5da8dSAndroid Build Coastguard Worker 282*cda5da8dSAndroid Build Coastguard Worker # ======================= 283*cda5da8dSAndroid Build Coastguard Worker # Help-formatting methods 284*cda5da8dSAndroid Build Coastguard Worker # ======================= 285*cda5da8dSAndroid Build Coastguard Worker def format_help(self): 286*cda5da8dSAndroid Build Coastguard Worker help = self._root_section.format_help() 287*cda5da8dSAndroid Build Coastguard Worker if help: 288*cda5da8dSAndroid Build Coastguard Worker help = self._long_break_matcher.sub('\n\n', help) 289*cda5da8dSAndroid Build Coastguard Worker help = help.strip('\n') + '\n' 290*cda5da8dSAndroid Build Coastguard Worker return help 291*cda5da8dSAndroid Build Coastguard Worker 292*cda5da8dSAndroid Build Coastguard Worker def _join_parts(self, part_strings): 293*cda5da8dSAndroid Build Coastguard Worker return ''.join([part 294*cda5da8dSAndroid Build Coastguard Worker for part in part_strings 295*cda5da8dSAndroid Build Coastguard Worker if part and part is not SUPPRESS]) 296*cda5da8dSAndroid Build Coastguard Worker 297*cda5da8dSAndroid Build Coastguard Worker def _format_usage(self, usage, actions, groups, prefix): 298*cda5da8dSAndroid Build Coastguard Worker if prefix is None: 299*cda5da8dSAndroid Build Coastguard Worker prefix = _('usage: ') 300*cda5da8dSAndroid Build Coastguard Worker 301*cda5da8dSAndroid Build Coastguard Worker # if usage is specified, use that 302*cda5da8dSAndroid Build Coastguard Worker if usage is not None: 303*cda5da8dSAndroid Build Coastguard Worker usage = usage % dict(prog=self._prog) 304*cda5da8dSAndroid Build Coastguard Worker 305*cda5da8dSAndroid Build Coastguard Worker # if no optionals or positionals are available, usage is just prog 306*cda5da8dSAndroid Build Coastguard Worker elif usage is None and not actions: 307*cda5da8dSAndroid Build Coastguard Worker usage = '%(prog)s' % dict(prog=self._prog) 308*cda5da8dSAndroid Build Coastguard Worker 309*cda5da8dSAndroid Build Coastguard Worker # if optionals and positionals are available, calculate usage 310*cda5da8dSAndroid Build Coastguard Worker elif usage is None: 311*cda5da8dSAndroid Build Coastguard Worker prog = '%(prog)s' % dict(prog=self._prog) 312*cda5da8dSAndroid Build Coastguard Worker 313*cda5da8dSAndroid Build Coastguard Worker # split optionals from positionals 314*cda5da8dSAndroid Build Coastguard Worker optionals = [] 315*cda5da8dSAndroid Build Coastguard Worker positionals = [] 316*cda5da8dSAndroid Build Coastguard Worker for action in actions: 317*cda5da8dSAndroid Build Coastguard Worker if action.option_strings: 318*cda5da8dSAndroid Build Coastguard Worker optionals.append(action) 319*cda5da8dSAndroid Build Coastguard Worker else: 320*cda5da8dSAndroid Build Coastguard Worker positionals.append(action) 321*cda5da8dSAndroid Build Coastguard Worker 322*cda5da8dSAndroid Build Coastguard Worker # build full usage string 323*cda5da8dSAndroid Build Coastguard Worker format = self._format_actions_usage 324*cda5da8dSAndroid Build Coastguard Worker action_usage = format(optionals + positionals, groups) 325*cda5da8dSAndroid Build Coastguard Worker usage = ' '.join([s for s in [prog, action_usage] if s]) 326*cda5da8dSAndroid Build Coastguard Worker 327*cda5da8dSAndroid Build Coastguard Worker # wrap the usage parts if it's too long 328*cda5da8dSAndroid Build Coastguard Worker text_width = self._width - self._current_indent 329*cda5da8dSAndroid Build Coastguard Worker if len(prefix) + len(usage) > text_width: 330*cda5da8dSAndroid Build Coastguard Worker 331*cda5da8dSAndroid Build Coastguard Worker # break usage into wrappable parts 332*cda5da8dSAndroid Build Coastguard Worker part_regexp = ( 333*cda5da8dSAndroid Build Coastguard Worker r'\(.*?\)+(?=\s|$)|' 334*cda5da8dSAndroid Build Coastguard Worker r'\[.*?\]+(?=\s|$)|' 335*cda5da8dSAndroid Build Coastguard Worker r'\S+' 336*cda5da8dSAndroid Build Coastguard Worker ) 337*cda5da8dSAndroid Build Coastguard Worker opt_usage = format(optionals, groups) 338*cda5da8dSAndroid Build Coastguard Worker pos_usage = format(positionals, groups) 339*cda5da8dSAndroid Build Coastguard Worker opt_parts = _re.findall(part_regexp, opt_usage) 340*cda5da8dSAndroid Build Coastguard Worker pos_parts = _re.findall(part_regexp, pos_usage) 341*cda5da8dSAndroid Build Coastguard Worker assert ' '.join(opt_parts) == opt_usage 342*cda5da8dSAndroid Build Coastguard Worker assert ' '.join(pos_parts) == pos_usage 343*cda5da8dSAndroid Build Coastguard Worker 344*cda5da8dSAndroid Build Coastguard Worker # helper for wrapping lines 345*cda5da8dSAndroid Build Coastguard Worker def get_lines(parts, indent, prefix=None): 346*cda5da8dSAndroid Build Coastguard Worker lines = [] 347*cda5da8dSAndroid Build Coastguard Worker line = [] 348*cda5da8dSAndroid Build Coastguard Worker if prefix is not None: 349*cda5da8dSAndroid Build Coastguard Worker line_len = len(prefix) - 1 350*cda5da8dSAndroid Build Coastguard Worker else: 351*cda5da8dSAndroid Build Coastguard Worker line_len = len(indent) - 1 352*cda5da8dSAndroid Build Coastguard Worker for part in parts: 353*cda5da8dSAndroid Build Coastguard Worker if line_len + 1 + len(part) > text_width and line: 354*cda5da8dSAndroid Build Coastguard Worker lines.append(indent + ' '.join(line)) 355*cda5da8dSAndroid Build Coastguard Worker line = [] 356*cda5da8dSAndroid Build Coastguard Worker line_len = len(indent) - 1 357*cda5da8dSAndroid Build Coastguard Worker line.append(part) 358*cda5da8dSAndroid Build Coastguard Worker line_len += len(part) + 1 359*cda5da8dSAndroid Build Coastguard Worker if line: 360*cda5da8dSAndroid Build Coastguard Worker lines.append(indent + ' '.join(line)) 361*cda5da8dSAndroid Build Coastguard Worker if prefix is not None: 362*cda5da8dSAndroid Build Coastguard Worker lines[0] = lines[0][len(indent):] 363*cda5da8dSAndroid Build Coastguard Worker return lines 364*cda5da8dSAndroid Build Coastguard Worker 365*cda5da8dSAndroid Build Coastguard Worker # if prog is short, follow it with optionals or positionals 366*cda5da8dSAndroid Build Coastguard Worker if len(prefix) + len(prog) <= 0.75 * text_width: 367*cda5da8dSAndroid Build Coastguard Worker indent = ' ' * (len(prefix) + len(prog) + 1) 368*cda5da8dSAndroid Build Coastguard Worker if opt_parts: 369*cda5da8dSAndroid Build Coastguard Worker lines = get_lines([prog] + opt_parts, indent, prefix) 370*cda5da8dSAndroid Build Coastguard Worker lines.extend(get_lines(pos_parts, indent)) 371*cda5da8dSAndroid Build Coastguard Worker elif pos_parts: 372*cda5da8dSAndroid Build Coastguard Worker lines = get_lines([prog] + pos_parts, indent, prefix) 373*cda5da8dSAndroid Build Coastguard Worker else: 374*cda5da8dSAndroid Build Coastguard Worker lines = [prog] 375*cda5da8dSAndroid Build Coastguard Worker 376*cda5da8dSAndroid Build Coastguard Worker # if prog is long, put it on its own line 377*cda5da8dSAndroid Build Coastguard Worker else: 378*cda5da8dSAndroid Build Coastguard Worker indent = ' ' * len(prefix) 379*cda5da8dSAndroid Build Coastguard Worker parts = opt_parts + pos_parts 380*cda5da8dSAndroid Build Coastguard Worker lines = get_lines(parts, indent) 381*cda5da8dSAndroid Build Coastguard Worker if len(lines) > 1: 382*cda5da8dSAndroid Build Coastguard Worker lines = [] 383*cda5da8dSAndroid Build Coastguard Worker lines.extend(get_lines(opt_parts, indent)) 384*cda5da8dSAndroid Build Coastguard Worker lines.extend(get_lines(pos_parts, indent)) 385*cda5da8dSAndroid Build Coastguard Worker lines = [prog] + lines 386*cda5da8dSAndroid Build Coastguard Worker 387*cda5da8dSAndroid Build Coastguard Worker # join lines into usage 388*cda5da8dSAndroid Build Coastguard Worker usage = '\n'.join(lines) 389*cda5da8dSAndroid Build Coastguard Worker 390*cda5da8dSAndroid Build Coastguard Worker # prefix with 'usage:' 391*cda5da8dSAndroid Build Coastguard Worker return '%s%s\n\n' % (prefix, usage) 392*cda5da8dSAndroid Build Coastguard Worker 393*cda5da8dSAndroid Build Coastguard Worker def _format_actions_usage(self, actions, groups): 394*cda5da8dSAndroid Build Coastguard Worker # find group indices and identify actions in groups 395*cda5da8dSAndroid Build Coastguard Worker group_actions = set() 396*cda5da8dSAndroid Build Coastguard Worker inserts = {} 397*cda5da8dSAndroid Build Coastguard Worker for group in groups: 398*cda5da8dSAndroid Build Coastguard Worker if not group._group_actions: 399*cda5da8dSAndroid Build Coastguard Worker raise ValueError(f'empty group {group}') 400*cda5da8dSAndroid Build Coastguard Worker 401*cda5da8dSAndroid Build Coastguard Worker try: 402*cda5da8dSAndroid Build Coastguard Worker start = actions.index(group._group_actions[0]) 403*cda5da8dSAndroid Build Coastguard Worker except ValueError: 404*cda5da8dSAndroid Build Coastguard Worker continue 405*cda5da8dSAndroid Build Coastguard Worker else: 406*cda5da8dSAndroid Build Coastguard Worker group_action_count = len(group._group_actions) 407*cda5da8dSAndroid Build Coastguard Worker end = start + group_action_count 408*cda5da8dSAndroid Build Coastguard Worker if actions[start:end] == group._group_actions: 409*cda5da8dSAndroid Build Coastguard Worker 410*cda5da8dSAndroid Build Coastguard Worker suppressed_actions_count = 0 411*cda5da8dSAndroid Build Coastguard Worker for action in group._group_actions: 412*cda5da8dSAndroid Build Coastguard Worker group_actions.add(action) 413*cda5da8dSAndroid Build Coastguard Worker if action.help is SUPPRESS: 414*cda5da8dSAndroid Build Coastguard Worker suppressed_actions_count += 1 415*cda5da8dSAndroid Build Coastguard Worker 416*cda5da8dSAndroid Build Coastguard Worker exposed_actions_count = group_action_count - suppressed_actions_count 417*cda5da8dSAndroid Build Coastguard Worker 418*cda5da8dSAndroid Build Coastguard Worker if not group.required: 419*cda5da8dSAndroid Build Coastguard Worker if start in inserts: 420*cda5da8dSAndroid Build Coastguard Worker inserts[start] += ' [' 421*cda5da8dSAndroid Build Coastguard Worker else: 422*cda5da8dSAndroid Build Coastguard Worker inserts[start] = '[' 423*cda5da8dSAndroid Build Coastguard Worker if end in inserts: 424*cda5da8dSAndroid Build Coastguard Worker inserts[end] += ']' 425*cda5da8dSAndroid Build Coastguard Worker else: 426*cda5da8dSAndroid Build Coastguard Worker inserts[end] = ']' 427*cda5da8dSAndroid Build Coastguard Worker elif exposed_actions_count > 1: 428*cda5da8dSAndroid Build Coastguard Worker if start in inserts: 429*cda5da8dSAndroid Build Coastguard Worker inserts[start] += ' (' 430*cda5da8dSAndroid Build Coastguard Worker else: 431*cda5da8dSAndroid Build Coastguard Worker inserts[start] = '(' 432*cda5da8dSAndroid Build Coastguard Worker if end in inserts: 433*cda5da8dSAndroid Build Coastguard Worker inserts[end] += ')' 434*cda5da8dSAndroid Build Coastguard Worker else: 435*cda5da8dSAndroid Build Coastguard Worker inserts[end] = ')' 436*cda5da8dSAndroid Build Coastguard Worker for i in range(start + 1, end): 437*cda5da8dSAndroid Build Coastguard Worker inserts[i] = '|' 438*cda5da8dSAndroid Build Coastguard Worker 439*cda5da8dSAndroid Build Coastguard Worker # collect all actions format strings 440*cda5da8dSAndroid Build Coastguard Worker parts = [] 441*cda5da8dSAndroid Build Coastguard Worker for i, action in enumerate(actions): 442*cda5da8dSAndroid Build Coastguard Worker 443*cda5da8dSAndroid Build Coastguard Worker # suppressed arguments are marked with None 444*cda5da8dSAndroid Build Coastguard Worker # remove | separators for suppressed arguments 445*cda5da8dSAndroid Build Coastguard Worker if action.help is SUPPRESS: 446*cda5da8dSAndroid Build Coastguard Worker parts.append(None) 447*cda5da8dSAndroid Build Coastguard Worker if inserts.get(i) == '|': 448*cda5da8dSAndroid Build Coastguard Worker inserts.pop(i) 449*cda5da8dSAndroid Build Coastguard Worker elif inserts.get(i + 1) == '|': 450*cda5da8dSAndroid Build Coastguard Worker inserts.pop(i + 1) 451*cda5da8dSAndroid Build Coastguard Worker 452*cda5da8dSAndroid Build Coastguard Worker # produce all arg strings 453*cda5da8dSAndroid Build Coastguard Worker elif not action.option_strings: 454*cda5da8dSAndroid Build Coastguard Worker default = self._get_default_metavar_for_positional(action) 455*cda5da8dSAndroid Build Coastguard Worker part = self._format_args(action, default) 456*cda5da8dSAndroid Build Coastguard Worker 457*cda5da8dSAndroid Build Coastguard Worker # if it's in a group, strip the outer [] 458*cda5da8dSAndroid Build Coastguard Worker if action in group_actions: 459*cda5da8dSAndroid Build Coastguard Worker if part[0] == '[' and part[-1] == ']': 460*cda5da8dSAndroid Build Coastguard Worker part = part[1:-1] 461*cda5da8dSAndroid Build Coastguard Worker 462*cda5da8dSAndroid Build Coastguard Worker # add the action string to the list 463*cda5da8dSAndroid Build Coastguard Worker parts.append(part) 464*cda5da8dSAndroid Build Coastguard Worker 465*cda5da8dSAndroid Build Coastguard Worker # produce the first way to invoke the option in brackets 466*cda5da8dSAndroid Build Coastguard Worker else: 467*cda5da8dSAndroid Build Coastguard Worker option_string = action.option_strings[0] 468*cda5da8dSAndroid Build Coastguard Worker 469*cda5da8dSAndroid Build Coastguard Worker # if the Optional doesn't take a value, format is: 470*cda5da8dSAndroid Build Coastguard Worker # -s or --long 471*cda5da8dSAndroid Build Coastguard Worker if action.nargs == 0: 472*cda5da8dSAndroid Build Coastguard Worker part = action.format_usage() 473*cda5da8dSAndroid Build Coastguard Worker 474*cda5da8dSAndroid Build Coastguard Worker # if the Optional takes a value, format is: 475*cda5da8dSAndroid Build Coastguard Worker # -s ARGS or --long ARGS 476*cda5da8dSAndroid Build Coastguard Worker else: 477*cda5da8dSAndroid Build Coastguard Worker default = self._get_default_metavar_for_optional(action) 478*cda5da8dSAndroid Build Coastguard Worker args_string = self._format_args(action, default) 479*cda5da8dSAndroid Build Coastguard Worker part = '%s %s' % (option_string, args_string) 480*cda5da8dSAndroid Build Coastguard Worker 481*cda5da8dSAndroid Build Coastguard Worker # make it look optional if it's not required or in a group 482*cda5da8dSAndroid Build Coastguard Worker if not action.required and action not in group_actions: 483*cda5da8dSAndroid Build Coastguard Worker part = '[%s]' % part 484*cda5da8dSAndroid Build Coastguard Worker 485*cda5da8dSAndroid Build Coastguard Worker # add the action string to the list 486*cda5da8dSAndroid Build Coastguard Worker parts.append(part) 487*cda5da8dSAndroid Build Coastguard Worker 488*cda5da8dSAndroid Build Coastguard Worker # insert things at the necessary indices 489*cda5da8dSAndroid Build Coastguard Worker for i in sorted(inserts, reverse=True): 490*cda5da8dSAndroid Build Coastguard Worker parts[i:i] = [inserts[i]] 491*cda5da8dSAndroid Build Coastguard Worker 492*cda5da8dSAndroid Build Coastguard Worker # join all the action items with spaces 493*cda5da8dSAndroid Build Coastguard Worker text = ' '.join([item for item in parts if item is not None]) 494*cda5da8dSAndroid Build Coastguard Worker 495*cda5da8dSAndroid Build Coastguard Worker # clean up separators for mutually exclusive groups 496*cda5da8dSAndroid Build Coastguard Worker open = r'[\[(]' 497*cda5da8dSAndroid Build Coastguard Worker close = r'[\])]' 498*cda5da8dSAndroid Build Coastguard Worker text = _re.sub(r'(%s) ' % open, r'\1', text) 499*cda5da8dSAndroid Build Coastguard Worker text = _re.sub(r' (%s)' % close, r'\1', text) 500*cda5da8dSAndroid Build Coastguard Worker text = _re.sub(r'%s *%s' % (open, close), r'', text) 501*cda5da8dSAndroid Build Coastguard Worker text = text.strip() 502*cda5da8dSAndroid Build Coastguard Worker 503*cda5da8dSAndroid Build Coastguard Worker # return the text 504*cda5da8dSAndroid Build Coastguard Worker return text 505*cda5da8dSAndroid Build Coastguard Worker 506*cda5da8dSAndroid Build Coastguard Worker def _format_text(self, text): 507*cda5da8dSAndroid Build Coastguard Worker if '%(prog)' in text: 508*cda5da8dSAndroid Build Coastguard Worker text = text % dict(prog=self._prog) 509*cda5da8dSAndroid Build Coastguard Worker text_width = max(self._width - self._current_indent, 11) 510*cda5da8dSAndroid Build Coastguard Worker indent = ' ' * self._current_indent 511*cda5da8dSAndroid Build Coastguard Worker return self._fill_text(text, text_width, indent) + '\n\n' 512*cda5da8dSAndroid Build Coastguard Worker 513*cda5da8dSAndroid Build Coastguard Worker def _format_action(self, action): 514*cda5da8dSAndroid Build Coastguard Worker # determine the required width and the entry label 515*cda5da8dSAndroid Build Coastguard Worker help_position = min(self._action_max_length + 2, 516*cda5da8dSAndroid Build Coastguard Worker self._max_help_position) 517*cda5da8dSAndroid Build Coastguard Worker help_width = max(self._width - help_position, 11) 518*cda5da8dSAndroid Build Coastguard Worker action_width = help_position - self._current_indent - 2 519*cda5da8dSAndroid Build Coastguard Worker action_header = self._format_action_invocation(action) 520*cda5da8dSAndroid Build Coastguard Worker 521*cda5da8dSAndroid Build Coastguard Worker # no help; start on same line and add a final newline 522*cda5da8dSAndroid Build Coastguard Worker if not action.help: 523*cda5da8dSAndroid Build Coastguard Worker tup = self._current_indent, '', action_header 524*cda5da8dSAndroid Build Coastguard Worker action_header = '%*s%s\n' % tup 525*cda5da8dSAndroid Build Coastguard Worker 526*cda5da8dSAndroid Build Coastguard Worker # short action name; start on the same line and pad two spaces 527*cda5da8dSAndroid Build Coastguard Worker elif len(action_header) <= action_width: 528*cda5da8dSAndroid Build Coastguard Worker tup = self._current_indent, '', action_width, action_header 529*cda5da8dSAndroid Build Coastguard Worker action_header = '%*s%-*s ' % tup 530*cda5da8dSAndroid Build Coastguard Worker indent_first = 0 531*cda5da8dSAndroid Build Coastguard Worker 532*cda5da8dSAndroid Build Coastguard Worker # long action name; start on the next line 533*cda5da8dSAndroid Build Coastguard Worker else: 534*cda5da8dSAndroid Build Coastguard Worker tup = self._current_indent, '', action_header 535*cda5da8dSAndroid Build Coastguard Worker action_header = '%*s%s\n' % tup 536*cda5da8dSAndroid Build Coastguard Worker indent_first = help_position 537*cda5da8dSAndroid Build Coastguard Worker 538*cda5da8dSAndroid Build Coastguard Worker # collect the pieces of the action help 539*cda5da8dSAndroid Build Coastguard Worker parts = [action_header] 540*cda5da8dSAndroid Build Coastguard Worker 541*cda5da8dSAndroid Build Coastguard Worker # if there was help for the action, add lines of help text 542*cda5da8dSAndroid Build Coastguard Worker if action.help and action.help.strip(): 543*cda5da8dSAndroid Build Coastguard Worker help_text = self._expand_help(action) 544*cda5da8dSAndroid Build Coastguard Worker if help_text: 545*cda5da8dSAndroid Build Coastguard Worker help_lines = self._split_lines(help_text, help_width) 546*cda5da8dSAndroid Build Coastguard Worker parts.append('%*s%s\n' % (indent_first, '', help_lines[0])) 547*cda5da8dSAndroid Build Coastguard Worker for line in help_lines[1:]: 548*cda5da8dSAndroid Build Coastguard Worker parts.append('%*s%s\n' % (help_position, '', line)) 549*cda5da8dSAndroid Build Coastguard Worker 550*cda5da8dSAndroid Build Coastguard Worker # or add a newline if the description doesn't end with one 551*cda5da8dSAndroid Build Coastguard Worker elif not action_header.endswith('\n'): 552*cda5da8dSAndroid Build Coastguard Worker parts.append('\n') 553*cda5da8dSAndroid Build Coastguard Worker 554*cda5da8dSAndroid Build Coastguard Worker # if there are any sub-actions, add their help as well 555*cda5da8dSAndroid Build Coastguard Worker for subaction in self._iter_indented_subactions(action): 556*cda5da8dSAndroid Build Coastguard Worker parts.append(self._format_action(subaction)) 557*cda5da8dSAndroid Build Coastguard Worker 558*cda5da8dSAndroid Build Coastguard Worker # return a single string 559*cda5da8dSAndroid Build Coastguard Worker return self._join_parts(parts) 560*cda5da8dSAndroid Build Coastguard Worker 561*cda5da8dSAndroid Build Coastguard Worker def _format_action_invocation(self, action): 562*cda5da8dSAndroid Build Coastguard Worker if not action.option_strings: 563*cda5da8dSAndroid Build Coastguard Worker default = self._get_default_metavar_for_positional(action) 564*cda5da8dSAndroid Build Coastguard Worker metavar, = self._metavar_formatter(action, default)(1) 565*cda5da8dSAndroid Build Coastguard Worker return metavar 566*cda5da8dSAndroid Build Coastguard Worker 567*cda5da8dSAndroid Build Coastguard Worker else: 568*cda5da8dSAndroid Build Coastguard Worker parts = [] 569*cda5da8dSAndroid Build Coastguard Worker 570*cda5da8dSAndroid Build Coastguard Worker # if the Optional doesn't take a value, format is: 571*cda5da8dSAndroid Build Coastguard Worker # -s, --long 572*cda5da8dSAndroid Build Coastguard Worker if action.nargs == 0: 573*cda5da8dSAndroid Build Coastguard Worker parts.extend(action.option_strings) 574*cda5da8dSAndroid Build Coastguard Worker 575*cda5da8dSAndroid Build Coastguard Worker # if the Optional takes a value, format is: 576*cda5da8dSAndroid Build Coastguard Worker # -s ARGS, --long ARGS 577*cda5da8dSAndroid Build Coastguard Worker else: 578*cda5da8dSAndroid Build Coastguard Worker default = self._get_default_metavar_for_optional(action) 579*cda5da8dSAndroid Build Coastguard Worker args_string = self._format_args(action, default) 580*cda5da8dSAndroid Build Coastguard Worker for option_string in action.option_strings: 581*cda5da8dSAndroid Build Coastguard Worker parts.append('%s %s' % (option_string, args_string)) 582*cda5da8dSAndroid Build Coastguard Worker 583*cda5da8dSAndroid Build Coastguard Worker return ', '.join(parts) 584*cda5da8dSAndroid Build Coastguard Worker 585*cda5da8dSAndroid Build Coastguard Worker def _metavar_formatter(self, action, default_metavar): 586*cda5da8dSAndroid Build Coastguard Worker if action.metavar is not None: 587*cda5da8dSAndroid Build Coastguard Worker result = action.metavar 588*cda5da8dSAndroid Build Coastguard Worker elif action.choices is not None: 589*cda5da8dSAndroid Build Coastguard Worker choice_strs = [str(choice) for choice in action.choices] 590*cda5da8dSAndroid Build Coastguard Worker result = '{%s}' % ','.join(choice_strs) 591*cda5da8dSAndroid Build Coastguard Worker else: 592*cda5da8dSAndroid Build Coastguard Worker result = default_metavar 593*cda5da8dSAndroid Build Coastguard Worker 594*cda5da8dSAndroid Build Coastguard Worker def format(tuple_size): 595*cda5da8dSAndroid Build Coastguard Worker if isinstance(result, tuple): 596*cda5da8dSAndroid Build Coastguard Worker return result 597*cda5da8dSAndroid Build Coastguard Worker else: 598*cda5da8dSAndroid Build Coastguard Worker return (result, ) * tuple_size 599*cda5da8dSAndroid Build Coastguard Worker return format 600*cda5da8dSAndroid Build Coastguard Worker 601*cda5da8dSAndroid Build Coastguard Worker def _format_args(self, action, default_metavar): 602*cda5da8dSAndroid Build Coastguard Worker get_metavar = self._metavar_formatter(action, default_metavar) 603*cda5da8dSAndroid Build Coastguard Worker if action.nargs is None: 604*cda5da8dSAndroid Build Coastguard Worker result = '%s' % get_metavar(1) 605*cda5da8dSAndroid Build Coastguard Worker elif action.nargs == OPTIONAL: 606*cda5da8dSAndroid Build Coastguard Worker result = '[%s]' % get_metavar(1) 607*cda5da8dSAndroid Build Coastguard Worker elif action.nargs == ZERO_OR_MORE: 608*cda5da8dSAndroid Build Coastguard Worker metavar = get_metavar(1) 609*cda5da8dSAndroid Build Coastguard Worker if len(metavar) == 2: 610*cda5da8dSAndroid Build Coastguard Worker result = '[%s [%s ...]]' % metavar 611*cda5da8dSAndroid Build Coastguard Worker else: 612*cda5da8dSAndroid Build Coastguard Worker result = '[%s ...]' % metavar 613*cda5da8dSAndroid Build Coastguard Worker elif action.nargs == ONE_OR_MORE: 614*cda5da8dSAndroid Build Coastguard Worker result = '%s [%s ...]' % get_metavar(2) 615*cda5da8dSAndroid Build Coastguard Worker elif action.nargs == REMAINDER: 616*cda5da8dSAndroid Build Coastguard Worker result = '...' 617*cda5da8dSAndroid Build Coastguard Worker elif action.nargs == PARSER: 618*cda5da8dSAndroid Build Coastguard Worker result = '%s ...' % get_metavar(1) 619*cda5da8dSAndroid Build Coastguard Worker elif action.nargs == SUPPRESS: 620*cda5da8dSAndroid Build Coastguard Worker result = '' 621*cda5da8dSAndroid Build Coastguard Worker else: 622*cda5da8dSAndroid Build Coastguard Worker try: 623*cda5da8dSAndroid Build Coastguard Worker formats = ['%s' for _ in range(action.nargs)] 624*cda5da8dSAndroid Build Coastguard Worker except TypeError: 625*cda5da8dSAndroid Build Coastguard Worker raise ValueError("invalid nargs value") from None 626*cda5da8dSAndroid Build Coastguard Worker result = ' '.join(formats) % get_metavar(action.nargs) 627*cda5da8dSAndroid Build Coastguard Worker return result 628*cda5da8dSAndroid Build Coastguard Worker 629*cda5da8dSAndroid Build Coastguard Worker def _expand_help(self, action): 630*cda5da8dSAndroid Build Coastguard Worker params = dict(vars(action), prog=self._prog) 631*cda5da8dSAndroid Build Coastguard Worker for name in list(params): 632*cda5da8dSAndroid Build Coastguard Worker if params[name] is SUPPRESS: 633*cda5da8dSAndroid Build Coastguard Worker del params[name] 634*cda5da8dSAndroid Build Coastguard Worker for name in list(params): 635*cda5da8dSAndroid Build Coastguard Worker if hasattr(params[name], '__name__'): 636*cda5da8dSAndroid Build Coastguard Worker params[name] = params[name].__name__ 637*cda5da8dSAndroid Build Coastguard Worker if params.get('choices') is not None: 638*cda5da8dSAndroid Build Coastguard Worker choices_str = ', '.join([str(c) for c in params['choices']]) 639*cda5da8dSAndroid Build Coastguard Worker params['choices'] = choices_str 640*cda5da8dSAndroid Build Coastguard Worker return self._get_help_string(action) % params 641*cda5da8dSAndroid Build Coastguard Worker 642*cda5da8dSAndroid Build Coastguard Worker def _iter_indented_subactions(self, action): 643*cda5da8dSAndroid Build Coastguard Worker try: 644*cda5da8dSAndroid Build Coastguard Worker get_subactions = action._get_subactions 645*cda5da8dSAndroid Build Coastguard Worker except AttributeError: 646*cda5da8dSAndroid Build Coastguard Worker pass 647*cda5da8dSAndroid Build Coastguard Worker else: 648*cda5da8dSAndroid Build Coastguard Worker self._indent() 649*cda5da8dSAndroid Build Coastguard Worker yield from get_subactions() 650*cda5da8dSAndroid Build Coastguard Worker self._dedent() 651*cda5da8dSAndroid Build Coastguard Worker 652*cda5da8dSAndroid Build Coastguard Worker def _split_lines(self, text, width): 653*cda5da8dSAndroid Build Coastguard Worker text = self._whitespace_matcher.sub(' ', text).strip() 654*cda5da8dSAndroid Build Coastguard Worker # The textwrap module is used only for formatting help. 655*cda5da8dSAndroid Build Coastguard Worker # Delay its import for speeding up the common usage of argparse. 656*cda5da8dSAndroid Build Coastguard Worker import textwrap 657*cda5da8dSAndroid Build Coastguard Worker return textwrap.wrap(text, width) 658*cda5da8dSAndroid Build Coastguard Worker 659*cda5da8dSAndroid Build Coastguard Worker def _fill_text(self, text, width, indent): 660*cda5da8dSAndroid Build Coastguard Worker text = self._whitespace_matcher.sub(' ', text).strip() 661*cda5da8dSAndroid Build Coastguard Worker import textwrap 662*cda5da8dSAndroid Build Coastguard Worker return textwrap.fill(text, width, 663*cda5da8dSAndroid Build Coastguard Worker initial_indent=indent, 664*cda5da8dSAndroid Build Coastguard Worker subsequent_indent=indent) 665*cda5da8dSAndroid Build Coastguard Worker 666*cda5da8dSAndroid Build Coastguard Worker def _get_help_string(self, action): 667*cda5da8dSAndroid Build Coastguard Worker return action.help 668*cda5da8dSAndroid Build Coastguard Worker 669*cda5da8dSAndroid Build Coastguard Worker def _get_default_metavar_for_optional(self, action): 670*cda5da8dSAndroid Build Coastguard Worker return action.dest.upper() 671*cda5da8dSAndroid Build Coastguard Worker 672*cda5da8dSAndroid Build Coastguard Worker def _get_default_metavar_for_positional(self, action): 673*cda5da8dSAndroid Build Coastguard Worker return action.dest 674*cda5da8dSAndroid Build Coastguard Worker 675*cda5da8dSAndroid Build Coastguard Worker 676*cda5da8dSAndroid Build Coastguard Workerclass RawDescriptionHelpFormatter(HelpFormatter): 677*cda5da8dSAndroid Build Coastguard Worker """Help message formatter which retains any formatting in descriptions. 678*cda5da8dSAndroid Build Coastguard Worker 679*cda5da8dSAndroid Build Coastguard Worker Only the name of this class is considered a public API. All the methods 680*cda5da8dSAndroid Build Coastguard Worker provided by the class are considered an implementation detail. 681*cda5da8dSAndroid Build Coastguard Worker """ 682*cda5da8dSAndroid Build Coastguard Worker 683*cda5da8dSAndroid Build Coastguard Worker def _fill_text(self, text, width, indent): 684*cda5da8dSAndroid Build Coastguard Worker return ''.join(indent + line for line in text.splitlines(keepends=True)) 685*cda5da8dSAndroid Build Coastguard Worker 686*cda5da8dSAndroid Build Coastguard Worker 687*cda5da8dSAndroid Build Coastguard Workerclass RawTextHelpFormatter(RawDescriptionHelpFormatter): 688*cda5da8dSAndroid Build Coastguard Worker """Help message formatter which retains formatting of all help text. 689*cda5da8dSAndroid Build Coastguard Worker 690*cda5da8dSAndroid Build Coastguard Worker Only the name of this class is considered a public API. All the methods 691*cda5da8dSAndroid Build Coastguard Worker provided by the class are considered an implementation detail. 692*cda5da8dSAndroid Build Coastguard Worker """ 693*cda5da8dSAndroid Build Coastguard Worker 694*cda5da8dSAndroid Build Coastguard Worker def _split_lines(self, text, width): 695*cda5da8dSAndroid Build Coastguard Worker return text.splitlines() 696*cda5da8dSAndroid Build Coastguard Worker 697*cda5da8dSAndroid Build Coastguard Worker 698*cda5da8dSAndroid Build Coastguard Workerclass ArgumentDefaultsHelpFormatter(HelpFormatter): 699*cda5da8dSAndroid Build Coastguard Worker """Help message formatter which adds default values to argument help. 700*cda5da8dSAndroid Build Coastguard Worker 701*cda5da8dSAndroid Build Coastguard Worker Only the name of this class is considered a public API. All the methods 702*cda5da8dSAndroid Build Coastguard Worker provided by the class are considered an implementation detail. 703*cda5da8dSAndroid Build Coastguard Worker """ 704*cda5da8dSAndroid Build Coastguard Worker 705*cda5da8dSAndroid Build Coastguard Worker def _get_help_string(self, action): 706*cda5da8dSAndroid Build Coastguard Worker """ 707*cda5da8dSAndroid Build Coastguard Worker Add the default value to the option help message. 708*cda5da8dSAndroid Build Coastguard Worker 709*cda5da8dSAndroid Build Coastguard Worker ArgumentDefaultsHelpFormatter and BooleanOptionalAction when it isn't 710*cda5da8dSAndroid Build Coastguard Worker already present. This code will do that, detecting cornercases to 711*cda5da8dSAndroid Build Coastguard Worker prevent duplicates or cases where it wouldn't make sense to the end 712*cda5da8dSAndroid Build Coastguard Worker user. 713*cda5da8dSAndroid Build Coastguard Worker """ 714*cda5da8dSAndroid Build Coastguard Worker help = action.help 715*cda5da8dSAndroid Build Coastguard Worker if help is None: 716*cda5da8dSAndroid Build Coastguard Worker help = '' 717*cda5da8dSAndroid Build Coastguard Worker 718*cda5da8dSAndroid Build Coastguard Worker if '%(default)' not in help: 719*cda5da8dSAndroid Build Coastguard Worker if action.default is not SUPPRESS: 720*cda5da8dSAndroid Build Coastguard Worker defaulting_nargs = [OPTIONAL, ZERO_OR_MORE] 721*cda5da8dSAndroid Build Coastguard Worker if action.option_strings or action.nargs in defaulting_nargs: 722*cda5da8dSAndroid Build Coastguard Worker help += ' (default: %(default)s)' 723*cda5da8dSAndroid Build Coastguard Worker return help 724*cda5da8dSAndroid Build Coastguard Worker 725*cda5da8dSAndroid Build Coastguard Worker 726*cda5da8dSAndroid Build Coastguard Worker 727*cda5da8dSAndroid Build Coastguard Workerclass MetavarTypeHelpFormatter(HelpFormatter): 728*cda5da8dSAndroid Build Coastguard Worker """Help message formatter which uses the argument 'type' as the default 729*cda5da8dSAndroid Build Coastguard Worker metavar value (instead of the argument 'dest') 730*cda5da8dSAndroid Build Coastguard Worker 731*cda5da8dSAndroid Build Coastguard Worker Only the name of this class is considered a public API. All the methods 732*cda5da8dSAndroid Build Coastguard Worker provided by the class are considered an implementation detail. 733*cda5da8dSAndroid Build Coastguard Worker """ 734*cda5da8dSAndroid Build Coastguard Worker 735*cda5da8dSAndroid Build Coastguard Worker def _get_default_metavar_for_optional(self, action): 736*cda5da8dSAndroid Build Coastguard Worker return action.type.__name__ 737*cda5da8dSAndroid Build Coastguard Worker 738*cda5da8dSAndroid Build Coastguard Worker def _get_default_metavar_for_positional(self, action): 739*cda5da8dSAndroid Build Coastguard Worker return action.type.__name__ 740*cda5da8dSAndroid Build Coastguard Worker 741*cda5da8dSAndroid Build Coastguard Worker 742*cda5da8dSAndroid Build Coastguard Worker# ===================== 743*cda5da8dSAndroid Build Coastguard Worker# Options and Arguments 744*cda5da8dSAndroid Build Coastguard Worker# ===================== 745*cda5da8dSAndroid Build Coastguard Worker 746*cda5da8dSAndroid Build Coastguard Workerdef _get_action_name(argument): 747*cda5da8dSAndroid Build Coastguard Worker if argument is None: 748*cda5da8dSAndroid Build Coastguard Worker return None 749*cda5da8dSAndroid Build Coastguard Worker elif argument.option_strings: 750*cda5da8dSAndroid Build Coastguard Worker return '/'.join(argument.option_strings) 751*cda5da8dSAndroid Build Coastguard Worker elif argument.metavar not in (None, SUPPRESS): 752*cda5da8dSAndroid Build Coastguard Worker return argument.metavar 753*cda5da8dSAndroid Build Coastguard Worker elif argument.dest not in (None, SUPPRESS): 754*cda5da8dSAndroid Build Coastguard Worker return argument.dest 755*cda5da8dSAndroid Build Coastguard Worker elif argument.choices: 756*cda5da8dSAndroid Build Coastguard Worker return '{' + ','.join(argument.choices) + '}' 757*cda5da8dSAndroid Build Coastguard Worker else: 758*cda5da8dSAndroid Build Coastguard Worker return None 759*cda5da8dSAndroid Build Coastguard Worker 760*cda5da8dSAndroid Build Coastguard Worker 761*cda5da8dSAndroid Build Coastguard Workerclass ArgumentError(Exception): 762*cda5da8dSAndroid Build Coastguard Worker """An error from creating or using an argument (optional or positional). 763*cda5da8dSAndroid Build Coastguard Worker 764*cda5da8dSAndroid Build Coastguard Worker The string value of this exception is the message, augmented with 765*cda5da8dSAndroid Build Coastguard Worker information about the argument that caused it. 766*cda5da8dSAndroid Build Coastguard Worker """ 767*cda5da8dSAndroid Build Coastguard Worker 768*cda5da8dSAndroid Build Coastguard Worker def __init__(self, argument, message): 769*cda5da8dSAndroid Build Coastguard Worker self.argument_name = _get_action_name(argument) 770*cda5da8dSAndroid Build Coastguard Worker self.message = message 771*cda5da8dSAndroid Build Coastguard Worker 772*cda5da8dSAndroid Build Coastguard Worker def __str__(self): 773*cda5da8dSAndroid Build Coastguard Worker if self.argument_name is None: 774*cda5da8dSAndroid Build Coastguard Worker format = '%(message)s' 775*cda5da8dSAndroid Build Coastguard Worker else: 776*cda5da8dSAndroid Build Coastguard Worker format = _('argument %(argument_name)s: %(message)s') 777*cda5da8dSAndroid Build Coastguard Worker return format % dict(message=self.message, 778*cda5da8dSAndroid Build Coastguard Worker argument_name=self.argument_name) 779*cda5da8dSAndroid Build Coastguard Worker 780*cda5da8dSAndroid Build Coastguard Worker 781*cda5da8dSAndroid Build Coastguard Workerclass ArgumentTypeError(Exception): 782*cda5da8dSAndroid Build Coastguard Worker """An error from trying to convert a command line string to a type.""" 783*cda5da8dSAndroid Build Coastguard Worker pass 784*cda5da8dSAndroid Build Coastguard Worker 785*cda5da8dSAndroid Build Coastguard Worker 786*cda5da8dSAndroid Build Coastguard Worker# ============== 787*cda5da8dSAndroid Build Coastguard Worker# Action classes 788*cda5da8dSAndroid Build Coastguard Worker# ============== 789*cda5da8dSAndroid Build Coastguard Worker 790*cda5da8dSAndroid Build Coastguard Workerclass Action(_AttributeHolder): 791*cda5da8dSAndroid Build Coastguard Worker """Information about how to convert command line strings to Python objects. 792*cda5da8dSAndroid Build Coastguard Worker 793*cda5da8dSAndroid Build Coastguard Worker Action objects are used by an ArgumentParser to represent the information 794*cda5da8dSAndroid Build Coastguard Worker needed to parse a single argument from one or more strings from the 795*cda5da8dSAndroid Build Coastguard Worker command line. The keyword arguments to the Action constructor are also 796*cda5da8dSAndroid Build Coastguard Worker all attributes of Action instances. 797*cda5da8dSAndroid Build Coastguard Worker 798*cda5da8dSAndroid Build Coastguard Worker Keyword Arguments: 799*cda5da8dSAndroid Build Coastguard Worker 800*cda5da8dSAndroid Build Coastguard Worker - option_strings -- A list of command-line option strings which 801*cda5da8dSAndroid Build Coastguard Worker should be associated with this action. 802*cda5da8dSAndroid Build Coastguard Worker 803*cda5da8dSAndroid Build Coastguard Worker - dest -- The name of the attribute to hold the created object(s) 804*cda5da8dSAndroid Build Coastguard Worker 805*cda5da8dSAndroid Build Coastguard Worker - nargs -- The number of command-line arguments that should be 806*cda5da8dSAndroid Build Coastguard Worker consumed. By default, one argument will be consumed and a single 807*cda5da8dSAndroid Build Coastguard Worker value will be produced. Other values include: 808*cda5da8dSAndroid Build Coastguard Worker - N (an integer) consumes N arguments (and produces a list) 809*cda5da8dSAndroid Build Coastguard Worker - '?' consumes zero or one arguments 810*cda5da8dSAndroid Build Coastguard Worker - '*' consumes zero or more arguments (and produces a list) 811*cda5da8dSAndroid Build Coastguard Worker - '+' consumes one or more arguments (and produces a list) 812*cda5da8dSAndroid Build Coastguard Worker Note that the difference between the default and nargs=1 is that 813*cda5da8dSAndroid Build Coastguard Worker with the default, a single value will be produced, while with 814*cda5da8dSAndroid Build Coastguard Worker nargs=1, a list containing a single value will be produced. 815*cda5da8dSAndroid Build Coastguard Worker 816*cda5da8dSAndroid Build Coastguard Worker - const -- The value to be produced if the option is specified and the 817*cda5da8dSAndroid Build Coastguard Worker option uses an action that takes no values. 818*cda5da8dSAndroid Build Coastguard Worker 819*cda5da8dSAndroid Build Coastguard Worker - default -- The value to be produced if the option is not specified. 820*cda5da8dSAndroid Build Coastguard Worker 821*cda5da8dSAndroid Build Coastguard Worker - type -- A callable that accepts a single string argument, and 822*cda5da8dSAndroid Build Coastguard Worker returns the converted value. The standard Python types str, int, 823*cda5da8dSAndroid Build Coastguard Worker float, and complex are useful examples of such callables. If None, 824*cda5da8dSAndroid Build Coastguard Worker str is used. 825*cda5da8dSAndroid Build Coastguard Worker 826*cda5da8dSAndroid Build Coastguard Worker - choices -- A container of values that should be allowed. If not None, 827*cda5da8dSAndroid Build Coastguard Worker after a command-line argument has been converted to the appropriate 828*cda5da8dSAndroid Build Coastguard Worker type, an exception will be raised if it is not a member of this 829*cda5da8dSAndroid Build Coastguard Worker collection. 830*cda5da8dSAndroid Build Coastguard Worker 831*cda5da8dSAndroid Build Coastguard Worker - required -- True if the action must always be specified at the 832*cda5da8dSAndroid Build Coastguard Worker command line. This is only meaningful for optional command-line 833*cda5da8dSAndroid Build Coastguard Worker arguments. 834*cda5da8dSAndroid Build Coastguard Worker 835*cda5da8dSAndroid Build Coastguard Worker - help -- The help string describing the argument. 836*cda5da8dSAndroid Build Coastguard Worker 837*cda5da8dSAndroid Build Coastguard Worker - metavar -- The name to be used for the option's argument with the 838*cda5da8dSAndroid Build Coastguard Worker help string. If None, the 'dest' value will be used as the name. 839*cda5da8dSAndroid Build Coastguard Worker """ 840*cda5da8dSAndroid Build Coastguard Worker 841*cda5da8dSAndroid Build Coastguard Worker def __init__(self, 842*cda5da8dSAndroid Build Coastguard Worker option_strings, 843*cda5da8dSAndroid Build Coastguard Worker dest, 844*cda5da8dSAndroid Build Coastguard Worker nargs=None, 845*cda5da8dSAndroid Build Coastguard Worker const=None, 846*cda5da8dSAndroid Build Coastguard Worker default=None, 847*cda5da8dSAndroid Build Coastguard Worker type=None, 848*cda5da8dSAndroid Build Coastguard Worker choices=None, 849*cda5da8dSAndroid Build Coastguard Worker required=False, 850*cda5da8dSAndroid Build Coastguard Worker help=None, 851*cda5da8dSAndroid Build Coastguard Worker metavar=None): 852*cda5da8dSAndroid Build Coastguard Worker self.option_strings = option_strings 853*cda5da8dSAndroid Build Coastguard Worker self.dest = dest 854*cda5da8dSAndroid Build Coastguard Worker self.nargs = nargs 855*cda5da8dSAndroid Build Coastguard Worker self.const = const 856*cda5da8dSAndroid Build Coastguard Worker self.default = default 857*cda5da8dSAndroid Build Coastguard Worker self.type = type 858*cda5da8dSAndroid Build Coastguard Worker self.choices = choices 859*cda5da8dSAndroid Build Coastguard Worker self.required = required 860*cda5da8dSAndroid Build Coastguard Worker self.help = help 861*cda5da8dSAndroid Build Coastguard Worker self.metavar = metavar 862*cda5da8dSAndroid Build Coastguard Worker 863*cda5da8dSAndroid Build Coastguard Worker def _get_kwargs(self): 864*cda5da8dSAndroid Build Coastguard Worker names = [ 865*cda5da8dSAndroid Build Coastguard Worker 'option_strings', 866*cda5da8dSAndroid Build Coastguard Worker 'dest', 867*cda5da8dSAndroid Build Coastguard Worker 'nargs', 868*cda5da8dSAndroid Build Coastguard Worker 'const', 869*cda5da8dSAndroid Build Coastguard Worker 'default', 870*cda5da8dSAndroid Build Coastguard Worker 'type', 871*cda5da8dSAndroid Build Coastguard Worker 'choices', 872*cda5da8dSAndroid Build Coastguard Worker 'required', 873*cda5da8dSAndroid Build Coastguard Worker 'help', 874*cda5da8dSAndroid Build Coastguard Worker 'metavar', 875*cda5da8dSAndroid Build Coastguard Worker ] 876*cda5da8dSAndroid Build Coastguard Worker return [(name, getattr(self, name)) for name in names] 877*cda5da8dSAndroid Build Coastguard Worker 878*cda5da8dSAndroid Build Coastguard Worker def format_usage(self): 879*cda5da8dSAndroid Build Coastguard Worker return self.option_strings[0] 880*cda5da8dSAndroid Build Coastguard Worker 881*cda5da8dSAndroid Build Coastguard Worker def __call__(self, parser, namespace, values, option_string=None): 882*cda5da8dSAndroid Build Coastguard Worker raise NotImplementedError(_('.__call__() not defined')) 883*cda5da8dSAndroid Build Coastguard Worker 884*cda5da8dSAndroid Build Coastguard Worker 885*cda5da8dSAndroid Build Coastguard Workerclass BooleanOptionalAction(Action): 886*cda5da8dSAndroid Build Coastguard Worker def __init__(self, 887*cda5da8dSAndroid Build Coastguard Worker option_strings, 888*cda5da8dSAndroid Build Coastguard Worker dest, 889*cda5da8dSAndroid Build Coastguard Worker default=None, 890*cda5da8dSAndroid Build Coastguard Worker type=None, 891*cda5da8dSAndroid Build Coastguard Worker choices=None, 892*cda5da8dSAndroid Build Coastguard Worker required=False, 893*cda5da8dSAndroid Build Coastguard Worker help=None, 894*cda5da8dSAndroid Build Coastguard Worker metavar=None): 895*cda5da8dSAndroid Build Coastguard Worker 896*cda5da8dSAndroid Build Coastguard Worker _option_strings = [] 897*cda5da8dSAndroid Build Coastguard Worker for option_string in option_strings: 898*cda5da8dSAndroid Build Coastguard Worker _option_strings.append(option_string) 899*cda5da8dSAndroid Build Coastguard Worker 900*cda5da8dSAndroid Build Coastguard Worker if option_string.startswith('--'): 901*cda5da8dSAndroid Build Coastguard Worker option_string = '--no-' + option_string[2:] 902*cda5da8dSAndroid Build Coastguard Worker _option_strings.append(option_string) 903*cda5da8dSAndroid Build Coastguard Worker 904*cda5da8dSAndroid Build Coastguard Worker super().__init__( 905*cda5da8dSAndroid Build Coastguard Worker option_strings=_option_strings, 906*cda5da8dSAndroid Build Coastguard Worker dest=dest, 907*cda5da8dSAndroid Build Coastguard Worker nargs=0, 908*cda5da8dSAndroid Build Coastguard Worker default=default, 909*cda5da8dSAndroid Build Coastguard Worker type=type, 910*cda5da8dSAndroid Build Coastguard Worker choices=choices, 911*cda5da8dSAndroid Build Coastguard Worker required=required, 912*cda5da8dSAndroid Build Coastguard Worker help=help, 913*cda5da8dSAndroid Build Coastguard Worker metavar=metavar) 914*cda5da8dSAndroid Build Coastguard Worker 915*cda5da8dSAndroid Build Coastguard Worker 916*cda5da8dSAndroid Build Coastguard Worker def __call__(self, parser, namespace, values, option_string=None): 917*cda5da8dSAndroid Build Coastguard Worker if option_string in self.option_strings: 918*cda5da8dSAndroid Build Coastguard Worker setattr(namespace, self.dest, not option_string.startswith('--no-')) 919*cda5da8dSAndroid Build Coastguard Worker 920*cda5da8dSAndroid Build Coastguard Worker def format_usage(self): 921*cda5da8dSAndroid Build Coastguard Worker return ' | '.join(self.option_strings) 922*cda5da8dSAndroid Build Coastguard Worker 923*cda5da8dSAndroid Build Coastguard Worker 924*cda5da8dSAndroid Build Coastguard Workerclass _StoreAction(Action): 925*cda5da8dSAndroid Build Coastguard Worker 926*cda5da8dSAndroid Build Coastguard Worker def __init__(self, 927*cda5da8dSAndroid Build Coastguard Worker option_strings, 928*cda5da8dSAndroid Build Coastguard Worker dest, 929*cda5da8dSAndroid Build Coastguard Worker nargs=None, 930*cda5da8dSAndroid Build Coastguard Worker const=None, 931*cda5da8dSAndroid Build Coastguard Worker default=None, 932*cda5da8dSAndroid Build Coastguard Worker type=None, 933*cda5da8dSAndroid Build Coastguard Worker choices=None, 934*cda5da8dSAndroid Build Coastguard Worker required=False, 935*cda5da8dSAndroid Build Coastguard Worker help=None, 936*cda5da8dSAndroid Build Coastguard Worker metavar=None): 937*cda5da8dSAndroid Build Coastguard Worker if nargs == 0: 938*cda5da8dSAndroid Build Coastguard Worker raise ValueError('nargs for store actions must be != 0; if you ' 939*cda5da8dSAndroid Build Coastguard Worker 'have nothing to store, actions such as store ' 940*cda5da8dSAndroid Build Coastguard Worker 'true or store const may be more appropriate') 941*cda5da8dSAndroid Build Coastguard Worker if const is not None and nargs != OPTIONAL: 942*cda5da8dSAndroid Build Coastguard Worker raise ValueError('nargs must be %r to supply const' % OPTIONAL) 943*cda5da8dSAndroid Build Coastguard Worker super(_StoreAction, self).__init__( 944*cda5da8dSAndroid Build Coastguard Worker option_strings=option_strings, 945*cda5da8dSAndroid Build Coastguard Worker dest=dest, 946*cda5da8dSAndroid Build Coastguard Worker nargs=nargs, 947*cda5da8dSAndroid Build Coastguard Worker const=const, 948*cda5da8dSAndroid Build Coastguard Worker default=default, 949*cda5da8dSAndroid Build Coastguard Worker type=type, 950*cda5da8dSAndroid Build Coastguard Worker choices=choices, 951*cda5da8dSAndroid Build Coastguard Worker required=required, 952*cda5da8dSAndroid Build Coastguard Worker help=help, 953*cda5da8dSAndroid Build Coastguard Worker metavar=metavar) 954*cda5da8dSAndroid Build Coastguard Worker 955*cda5da8dSAndroid Build Coastguard Worker def __call__(self, parser, namespace, values, option_string=None): 956*cda5da8dSAndroid Build Coastguard Worker setattr(namespace, self.dest, values) 957*cda5da8dSAndroid Build Coastguard Worker 958*cda5da8dSAndroid Build Coastguard Worker 959*cda5da8dSAndroid Build Coastguard Workerclass _StoreConstAction(Action): 960*cda5da8dSAndroid Build Coastguard Worker 961*cda5da8dSAndroid Build Coastguard Worker def __init__(self, 962*cda5da8dSAndroid Build Coastguard Worker option_strings, 963*cda5da8dSAndroid Build Coastguard Worker dest, 964*cda5da8dSAndroid Build Coastguard Worker const=None, 965*cda5da8dSAndroid Build Coastguard Worker default=None, 966*cda5da8dSAndroid Build Coastguard Worker required=False, 967*cda5da8dSAndroid Build Coastguard Worker help=None, 968*cda5da8dSAndroid Build Coastguard Worker metavar=None): 969*cda5da8dSAndroid Build Coastguard Worker super(_StoreConstAction, self).__init__( 970*cda5da8dSAndroid Build Coastguard Worker option_strings=option_strings, 971*cda5da8dSAndroid Build Coastguard Worker dest=dest, 972*cda5da8dSAndroid Build Coastguard Worker nargs=0, 973*cda5da8dSAndroid Build Coastguard Worker const=const, 974*cda5da8dSAndroid Build Coastguard Worker default=default, 975*cda5da8dSAndroid Build Coastguard Worker required=required, 976*cda5da8dSAndroid Build Coastguard Worker help=help) 977*cda5da8dSAndroid Build Coastguard Worker 978*cda5da8dSAndroid Build Coastguard Worker def __call__(self, parser, namespace, values, option_string=None): 979*cda5da8dSAndroid Build Coastguard Worker setattr(namespace, self.dest, self.const) 980*cda5da8dSAndroid Build Coastguard Worker 981*cda5da8dSAndroid Build Coastguard Worker 982*cda5da8dSAndroid Build Coastguard Workerclass _StoreTrueAction(_StoreConstAction): 983*cda5da8dSAndroid Build Coastguard Worker 984*cda5da8dSAndroid Build Coastguard Worker def __init__(self, 985*cda5da8dSAndroid Build Coastguard Worker option_strings, 986*cda5da8dSAndroid Build Coastguard Worker dest, 987*cda5da8dSAndroid Build Coastguard Worker default=False, 988*cda5da8dSAndroid Build Coastguard Worker required=False, 989*cda5da8dSAndroid Build Coastguard Worker help=None): 990*cda5da8dSAndroid Build Coastguard Worker super(_StoreTrueAction, self).__init__( 991*cda5da8dSAndroid Build Coastguard Worker option_strings=option_strings, 992*cda5da8dSAndroid Build Coastguard Worker dest=dest, 993*cda5da8dSAndroid Build Coastguard Worker const=True, 994*cda5da8dSAndroid Build Coastguard Worker default=default, 995*cda5da8dSAndroid Build Coastguard Worker required=required, 996*cda5da8dSAndroid Build Coastguard Worker help=help) 997*cda5da8dSAndroid Build Coastguard Worker 998*cda5da8dSAndroid Build Coastguard Worker 999*cda5da8dSAndroid Build Coastguard Workerclass _StoreFalseAction(_StoreConstAction): 1000*cda5da8dSAndroid Build Coastguard Worker 1001*cda5da8dSAndroid Build Coastguard Worker def __init__(self, 1002*cda5da8dSAndroid Build Coastguard Worker option_strings, 1003*cda5da8dSAndroid Build Coastguard Worker dest, 1004*cda5da8dSAndroid Build Coastguard Worker default=True, 1005*cda5da8dSAndroid Build Coastguard Worker required=False, 1006*cda5da8dSAndroid Build Coastguard Worker help=None): 1007*cda5da8dSAndroid Build Coastguard Worker super(_StoreFalseAction, self).__init__( 1008*cda5da8dSAndroid Build Coastguard Worker option_strings=option_strings, 1009*cda5da8dSAndroid Build Coastguard Worker dest=dest, 1010*cda5da8dSAndroid Build Coastguard Worker const=False, 1011*cda5da8dSAndroid Build Coastguard Worker default=default, 1012*cda5da8dSAndroid Build Coastguard Worker required=required, 1013*cda5da8dSAndroid Build Coastguard Worker help=help) 1014*cda5da8dSAndroid Build Coastguard Worker 1015*cda5da8dSAndroid Build Coastguard Worker 1016*cda5da8dSAndroid Build Coastguard Workerclass _AppendAction(Action): 1017*cda5da8dSAndroid Build Coastguard Worker 1018*cda5da8dSAndroid Build Coastguard Worker def __init__(self, 1019*cda5da8dSAndroid Build Coastguard Worker option_strings, 1020*cda5da8dSAndroid Build Coastguard Worker dest, 1021*cda5da8dSAndroid Build Coastguard Worker nargs=None, 1022*cda5da8dSAndroid Build Coastguard Worker const=None, 1023*cda5da8dSAndroid Build Coastguard Worker default=None, 1024*cda5da8dSAndroid Build Coastguard Worker type=None, 1025*cda5da8dSAndroid Build Coastguard Worker choices=None, 1026*cda5da8dSAndroid Build Coastguard Worker required=False, 1027*cda5da8dSAndroid Build Coastguard Worker help=None, 1028*cda5da8dSAndroid Build Coastguard Worker metavar=None): 1029*cda5da8dSAndroid Build Coastguard Worker if nargs == 0: 1030*cda5da8dSAndroid Build Coastguard Worker raise ValueError('nargs for append actions must be != 0; if arg ' 1031*cda5da8dSAndroid Build Coastguard Worker 'strings are not supplying the value to append, ' 1032*cda5da8dSAndroid Build Coastguard Worker 'the append const action may be more appropriate') 1033*cda5da8dSAndroid Build Coastguard Worker if const is not None and nargs != OPTIONAL: 1034*cda5da8dSAndroid Build Coastguard Worker raise ValueError('nargs must be %r to supply const' % OPTIONAL) 1035*cda5da8dSAndroid Build Coastguard Worker super(_AppendAction, self).__init__( 1036*cda5da8dSAndroid Build Coastguard Worker option_strings=option_strings, 1037*cda5da8dSAndroid Build Coastguard Worker dest=dest, 1038*cda5da8dSAndroid Build Coastguard Worker nargs=nargs, 1039*cda5da8dSAndroid Build Coastguard Worker const=const, 1040*cda5da8dSAndroid Build Coastguard Worker default=default, 1041*cda5da8dSAndroid Build Coastguard Worker type=type, 1042*cda5da8dSAndroid Build Coastguard Worker choices=choices, 1043*cda5da8dSAndroid Build Coastguard Worker required=required, 1044*cda5da8dSAndroid Build Coastguard Worker help=help, 1045*cda5da8dSAndroid Build Coastguard Worker metavar=metavar) 1046*cda5da8dSAndroid Build Coastguard Worker 1047*cda5da8dSAndroid Build Coastguard Worker def __call__(self, parser, namespace, values, option_string=None): 1048*cda5da8dSAndroid Build Coastguard Worker items = getattr(namespace, self.dest, None) 1049*cda5da8dSAndroid Build Coastguard Worker items = _copy_items(items) 1050*cda5da8dSAndroid Build Coastguard Worker items.append(values) 1051*cda5da8dSAndroid Build Coastguard Worker setattr(namespace, self.dest, items) 1052*cda5da8dSAndroid Build Coastguard Worker 1053*cda5da8dSAndroid Build Coastguard Worker 1054*cda5da8dSAndroid Build Coastguard Workerclass _AppendConstAction(Action): 1055*cda5da8dSAndroid Build Coastguard Worker 1056*cda5da8dSAndroid Build Coastguard Worker def __init__(self, 1057*cda5da8dSAndroid Build Coastguard Worker option_strings, 1058*cda5da8dSAndroid Build Coastguard Worker dest, 1059*cda5da8dSAndroid Build Coastguard Worker const=None, 1060*cda5da8dSAndroid Build Coastguard Worker default=None, 1061*cda5da8dSAndroid Build Coastguard Worker required=False, 1062*cda5da8dSAndroid Build Coastguard Worker help=None, 1063*cda5da8dSAndroid Build Coastguard Worker metavar=None): 1064*cda5da8dSAndroid Build Coastguard Worker super(_AppendConstAction, self).__init__( 1065*cda5da8dSAndroid Build Coastguard Worker option_strings=option_strings, 1066*cda5da8dSAndroid Build Coastguard Worker dest=dest, 1067*cda5da8dSAndroid Build Coastguard Worker nargs=0, 1068*cda5da8dSAndroid Build Coastguard Worker const=const, 1069*cda5da8dSAndroid Build Coastguard Worker default=default, 1070*cda5da8dSAndroid Build Coastguard Worker required=required, 1071*cda5da8dSAndroid Build Coastguard Worker help=help, 1072*cda5da8dSAndroid Build Coastguard Worker metavar=metavar) 1073*cda5da8dSAndroid Build Coastguard Worker 1074*cda5da8dSAndroid Build Coastguard Worker def __call__(self, parser, namespace, values, option_string=None): 1075*cda5da8dSAndroid Build Coastguard Worker items = getattr(namespace, self.dest, None) 1076*cda5da8dSAndroid Build Coastguard Worker items = _copy_items(items) 1077*cda5da8dSAndroid Build Coastguard Worker items.append(self.const) 1078*cda5da8dSAndroid Build Coastguard Worker setattr(namespace, self.dest, items) 1079*cda5da8dSAndroid Build Coastguard Worker 1080*cda5da8dSAndroid Build Coastguard Worker 1081*cda5da8dSAndroid Build Coastguard Workerclass _CountAction(Action): 1082*cda5da8dSAndroid Build Coastguard Worker 1083*cda5da8dSAndroid Build Coastguard Worker def __init__(self, 1084*cda5da8dSAndroid Build Coastguard Worker option_strings, 1085*cda5da8dSAndroid Build Coastguard Worker dest, 1086*cda5da8dSAndroid Build Coastguard Worker default=None, 1087*cda5da8dSAndroid Build Coastguard Worker required=False, 1088*cda5da8dSAndroid Build Coastguard Worker help=None): 1089*cda5da8dSAndroid Build Coastguard Worker super(_CountAction, self).__init__( 1090*cda5da8dSAndroid Build Coastguard Worker option_strings=option_strings, 1091*cda5da8dSAndroid Build Coastguard Worker dest=dest, 1092*cda5da8dSAndroid Build Coastguard Worker nargs=0, 1093*cda5da8dSAndroid Build Coastguard Worker default=default, 1094*cda5da8dSAndroid Build Coastguard Worker required=required, 1095*cda5da8dSAndroid Build Coastguard Worker help=help) 1096*cda5da8dSAndroid Build Coastguard Worker 1097*cda5da8dSAndroid Build Coastguard Worker def __call__(self, parser, namespace, values, option_string=None): 1098*cda5da8dSAndroid Build Coastguard Worker count = getattr(namespace, self.dest, None) 1099*cda5da8dSAndroid Build Coastguard Worker if count is None: 1100*cda5da8dSAndroid Build Coastguard Worker count = 0 1101*cda5da8dSAndroid Build Coastguard Worker setattr(namespace, self.dest, count + 1) 1102*cda5da8dSAndroid Build Coastguard Worker 1103*cda5da8dSAndroid Build Coastguard Worker 1104*cda5da8dSAndroid Build Coastguard Workerclass _HelpAction(Action): 1105*cda5da8dSAndroid Build Coastguard Worker 1106*cda5da8dSAndroid Build Coastguard Worker def __init__(self, 1107*cda5da8dSAndroid Build Coastguard Worker option_strings, 1108*cda5da8dSAndroid Build Coastguard Worker dest=SUPPRESS, 1109*cda5da8dSAndroid Build Coastguard Worker default=SUPPRESS, 1110*cda5da8dSAndroid Build Coastguard Worker help=None): 1111*cda5da8dSAndroid Build Coastguard Worker super(_HelpAction, self).__init__( 1112*cda5da8dSAndroid Build Coastguard Worker option_strings=option_strings, 1113*cda5da8dSAndroid Build Coastguard Worker dest=dest, 1114*cda5da8dSAndroid Build Coastguard Worker default=default, 1115*cda5da8dSAndroid Build Coastguard Worker nargs=0, 1116*cda5da8dSAndroid Build Coastguard Worker help=help) 1117*cda5da8dSAndroid Build Coastguard Worker 1118*cda5da8dSAndroid Build Coastguard Worker def __call__(self, parser, namespace, values, option_string=None): 1119*cda5da8dSAndroid Build Coastguard Worker parser.print_help() 1120*cda5da8dSAndroid Build Coastguard Worker parser.exit() 1121*cda5da8dSAndroid Build Coastguard Worker 1122*cda5da8dSAndroid Build Coastguard Worker 1123*cda5da8dSAndroid Build Coastguard Workerclass _VersionAction(Action): 1124*cda5da8dSAndroid Build Coastguard Worker 1125*cda5da8dSAndroid Build Coastguard Worker def __init__(self, 1126*cda5da8dSAndroid Build Coastguard Worker option_strings, 1127*cda5da8dSAndroid Build Coastguard Worker version=None, 1128*cda5da8dSAndroid Build Coastguard Worker dest=SUPPRESS, 1129*cda5da8dSAndroid Build Coastguard Worker default=SUPPRESS, 1130*cda5da8dSAndroid Build Coastguard Worker help="show program's version number and exit"): 1131*cda5da8dSAndroid Build Coastguard Worker super(_VersionAction, self).__init__( 1132*cda5da8dSAndroid Build Coastguard Worker option_strings=option_strings, 1133*cda5da8dSAndroid Build Coastguard Worker dest=dest, 1134*cda5da8dSAndroid Build Coastguard Worker default=default, 1135*cda5da8dSAndroid Build Coastguard Worker nargs=0, 1136*cda5da8dSAndroid Build Coastguard Worker help=help) 1137*cda5da8dSAndroid Build Coastguard Worker self.version = version 1138*cda5da8dSAndroid Build Coastguard Worker 1139*cda5da8dSAndroid Build Coastguard Worker def __call__(self, parser, namespace, values, option_string=None): 1140*cda5da8dSAndroid Build Coastguard Worker version = self.version 1141*cda5da8dSAndroid Build Coastguard Worker if version is None: 1142*cda5da8dSAndroid Build Coastguard Worker version = parser.version 1143*cda5da8dSAndroid Build Coastguard Worker formatter = parser._get_formatter() 1144*cda5da8dSAndroid Build Coastguard Worker formatter.add_text(version) 1145*cda5da8dSAndroid Build Coastguard Worker parser._print_message(formatter.format_help(), _sys.stdout) 1146*cda5da8dSAndroid Build Coastguard Worker parser.exit() 1147*cda5da8dSAndroid Build Coastguard Worker 1148*cda5da8dSAndroid Build Coastguard Worker 1149*cda5da8dSAndroid Build Coastguard Workerclass _SubParsersAction(Action): 1150*cda5da8dSAndroid Build Coastguard Worker 1151*cda5da8dSAndroid Build Coastguard Worker class _ChoicesPseudoAction(Action): 1152*cda5da8dSAndroid Build Coastguard Worker 1153*cda5da8dSAndroid Build Coastguard Worker def __init__(self, name, aliases, help): 1154*cda5da8dSAndroid Build Coastguard Worker metavar = dest = name 1155*cda5da8dSAndroid Build Coastguard Worker if aliases: 1156*cda5da8dSAndroid Build Coastguard Worker metavar += ' (%s)' % ', '.join(aliases) 1157*cda5da8dSAndroid Build Coastguard Worker sup = super(_SubParsersAction._ChoicesPseudoAction, self) 1158*cda5da8dSAndroid Build Coastguard Worker sup.__init__(option_strings=[], dest=dest, help=help, 1159*cda5da8dSAndroid Build Coastguard Worker metavar=metavar) 1160*cda5da8dSAndroid Build Coastguard Worker 1161*cda5da8dSAndroid Build Coastguard Worker def __init__(self, 1162*cda5da8dSAndroid Build Coastguard Worker option_strings, 1163*cda5da8dSAndroid Build Coastguard Worker prog, 1164*cda5da8dSAndroid Build Coastguard Worker parser_class, 1165*cda5da8dSAndroid Build Coastguard Worker dest=SUPPRESS, 1166*cda5da8dSAndroid Build Coastguard Worker required=False, 1167*cda5da8dSAndroid Build Coastguard Worker help=None, 1168*cda5da8dSAndroid Build Coastguard Worker metavar=None): 1169*cda5da8dSAndroid Build Coastguard Worker 1170*cda5da8dSAndroid Build Coastguard Worker self._prog_prefix = prog 1171*cda5da8dSAndroid Build Coastguard Worker self._parser_class = parser_class 1172*cda5da8dSAndroid Build Coastguard Worker self._name_parser_map = {} 1173*cda5da8dSAndroid Build Coastguard Worker self._choices_actions = [] 1174*cda5da8dSAndroid Build Coastguard Worker 1175*cda5da8dSAndroid Build Coastguard Worker super(_SubParsersAction, self).__init__( 1176*cda5da8dSAndroid Build Coastguard Worker option_strings=option_strings, 1177*cda5da8dSAndroid Build Coastguard Worker dest=dest, 1178*cda5da8dSAndroid Build Coastguard Worker nargs=PARSER, 1179*cda5da8dSAndroid Build Coastguard Worker choices=self._name_parser_map, 1180*cda5da8dSAndroid Build Coastguard Worker required=required, 1181*cda5da8dSAndroid Build Coastguard Worker help=help, 1182*cda5da8dSAndroid Build Coastguard Worker metavar=metavar) 1183*cda5da8dSAndroid Build Coastguard Worker 1184*cda5da8dSAndroid Build Coastguard Worker def add_parser(self, name, **kwargs): 1185*cda5da8dSAndroid Build Coastguard Worker # set prog from the existing prefix 1186*cda5da8dSAndroid Build Coastguard Worker if kwargs.get('prog') is None: 1187*cda5da8dSAndroid Build Coastguard Worker kwargs['prog'] = '%s %s' % (self._prog_prefix, name) 1188*cda5da8dSAndroid Build Coastguard Worker 1189*cda5da8dSAndroid Build Coastguard Worker aliases = kwargs.pop('aliases', ()) 1190*cda5da8dSAndroid Build Coastguard Worker 1191*cda5da8dSAndroid Build Coastguard Worker if name in self._name_parser_map: 1192*cda5da8dSAndroid Build Coastguard Worker raise ArgumentError(self, _('conflicting subparser: %s') % name) 1193*cda5da8dSAndroid Build Coastguard Worker for alias in aliases: 1194*cda5da8dSAndroid Build Coastguard Worker if alias in self._name_parser_map: 1195*cda5da8dSAndroid Build Coastguard Worker raise ArgumentError( 1196*cda5da8dSAndroid Build Coastguard Worker self, _('conflicting subparser alias: %s') % alias) 1197*cda5da8dSAndroid Build Coastguard Worker 1198*cda5da8dSAndroid Build Coastguard Worker # create a pseudo-action to hold the choice help 1199*cda5da8dSAndroid Build Coastguard Worker if 'help' in kwargs: 1200*cda5da8dSAndroid Build Coastguard Worker help = kwargs.pop('help') 1201*cda5da8dSAndroid Build Coastguard Worker choice_action = self._ChoicesPseudoAction(name, aliases, help) 1202*cda5da8dSAndroid Build Coastguard Worker self._choices_actions.append(choice_action) 1203*cda5da8dSAndroid Build Coastguard Worker 1204*cda5da8dSAndroid Build Coastguard Worker # create the parser and add it to the map 1205*cda5da8dSAndroid Build Coastguard Worker parser = self._parser_class(**kwargs) 1206*cda5da8dSAndroid Build Coastguard Worker self._name_parser_map[name] = parser 1207*cda5da8dSAndroid Build Coastguard Worker 1208*cda5da8dSAndroid Build Coastguard Worker # make parser available under aliases also 1209*cda5da8dSAndroid Build Coastguard Worker for alias in aliases: 1210*cda5da8dSAndroid Build Coastguard Worker self._name_parser_map[alias] = parser 1211*cda5da8dSAndroid Build Coastguard Worker 1212*cda5da8dSAndroid Build Coastguard Worker return parser 1213*cda5da8dSAndroid Build Coastguard Worker 1214*cda5da8dSAndroid Build Coastguard Worker def _get_subactions(self): 1215*cda5da8dSAndroid Build Coastguard Worker return self._choices_actions 1216*cda5da8dSAndroid Build Coastguard Worker 1217*cda5da8dSAndroid Build Coastguard Worker def __call__(self, parser, namespace, values, option_string=None): 1218*cda5da8dSAndroid Build Coastguard Worker parser_name = values[0] 1219*cda5da8dSAndroid Build Coastguard Worker arg_strings = values[1:] 1220*cda5da8dSAndroid Build Coastguard Worker 1221*cda5da8dSAndroid Build Coastguard Worker # set the parser name if requested 1222*cda5da8dSAndroid Build Coastguard Worker if self.dest is not SUPPRESS: 1223*cda5da8dSAndroid Build Coastguard Worker setattr(namespace, self.dest, parser_name) 1224*cda5da8dSAndroid Build Coastguard Worker 1225*cda5da8dSAndroid Build Coastguard Worker # select the parser 1226*cda5da8dSAndroid Build Coastguard Worker try: 1227*cda5da8dSAndroid Build Coastguard Worker parser = self._name_parser_map[parser_name] 1228*cda5da8dSAndroid Build Coastguard Worker except KeyError: 1229*cda5da8dSAndroid Build Coastguard Worker args = {'parser_name': parser_name, 1230*cda5da8dSAndroid Build Coastguard Worker 'choices': ', '.join(self._name_parser_map)} 1231*cda5da8dSAndroid Build Coastguard Worker msg = _('unknown parser %(parser_name)r (choices: %(choices)s)') % args 1232*cda5da8dSAndroid Build Coastguard Worker raise ArgumentError(self, msg) 1233*cda5da8dSAndroid Build Coastguard Worker 1234*cda5da8dSAndroid Build Coastguard Worker # parse all the remaining options into the namespace 1235*cda5da8dSAndroid Build Coastguard Worker # store any unrecognized options on the object, so that the top 1236*cda5da8dSAndroid Build Coastguard Worker # level parser can decide what to do with them 1237*cda5da8dSAndroid Build Coastguard Worker 1238*cda5da8dSAndroid Build Coastguard Worker # In case this subparser defines new defaults, we parse them 1239*cda5da8dSAndroid Build Coastguard Worker # in a new namespace object and then update the original 1240*cda5da8dSAndroid Build Coastguard Worker # namespace for the relevant parts. 1241*cda5da8dSAndroid Build Coastguard Worker subnamespace, arg_strings = parser.parse_known_args(arg_strings, None) 1242*cda5da8dSAndroid Build Coastguard Worker for key, value in vars(subnamespace).items(): 1243*cda5da8dSAndroid Build Coastguard Worker setattr(namespace, key, value) 1244*cda5da8dSAndroid Build Coastguard Worker 1245*cda5da8dSAndroid Build Coastguard Worker if arg_strings: 1246*cda5da8dSAndroid Build Coastguard Worker vars(namespace).setdefault(_UNRECOGNIZED_ARGS_ATTR, []) 1247*cda5da8dSAndroid Build Coastguard Worker getattr(namespace, _UNRECOGNIZED_ARGS_ATTR).extend(arg_strings) 1248*cda5da8dSAndroid Build Coastguard Worker 1249*cda5da8dSAndroid Build Coastguard Workerclass _ExtendAction(_AppendAction): 1250*cda5da8dSAndroid Build Coastguard Worker def __call__(self, parser, namespace, values, option_string=None): 1251*cda5da8dSAndroid Build Coastguard Worker items = getattr(namespace, self.dest, None) 1252*cda5da8dSAndroid Build Coastguard Worker items = _copy_items(items) 1253*cda5da8dSAndroid Build Coastguard Worker items.extend(values) 1254*cda5da8dSAndroid Build Coastguard Worker setattr(namespace, self.dest, items) 1255*cda5da8dSAndroid Build Coastguard Worker 1256*cda5da8dSAndroid Build Coastguard Worker# ============== 1257*cda5da8dSAndroid Build Coastguard Worker# Type classes 1258*cda5da8dSAndroid Build Coastguard Worker# ============== 1259*cda5da8dSAndroid Build Coastguard Worker 1260*cda5da8dSAndroid Build Coastguard Workerclass FileType(object): 1261*cda5da8dSAndroid Build Coastguard Worker """Factory for creating file object types 1262*cda5da8dSAndroid Build Coastguard Worker 1263*cda5da8dSAndroid Build Coastguard Worker Instances of FileType are typically passed as type= arguments to the 1264*cda5da8dSAndroid Build Coastguard Worker ArgumentParser add_argument() method. 1265*cda5da8dSAndroid Build Coastguard Worker 1266*cda5da8dSAndroid Build Coastguard Worker Keyword Arguments: 1267*cda5da8dSAndroid Build Coastguard Worker - mode -- A string indicating how the file is to be opened. Accepts the 1268*cda5da8dSAndroid Build Coastguard Worker same values as the builtin open() function. 1269*cda5da8dSAndroid Build Coastguard Worker - bufsize -- The file's desired buffer size. Accepts the same values as 1270*cda5da8dSAndroid Build Coastguard Worker the builtin open() function. 1271*cda5da8dSAndroid Build Coastguard Worker - encoding -- The file's encoding. Accepts the same values as the 1272*cda5da8dSAndroid Build Coastguard Worker builtin open() function. 1273*cda5da8dSAndroid Build Coastguard Worker - errors -- A string indicating how encoding and decoding errors are to 1274*cda5da8dSAndroid Build Coastguard Worker be handled. Accepts the same value as the builtin open() function. 1275*cda5da8dSAndroid Build Coastguard Worker """ 1276*cda5da8dSAndroid Build Coastguard Worker 1277*cda5da8dSAndroid Build Coastguard Worker def __init__(self, mode='r', bufsize=-1, encoding=None, errors=None): 1278*cda5da8dSAndroid Build Coastguard Worker self._mode = mode 1279*cda5da8dSAndroid Build Coastguard Worker self._bufsize = bufsize 1280*cda5da8dSAndroid Build Coastguard Worker self._encoding = encoding 1281*cda5da8dSAndroid Build Coastguard Worker self._errors = errors 1282*cda5da8dSAndroid Build Coastguard Worker 1283*cda5da8dSAndroid Build Coastguard Worker def __call__(self, string): 1284*cda5da8dSAndroid Build Coastguard Worker # the special argument "-" means sys.std{in,out} 1285*cda5da8dSAndroid Build Coastguard Worker if string == '-': 1286*cda5da8dSAndroid Build Coastguard Worker if 'r' in self._mode: 1287*cda5da8dSAndroid Build Coastguard Worker return _sys.stdin.buffer if 'b' in self._mode else _sys.stdin 1288*cda5da8dSAndroid Build Coastguard Worker elif any(c in self._mode for c in 'wax'): 1289*cda5da8dSAndroid Build Coastguard Worker return _sys.stdout.buffer if 'b' in self._mode else _sys.stdout 1290*cda5da8dSAndroid Build Coastguard Worker else: 1291*cda5da8dSAndroid Build Coastguard Worker msg = _('argument "-" with mode %r') % self._mode 1292*cda5da8dSAndroid Build Coastguard Worker raise ValueError(msg) 1293*cda5da8dSAndroid Build Coastguard Worker 1294*cda5da8dSAndroid Build Coastguard Worker # all other arguments are used as file names 1295*cda5da8dSAndroid Build Coastguard Worker try: 1296*cda5da8dSAndroid Build Coastguard Worker return open(string, self._mode, self._bufsize, self._encoding, 1297*cda5da8dSAndroid Build Coastguard Worker self._errors) 1298*cda5da8dSAndroid Build Coastguard Worker except OSError as e: 1299*cda5da8dSAndroid Build Coastguard Worker args = {'filename': string, 'error': e} 1300*cda5da8dSAndroid Build Coastguard Worker message = _("can't open '%(filename)s': %(error)s") 1301*cda5da8dSAndroid Build Coastguard Worker raise ArgumentTypeError(message % args) 1302*cda5da8dSAndroid Build Coastguard Worker 1303*cda5da8dSAndroid Build Coastguard Worker def __repr__(self): 1304*cda5da8dSAndroid Build Coastguard Worker args = self._mode, self._bufsize 1305*cda5da8dSAndroid Build Coastguard Worker kwargs = [('encoding', self._encoding), ('errors', self._errors)] 1306*cda5da8dSAndroid Build Coastguard Worker args_str = ', '.join([repr(arg) for arg in args if arg != -1] + 1307*cda5da8dSAndroid Build Coastguard Worker ['%s=%r' % (kw, arg) for kw, arg in kwargs 1308*cda5da8dSAndroid Build Coastguard Worker if arg is not None]) 1309*cda5da8dSAndroid Build Coastguard Worker return '%s(%s)' % (type(self).__name__, args_str) 1310*cda5da8dSAndroid Build Coastguard Worker 1311*cda5da8dSAndroid Build Coastguard Worker# =========================== 1312*cda5da8dSAndroid Build Coastguard Worker# Optional and Positional Parsing 1313*cda5da8dSAndroid Build Coastguard Worker# =========================== 1314*cda5da8dSAndroid Build Coastguard Worker 1315*cda5da8dSAndroid Build Coastguard Workerclass Namespace(_AttributeHolder): 1316*cda5da8dSAndroid Build Coastguard Worker """Simple object for storing attributes. 1317*cda5da8dSAndroid Build Coastguard Worker 1318*cda5da8dSAndroid Build Coastguard Worker Implements equality by attribute names and values, and provides a simple 1319*cda5da8dSAndroid Build Coastguard Worker string representation. 1320*cda5da8dSAndroid Build Coastguard Worker """ 1321*cda5da8dSAndroid Build Coastguard Worker 1322*cda5da8dSAndroid Build Coastguard Worker def __init__(self, **kwargs): 1323*cda5da8dSAndroid Build Coastguard Worker for name in kwargs: 1324*cda5da8dSAndroid Build Coastguard Worker setattr(self, name, kwargs[name]) 1325*cda5da8dSAndroid Build Coastguard Worker 1326*cda5da8dSAndroid Build Coastguard Worker def __eq__(self, other): 1327*cda5da8dSAndroid Build Coastguard Worker if not isinstance(other, Namespace): 1328*cda5da8dSAndroid Build Coastguard Worker return NotImplemented 1329*cda5da8dSAndroid Build Coastguard Worker return vars(self) == vars(other) 1330*cda5da8dSAndroid Build Coastguard Worker 1331*cda5da8dSAndroid Build Coastguard Worker def __contains__(self, key): 1332*cda5da8dSAndroid Build Coastguard Worker return key in self.__dict__ 1333*cda5da8dSAndroid Build Coastguard Worker 1334*cda5da8dSAndroid Build Coastguard Worker 1335*cda5da8dSAndroid Build Coastguard Workerclass _ActionsContainer(object): 1336*cda5da8dSAndroid Build Coastguard Worker 1337*cda5da8dSAndroid Build Coastguard Worker def __init__(self, 1338*cda5da8dSAndroid Build Coastguard Worker description, 1339*cda5da8dSAndroid Build Coastguard Worker prefix_chars, 1340*cda5da8dSAndroid Build Coastguard Worker argument_default, 1341*cda5da8dSAndroid Build Coastguard Worker conflict_handler): 1342*cda5da8dSAndroid Build Coastguard Worker super(_ActionsContainer, self).__init__() 1343*cda5da8dSAndroid Build Coastguard Worker 1344*cda5da8dSAndroid Build Coastguard Worker self.description = description 1345*cda5da8dSAndroid Build Coastguard Worker self.argument_default = argument_default 1346*cda5da8dSAndroid Build Coastguard Worker self.prefix_chars = prefix_chars 1347*cda5da8dSAndroid Build Coastguard Worker self.conflict_handler = conflict_handler 1348*cda5da8dSAndroid Build Coastguard Worker 1349*cda5da8dSAndroid Build Coastguard Worker # set up registries 1350*cda5da8dSAndroid Build Coastguard Worker self._registries = {} 1351*cda5da8dSAndroid Build Coastguard Worker 1352*cda5da8dSAndroid Build Coastguard Worker # register actions 1353*cda5da8dSAndroid Build Coastguard Worker self.register('action', None, _StoreAction) 1354*cda5da8dSAndroid Build Coastguard Worker self.register('action', 'store', _StoreAction) 1355*cda5da8dSAndroid Build Coastguard Worker self.register('action', 'store_const', _StoreConstAction) 1356*cda5da8dSAndroid Build Coastguard Worker self.register('action', 'store_true', _StoreTrueAction) 1357*cda5da8dSAndroid Build Coastguard Worker self.register('action', 'store_false', _StoreFalseAction) 1358*cda5da8dSAndroid Build Coastguard Worker self.register('action', 'append', _AppendAction) 1359*cda5da8dSAndroid Build Coastguard Worker self.register('action', 'append_const', _AppendConstAction) 1360*cda5da8dSAndroid Build Coastguard Worker self.register('action', 'count', _CountAction) 1361*cda5da8dSAndroid Build Coastguard Worker self.register('action', 'help', _HelpAction) 1362*cda5da8dSAndroid Build Coastguard Worker self.register('action', 'version', _VersionAction) 1363*cda5da8dSAndroid Build Coastguard Worker self.register('action', 'parsers', _SubParsersAction) 1364*cda5da8dSAndroid Build Coastguard Worker self.register('action', 'extend', _ExtendAction) 1365*cda5da8dSAndroid Build Coastguard Worker 1366*cda5da8dSAndroid Build Coastguard Worker # raise an exception if the conflict handler is invalid 1367*cda5da8dSAndroid Build Coastguard Worker self._get_handler() 1368*cda5da8dSAndroid Build Coastguard Worker 1369*cda5da8dSAndroid Build Coastguard Worker # action storage 1370*cda5da8dSAndroid Build Coastguard Worker self._actions = [] 1371*cda5da8dSAndroid Build Coastguard Worker self._option_string_actions = {} 1372*cda5da8dSAndroid Build Coastguard Worker 1373*cda5da8dSAndroid Build Coastguard Worker # groups 1374*cda5da8dSAndroid Build Coastguard Worker self._action_groups = [] 1375*cda5da8dSAndroid Build Coastguard Worker self._mutually_exclusive_groups = [] 1376*cda5da8dSAndroid Build Coastguard Worker 1377*cda5da8dSAndroid Build Coastguard Worker # defaults storage 1378*cda5da8dSAndroid Build Coastguard Worker self._defaults = {} 1379*cda5da8dSAndroid Build Coastguard Worker 1380*cda5da8dSAndroid Build Coastguard Worker # determines whether an "option" looks like a negative number 1381*cda5da8dSAndroid Build Coastguard Worker self._negative_number_matcher = _re.compile(r'^-\d+$|^-\d*\.\d+$') 1382*cda5da8dSAndroid Build Coastguard Worker 1383*cda5da8dSAndroid Build Coastguard Worker # whether or not there are any optionals that look like negative 1384*cda5da8dSAndroid Build Coastguard Worker # numbers -- uses a list so it can be shared and edited 1385*cda5da8dSAndroid Build Coastguard Worker self._has_negative_number_optionals = [] 1386*cda5da8dSAndroid Build Coastguard Worker 1387*cda5da8dSAndroid Build Coastguard Worker # ==================== 1388*cda5da8dSAndroid Build Coastguard Worker # Registration methods 1389*cda5da8dSAndroid Build Coastguard Worker # ==================== 1390*cda5da8dSAndroid Build Coastguard Worker def register(self, registry_name, value, object): 1391*cda5da8dSAndroid Build Coastguard Worker registry = self._registries.setdefault(registry_name, {}) 1392*cda5da8dSAndroid Build Coastguard Worker registry[value] = object 1393*cda5da8dSAndroid Build Coastguard Worker 1394*cda5da8dSAndroid Build Coastguard Worker def _registry_get(self, registry_name, value, default=None): 1395*cda5da8dSAndroid Build Coastguard Worker return self._registries[registry_name].get(value, default) 1396*cda5da8dSAndroid Build Coastguard Worker 1397*cda5da8dSAndroid Build Coastguard Worker # ================================== 1398*cda5da8dSAndroid Build Coastguard Worker # Namespace default accessor methods 1399*cda5da8dSAndroid Build Coastguard Worker # ================================== 1400*cda5da8dSAndroid Build Coastguard Worker def set_defaults(self, **kwargs): 1401*cda5da8dSAndroid Build Coastguard Worker self._defaults.update(kwargs) 1402*cda5da8dSAndroid Build Coastguard Worker 1403*cda5da8dSAndroid Build Coastguard Worker # if these defaults match any existing arguments, replace 1404*cda5da8dSAndroid Build Coastguard Worker # the previous default on the object with the new one 1405*cda5da8dSAndroid Build Coastguard Worker for action in self._actions: 1406*cda5da8dSAndroid Build Coastguard Worker if action.dest in kwargs: 1407*cda5da8dSAndroid Build Coastguard Worker action.default = kwargs[action.dest] 1408*cda5da8dSAndroid Build Coastguard Worker 1409*cda5da8dSAndroid Build Coastguard Worker def get_default(self, dest): 1410*cda5da8dSAndroid Build Coastguard Worker for action in self._actions: 1411*cda5da8dSAndroid Build Coastguard Worker if action.dest == dest and action.default is not None: 1412*cda5da8dSAndroid Build Coastguard Worker return action.default 1413*cda5da8dSAndroid Build Coastguard Worker return self._defaults.get(dest, None) 1414*cda5da8dSAndroid Build Coastguard Worker 1415*cda5da8dSAndroid Build Coastguard Worker 1416*cda5da8dSAndroid Build Coastguard Worker # ======================= 1417*cda5da8dSAndroid Build Coastguard Worker # Adding argument actions 1418*cda5da8dSAndroid Build Coastguard Worker # ======================= 1419*cda5da8dSAndroid Build Coastguard Worker def add_argument(self, *args, **kwargs): 1420*cda5da8dSAndroid Build Coastguard Worker """ 1421*cda5da8dSAndroid Build Coastguard Worker add_argument(dest, ..., name=value, ...) 1422*cda5da8dSAndroid Build Coastguard Worker add_argument(option_string, option_string, ..., name=value, ...) 1423*cda5da8dSAndroid Build Coastguard Worker """ 1424*cda5da8dSAndroid Build Coastguard Worker 1425*cda5da8dSAndroid Build Coastguard Worker # if no positional args are supplied or only one is supplied and 1426*cda5da8dSAndroid Build Coastguard Worker # it doesn't look like an option string, parse a positional 1427*cda5da8dSAndroid Build Coastguard Worker # argument 1428*cda5da8dSAndroid Build Coastguard Worker chars = self.prefix_chars 1429*cda5da8dSAndroid Build Coastguard Worker if not args or len(args) == 1 and args[0][0] not in chars: 1430*cda5da8dSAndroid Build Coastguard Worker if args and 'dest' in kwargs: 1431*cda5da8dSAndroid Build Coastguard Worker raise ValueError('dest supplied twice for positional argument') 1432*cda5da8dSAndroid Build Coastguard Worker kwargs = self._get_positional_kwargs(*args, **kwargs) 1433*cda5da8dSAndroid Build Coastguard Worker 1434*cda5da8dSAndroid Build Coastguard Worker # otherwise, we're adding an optional argument 1435*cda5da8dSAndroid Build Coastguard Worker else: 1436*cda5da8dSAndroid Build Coastguard Worker kwargs = self._get_optional_kwargs(*args, **kwargs) 1437*cda5da8dSAndroid Build Coastguard Worker 1438*cda5da8dSAndroid Build Coastguard Worker # if no default was supplied, use the parser-level default 1439*cda5da8dSAndroid Build Coastguard Worker if 'default' not in kwargs: 1440*cda5da8dSAndroid Build Coastguard Worker dest = kwargs['dest'] 1441*cda5da8dSAndroid Build Coastguard Worker if dest in self._defaults: 1442*cda5da8dSAndroid Build Coastguard Worker kwargs['default'] = self._defaults[dest] 1443*cda5da8dSAndroid Build Coastguard Worker elif self.argument_default is not None: 1444*cda5da8dSAndroid Build Coastguard Worker kwargs['default'] = self.argument_default 1445*cda5da8dSAndroid Build Coastguard Worker 1446*cda5da8dSAndroid Build Coastguard Worker # create the action object, and add it to the parser 1447*cda5da8dSAndroid Build Coastguard Worker action_class = self._pop_action_class(kwargs) 1448*cda5da8dSAndroid Build Coastguard Worker if not callable(action_class): 1449*cda5da8dSAndroid Build Coastguard Worker raise ValueError('unknown action "%s"' % (action_class,)) 1450*cda5da8dSAndroid Build Coastguard Worker action = action_class(**kwargs) 1451*cda5da8dSAndroid Build Coastguard Worker 1452*cda5da8dSAndroid Build Coastguard Worker # raise an error if the action type is not callable 1453*cda5da8dSAndroid Build Coastguard Worker type_func = self._registry_get('type', action.type, action.type) 1454*cda5da8dSAndroid Build Coastguard Worker if not callable(type_func): 1455*cda5da8dSAndroid Build Coastguard Worker raise ValueError('%r is not callable' % (type_func,)) 1456*cda5da8dSAndroid Build Coastguard Worker 1457*cda5da8dSAndroid Build Coastguard Worker if type_func is FileType: 1458*cda5da8dSAndroid Build Coastguard Worker raise ValueError('%r is a FileType class object, instance of it' 1459*cda5da8dSAndroid Build Coastguard Worker ' must be passed' % (type_func,)) 1460*cda5da8dSAndroid Build Coastguard Worker 1461*cda5da8dSAndroid Build Coastguard Worker # raise an error if the metavar does not match the type 1462*cda5da8dSAndroid Build Coastguard Worker if hasattr(self, "_get_formatter"): 1463*cda5da8dSAndroid Build Coastguard Worker try: 1464*cda5da8dSAndroid Build Coastguard Worker self._get_formatter()._format_args(action, None) 1465*cda5da8dSAndroid Build Coastguard Worker except TypeError: 1466*cda5da8dSAndroid Build Coastguard Worker raise ValueError("length of metavar tuple does not match nargs") 1467*cda5da8dSAndroid Build Coastguard Worker 1468*cda5da8dSAndroid Build Coastguard Worker return self._add_action(action) 1469*cda5da8dSAndroid Build Coastguard Worker 1470*cda5da8dSAndroid Build Coastguard Worker def add_argument_group(self, *args, **kwargs): 1471*cda5da8dSAndroid Build Coastguard Worker group = _ArgumentGroup(self, *args, **kwargs) 1472*cda5da8dSAndroid Build Coastguard Worker self._action_groups.append(group) 1473*cda5da8dSAndroid Build Coastguard Worker return group 1474*cda5da8dSAndroid Build Coastguard Worker 1475*cda5da8dSAndroid Build Coastguard Worker def add_mutually_exclusive_group(self, **kwargs): 1476*cda5da8dSAndroid Build Coastguard Worker group = _MutuallyExclusiveGroup(self, **kwargs) 1477*cda5da8dSAndroid Build Coastguard Worker self._mutually_exclusive_groups.append(group) 1478*cda5da8dSAndroid Build Coastguard Worker return group 1479*cda5da8dSAndroid Build Coastguard Worker 1480*cda5da8dSAndroid Build Coastguard Worker def _add_action(self, action): 1481*cda5da8dSAndroid Build Coastguard Worker # resolve any conflicts 1482*cda5da8dSAndroid Build Coastguard Worker self._check_conflict(action) 1483*cda5da8dSAndroid Build Coastguard Worker 1484*cda5da8dSAndroid Build Coastguard Worker # add to actions list 1485*cda5da8dSAndroid Build Coastguard Worker self._actions.append(action) 1486*cda5da8dSAndroid Build Coastguard Worker action.container = self 1487*cda5da8dSAndroid Build Coastguard Worker 1488*cda5da8dSAndroid Build Coastguard Worker # index the action by any option strings it has 1489*cda5da8dSAndroid Build Coastguard Worker for option_string in action.option_strings: 1490*cda5da8dSAndroid Build Coastguard Worker self._option_string_actions[option_string] = action 1491*cda5da8dSAndroid Build Coastguard Worker 1492*cda5da8dSAndroid Build Coastguard Worker # set the flag if any option strings look like negative numbers 1493*cda5da8dSAndroid Build Coastguard Worker for option_string in action.option_strings: 1494*cda5da8dSAndroid Build Coastguard Worker if self._negative_number_matcher.match(option_string): 1495*cda5da8dSAndroid Build Coastguard Worker if not self._has_negative_number_optionals: 1496*cda5da8dSAndroid Build Coastguard Worker self._has_negative_number_optionals.append(True) 1497*cda5da8dSAndroid Build Coastguard Worker 1498*cda5da8dSAndroid Build Coastguard Worker # return the created action 1499*cda5da8dSAndroid Build Coastguard Worker return action 1500*cda5da8dSAndroid Build Coastguard Worker 1501*cda5da8dSAndroid Build Coastguard Worker def _remove_action(self, action): 1502*cda5da8dSAndroid Build Coastguard Worker self._actions.remove(action) 1503*cda5da8dSAndroid Build Coastguard Worker 1504*cda5da8dSAndroid Build Coastguard Worker def _add_container_actions(self, container): 1505*cda5da8dSAndroid Build Coastguard Worker # collect groups by titles 1506*cda5da8dSAndroid Build Coastguard Worker title_group_map = {} 1507*cda5da8dSAndroid Build Coastguard Worker for group in self._action_groups: 1508*cda5da8dSAndroid Build Coastguard Worker if group.title in title_group_map: 1509*cda5da8dSAndroid Build Coastguard Worker msg = _('cannot merge actions - two groups are named %r') 1510*cda5da8dSAndroid Build Coastguard Worker raise ValueError(msg % (group.title)) 1511*cda5da8dSAndroid Build Coastguard Worker title_group_map[group.title] = group 1512*cda5da8dSAndroid Build Coastguard Worker 1513*cda5da8dSAndroid Build Coastguard Worker # map each action to its group 1514*cda5da8dSAndroid Build Coastguard Worker group_map = {} 1515*cda5da8dSAndroid Build Coastguard Worker for group in container._action_groups: 1516*cda5da8dSAndroid Build Coastguard Worker 1517*cda5da8dSAndroid Build Coastguard Worker # if a group with the title exists, use that, otherwise 1518*cda5da8dSAndroid Build Coastguard Worker # create a new group matching the container's group 1519*cda5da8dSAndroid Build Coastguard Worker if group.title not in title_group_map: 1520*cda5da8dSAndroid Build Coastguard Worker title_group_map[group.title] = self.add_argument_group( 1521*cda5da8dSAndroid Build Coastguard Worker title=group.title, 1522*cda5da8dSAndroid Build Coastguard Worker description=group.description, 1523*cda5da8dSAndroid Build Coastguard Worker conflict_handler=group.conflict_handler) 1524*cda5da8dSAndroid Build Coastguard Worker 1525*cda5da8dSAndroid Build Coastguard Worker # map the actions to their new group 1526*cda5da8dSAndroid Build Coastguard Worker for action in group._group_actions: 1527*cda5da8dSAndroid Build Coastguard Worker group_map[action] = title_group_map[group.title] 1528*cda5da8dSAndroid Build Coastguard Worker 1529*cda5da8dSAndroid Build Coastguard Worker # add container's mutually exclusive groups 1530*cda5da8dSAndroid Build Coastguard Worker # NOTE: if add_mutually_exclusive_group ever gains title= and 1531*cda5da8dSAndroid Build Coastguard Worker # description= then this code will need to be expanded as above 1532*cda5da8dSAndroid Build Coastguard Worker for group in container._mutually_exclusive_groups: 1533*cda5da8dSAndroid Build Coastguard Worker mutex_group = self.add_mutually_exclusive_group( 1534*cda5da8dSAndroid Build Coastguard Worker required=group.required) 1535*cda5da8dSAndroid Build Coastguard Worker 1536*cda5da8dSAndroid Build Coastguard Worker # map the actions to their new mutex group 1537*cda5da8dSAndroid Build Coastguard Worker for action in group._group_actions: 1538*cda5da8dSAndroid Build Coastguard Worker group_map[action] = mutex_group 1539*cda5da8dSAndroid Build Coastguard Worker 1540*cda5da8dSAndroid Build Coastguard Worker # add all actions to this container or their group 1541*cda5da8dSAndroid Build Coastguard Worker for action in container._actions: 1542*cda5da8dSAndroid Build Coastguard Worker group_map.get(action, self)._add_action(action) 1543*cda5da8dSAndroid Build Coastguard Worker 1544*cda5da8dSAndroid Build Coastguard Worker def _get_positional_kwargs(self, dest, **kwargs): 1545*cda5da8dSAndroid Build Coastguard Worker # make sure required is not specified 1546*cda5da8dSAndroid Build Coastguard Worker if 'required' in kwargs: 1547*cda5da8dSAndroid Build Coastguard Worker msg = _("'required' is an invalid argument for positionals") 1548*cda5da8dSAndroid Build Coastguard Worker raise TypeError(msg) 1549*cda5da8dSAndroid Build Coastguard Worker 1550*cda5da8dSAndroid Build Coastguard Worker # mark positional arguments as required if at least one is 1551*cda5da8dSAndroid Build Coastguard Worker # always required 1552*cda5da8dSAndroid Build Coastguard Worker if kwargs.get('nargs') not in [OPTIONAL, ZERO_OR_MORE]: 1553*cda5da8dSAndroid Build Coastguard Worker kwargs['required'] = True 1554*cda5da8dSAndroid Build Coastguard Worker if kwargs.get('nargs') == ZERO_OR_MORE and 'default' not in kwargs: 1555*cda5da8dSAndroid Build Coastguard Worker kwargs['required'] = True 1556*cda5da8dSAndroid Build Coastguard Worker 1557*cda5da8dSAndroid Build Coastguard Worker # return the keyword arguments with no option strings 1558*cda5da8dSAndroid Build Coastguard Worker return dict(kwargs, dest=dest, option_strings=[]) 1559*cda5da8dSAndroid Build Coastguard Worker 1560*cda5da8dSAndroid Build Coastguard Worker def _get_optional_kwargs(self, *args, **kwargs): 1561*cda5da8dSAndroid Build Coastguard Worker # determine short and long option strings 1562*cda5da8dSAndroid Build Coastguard Worker option_strings = [] 1563*cda5da8dSAndroid Build Coastguard Worker long_option_strings = [] 1564*cda5da8dSAndroid Build Coastguard Worker for option_string in args: 1565*cda5da8dSAndroid Build Coastguard Worker # error on strings that don't start with an appropriate prefix 1566*cda5da8dSAndroid Build Coastguard Worker if not option_string[0] in self.prefix_chars: 1567*cda5da8dSAndroid Build Coastguard Worker args = {'option': option_string, 1568*cda5da8dSAndroid Build Coastguard Worker 'prefix_chars': self.prefix_chars} 1569*cda5da8dSAndroid Build Coastguard Worker msg = _('invalid option string %(option)r: ' 1570*cda5da8dSAndroid Build Coastguard Worker 'must start with a character %(prefix_chars)r') 1571*cda5da8dSAndroid Build Coastguard Worker raise ValueError(msg % args) 1572*cda5da8dSAndroid Build Coastguard Worker 1573*cda5da8dSAndroid Build Coastguard Worker # strings starting with two prefix characters are long options 1574*cda5da8dSAndroid Build Coastguard Worker option_strings.append(option_string) 1575*cda5da8dSAndroid Build Coastguard Worker if len(option_string) > 1 and option_string[1] in self.prefix_chars: 1576*cda5da8dSAndroid Build Coastguard Worker long_option_strings.append(option_string) 1577*cda5da8dSAndroid Build Coastguard Worker 1578*cda5da8dSAndroid Build Coastguard Worker # infer destination, '--foo-bar' -> 'foo_bar' and '-x' -> 'x' 1579*cda5da8dSAndroid Build Coastguard Worker dest = kwargs.pop('dest', None) 1580*cda5da8dSAndroid Build Coastguard Worker if dest is None: 1581*cda5da8dSAndroid Build Coastguard Worker if long_option_strings: 1582*cda5da8dSAndroid Build Coastguard Worker dest_option_string = long_option_strings[0] 1583*cda5da8dSAndroid Build Coastguard Worker else: 1584*cda5da8dSAndroid Build Coastguard Worker dest_option_string = option_strings[0] 1585*cda5da8dSAndroid Build Coastguard Worker dest = dest_option_string.lstrip(self.prefix_chars) 1586*cda5da8dSAndroid Build Coastguard Worker if not dest: 1587*cda5da8dSAndroid Build Coastguard Worker msg = _('dest= is required for options like %r') 1588*cda5da8dSAndroid Build Coastguard Worker raise ValueError(msg % option_string) 1589*cda5da8dSAndroid Build Coastguard Worker dest = dest.replace('-', '_') 1590*cda5da8dSAndroid Build Coastguard Worker 1591*cda5da8dSAndroid Build Coastguard Worker # return the updated keyword arguments 1592*cda5da8dSAndroid Build Coastguard Worker return dict(kwargs, dest=dest, option_strings=option_strings) 1593*cda5da8dSAndroid Build Coastguard Worker 1594*cda5da8dSAndroid Build Coastguard Worker def _pop_action_class(self, kwargs, default=None): 1595*cda5da8dSAndroid Build Coastguard Worker action = kwargs.pop('action', default) 1596*cda5da8dSAndroid Build Coastguard Worker return self._registry_get('action', action, action) 1597*cda5da8dSAndroid Build Coastguard Worker 1598*cda5da8dSAndroid Build Coastguard Worker def _get_handler(self): 1599*cda5da8dSAndroid Build Coastguard Worker # determine function from conflict handler string 1600*cda5da8dSAndroid Build Coastguard Worker handler_func_name = '_handle_conflict_%s' % self.conflict_handler 1601*cda5da8dSAndroid Build Coastguard Worker try: 1602*cda5da8dSAndroid Build Coastguard Worker return getattr(self, handler_func_name) 1603*cda5da8dSAndroid Build Coastguard Worker except AttributeError: 1604*cda5da8dSAndroid Build Coastguard Worker msg = _('invalid conflict_resolution value: %r') 1605*cda5da8dSAndroid Build Coastguard Worker raise ValueError(msg % self.conflict_handler) 1606*cda5da8dSAndroid Build Coastguard Worker 1607*cda5da8dSAndroid Build Coastguard Worker def _check_conflict(self, action): 1608*cda5da8dSAndroid Build Coastguard Worker 1609*cda5da8dSAndroid Build Coastguard Worker # find all options that conflict with this option 1610*cda5da8dSAndroid Build Coastguard Worker confl_optionals = [] 1611*cda5da8dSAndroid Build Coastguard Worker for option_string in action.option_strings: 1612*cda5da8dSAndroid Build Coastguard Worker if option_string in self._option_string_actions: 1613*cda5da8dSAndroid Build Coastguard Worker confl_optional = self._option_string_actions[option_string] 1614*cda5da8dSAndroid Build Coastguard Worker confl_optionals.append((option_string, confl_optional)) 1615*cda5da8dSAndroid Build Coastguard Worker 1616*cda5da8dSAndroid Build Coastguard Worker # resolve any conflicts 1617*cda5da8dSAndroid Build Coastguard Worker if confl_optionals: 1618*cda5da8dSAndroid Build Coastguard Worker conflict_handler = self._get_handler() 1619*cda5da8dSAndroid Build Coastguard Worker conflict_handler(action, confl_optionals) 1620*cda5da8dSAndroid Build Coastguard Worker 1621*cda5da8dSAndroid Build Coastguard Worker def _handle_conflict_error(self, action, conflicting_actions): 1622*cda5da8dSAndroid Build Coastguard Worker message = ngettext('conflicting option string: %s', 1623*cda5da8dSAndroid Build Coastguard Worker 'conflicting option strings: %s', 1624*cda5da8dSAndroid Build Coastguard Worker len(conflicting_actions)) 1625*cda5da8dSAndroid Build Coastguard Worker conflict_string = ', '.join([option_string 1626*cda5da8dSAndroid Build Coastguard Worker for option_string, action 1627*cda5da8dSAndroid Build Coastguard Worker in conflicting_actions]) 1628*cda5da8dSAndroid Build Coastguard Worker raise ArgumentError(action, message % conflict_string) 1629*cda5da8dSAndroid Build Coastguard Worker 1630*cda5da8dSAndroid Build Coastguard Worker def _handle_conflict_resolve(self, action, conflicting_actions): 1631*cda5da8dSAndroid Build Coastguard Worker 1632*cda5da8dSAndroid Build Coastguard Worker # remove all conflicting options 1633*cda5da8dSAndroid Build Coastguard Worker for option_string, action in conflicting_actions: 1634*cda5da8dSAndroid Build Coastguard Worker 1635*cda5da8dSAndroid Build Coastguard Worker # remove the conflicting option 1636*cda5da8dSAndroid Build Coastguard Worker action.option_strings.remove(option_string) 1637*cda5da8dSAndroid Build Coastguard Worker self._option_string_actions.pop(option_string, None) 1638*cda5da8dSAndroid Build Coastguard Worker 1639*cda5da8dSAndroid Build Coastguard Worker # if the option now has no option string, remove it from the 1640*cda5da8dSAndroid Build Coastguard Worker # container holding it 1641*cda5da8dSAndroid Build Coastguard Worker if not action.option_strings: 1642*cda5da8dSAndroid Build Coastguard Worker action.container._remove_action(action) 1643*cda5da8dSAndroid Build Coastguard Worker 1644*cda5da8dSAndroid Build Coastguard Worker 1645*cda5da8dSAndroid Build Coastguard Workerclass _ArgumentGroup(_ActionsContainer): 1646*cda5da8dSAndroid Build Coastguard Worker 1647*cda5da8dSAndroid Build Coastguard Worker def __init__(self, container, title=None, description=None, **kwargs): 1648*cda5da8dSAndroid Build Coastguard Worker # add any missing keyword arguments by checking the container 1649*cda5da8dSAndroid Build Coastguard Worker update = kwargs.setdefault 1650*cda5da8dSAndroid Build Coastguard Worker update('conflict_handler', container.conflict_handler) 1651*cda5da8dSAndroid Build Coastguard Worker update('prefix_chars', container.prefix_chars) 1652*cda5da8dSAndroid Build Coastguard Worker update('argument_default', container.argument_default) 1653*cda5da8dSAndroid Build Coastguard Worker super_init = super(_ArgumentGroup, self).__init__ 1654*cda5da8dSAndroid Build Coastguard Worker super_init(description=description, **kwargs) 1655*cda5da8dSAndroid Build Coastguard Worker 1656*cda5da8dSAndroid Build Coastguard Worker # group attributes 1657*cda5da8dSAndroid Build Coastguard Worker self.title = title 1658*cda5da8dSAndroid Build Coastguard Worker self._group_actions = [] 1659*cda5da8dSAndroid Build Coastguard Worker 1660*cda5da8dSAndroid Build Coastguard Worker # share most attributes with the container 1661*cda5da8dSAndroid Build Coastguard Worker self._registries = container._registries 1662*cda5da8dSAndroid Build Coastguard Worker self._actions = container._actions 1663*cda5da8dSAndroid Build Coastguard Worker self._option_string_actions = container._option_string_actions 1664*cda5da8dSAndroid Build Coastguard Worker self._defaults = container._defaults 1665*cda5da8dSAndroid Build Coastguard Worker self._has_negative_number_optionals = \ 1666*cda5da8dSAndroid Build Coastguard Worker container._has_negative_number_optionals 1667*cda5da8dSAndroid Build Coastguard Worker self._mutually_exclusive_groups = container._mutually_exclusive_groups 1668*cda5da8dSAndroid Build Coastguard Worker 1669*cda5da8dSAndroid Build Coastguard Worker def _add_action(self, action): 1670*cda5da8dSAndroid Build Coastguard Worker action = super(_ArgumentGroup, self)._add_action(action) 1671*cda5da8dSAndroid Build Coastguard Worker self._group_actions.append(action) 1672*cda5da8dSAndroid Build Coastguard Worker return action 1673*cda5da8dSAndroid Build Coastguard Worker 1674*cda5da8dSAndroid Build Coastguard Worker def _remove_action(self, action): 1675*cda5da8dSAndroid Build Coastguard Worker super(_ArgumentGroup, self)._remove_action(action) 1676*cda5da8dSAndroid Build Coastguard Worker self._group_actions.remove(action) 1677*cda5da8dSAndroid Build Coastguard Worker 1678*cda5da8dSAndroid Build Coastguard Worker def add_argument_group(self, *args, **kwargs): 1679*cda5da8dSAndroid Build Coastguard Worker warnings.warn( 1680*cda5da8dSAndroid Build Coastguard Worker "Nesting argument groups is deprecated.", 1681*cda5da8dSAndroid Build Coastguard Worker category=DeprecationWarning, 1682*cda5da8dSAndroid Build Coastguard Worker stacklevel=2 1683*cda5da8dSAndroid Build Coastguard Worker ) 1684*cda5da8dSAndroid Build Coastguard Worker return super().add_argument_group(*args, **kwargs) 1685*cda5da8dSAndroid Build Coastguard Worker 1686*cda5da8dSAndroid Build Coastguard Worker 1687*cda5da8dSAndroid Build Coastguard Workerclass _MutuallyExclusiveGroup(_ArgumentGroup): 1688*cda5da8dSAndroid Build Coastguard Worker 1689*cda5da8dSAndroid Build Coastguard Worker def __init__(self, container, required=False): 1690*cda5da8dSAndroid Build Coastguard Worker super(_MutuallyExclusiveGroup, self).__init__(container) 1691*cda5da8dSAndroid Build Coastguard Worker self.required = required 1692*cda5da8dSAndroid Build Coastguard Worker self._container = container 1693*cda5da8dSAndroid Build Coastguard Worker 1694*cda5da8dSAndroid Build Coastguard Worker def _add_action(self, action): 1695*cda5da8dSAndroid Build Coastguard Worker if action.required: 1696*cda5da8dSAndroid Build Coastguard Worker msg = _('mutually exclusive arguments must be optional') 1697*cda5da8dSAndroid Build Coastguard Worker raise ValueError(msg) 1698*cda5da8dSAndroid Build Coastguard Worker action = self._container._add_action(action) 1699*cda5da8dSAndroid Build Coastguard Worker self._group_actions.append(action) 1700*cda5da8dSAndroid Build Coastguard Worker return action 1701*cda5da8dSAndroid Build Coastguard Worker 1702*cda5da8dSAndroid Build Coastguard Worker def _remove_action(self, action): 1703*cda5da8dSAndroid Build Coastguard Worker self._container._remove_action(action) 1704*cda5da8dSAndroid Build Coastguard Worker self._group_actions.remove(action) 1705*cda5da8dSAndroid Build Coastguard Worker 1706*cda5da8dSAndroid Build Coastguard Worker def add_mutually_exclusive_group(self, *args, **kwargs): 1707*cda5da8dSAndroid Build Coastguard Worker warnings.warn( 1708*cda5da8dSAndroid Build Coastguard Worker "Nesting mutually exclusive groups is deprecated.", 1709*cda5da8dSAndroid Build Coastguard Worker category=DeprecationWarning, 1710*cda5da8dSAndroid Build Coastguard Worker stacklevel=2 1711*cda5da8dSAndroid Build Coastguard Worker ) 1712*cda5da8dSAndroid Build Coastguard Worker return super().add_mutually_exclusive_group(*args, **kwargs) 1713*cda5da8dSAndroid Build Coastguard Worker 1714*cda5da8dSAndroid Build Coastguard Worker 1715*cda5da8dSAndroid Build Coastguard Workerclass ArgumentParser(_AttributeHolder, _ActionsContainer): 1716*cda5da8dSAndroid Build Coastguard Worker """Object for parsing command line strings into Python objects. 1717*cda5da8dSAndroid Build Coastguard Worker 1718*cda5da8dSAndroid Build Coastguard Worker Keyword Arguments: 1719*cda5da8dSAndroid Build Coastguard Worker - prog -- The name of the program (default: 1720*cda5da8dSAndroid Build Coastguard Worker ``os.path.basename(sys.argv[0])``) 1721*cda5da8dSAndroid Build Coastguard Worker - usage -- A usage message (default: auto-generated from arguments) 1722*cda5da8dSAndroid Build Coastguard Worker - description -- A description of what the program does 1723*cda5da8dSAndroid Build Coastguard Worker - epilog -- Text following the argument descriptions 1724*cda5da8dSAndroid Build Coastguard Worker - parents -- Parsers whose arguments should be copied into this one 1725*cda5da8dSAndroid Build Coastguard Worker - formatter_class -- HelpFormatter class for printing help messages 1726*cda5da8dSAndroid Build Coastguard Worker - prefix_chars -- Characters that prefix optional arguments 1727*cda5da8dSAndroid Build Coastguard Worker - fromfile_prefix_chars -- Characters that prefix files containing 1728*cda5da8dSAndroid Build Coastguard Worker additional arguments 1729*cda5da8dSAndroid Build Coastguard Worker - argument_default -- The default value for all arguments 1730*cda5da8dSAndroid Build Coastguard Worker - conflict_handler -- String indicating how to handle conflicts 1731*cda5da8dSAndroid Build Coastguard Worker - add_help -- Add a -h/-help option 1732*cda5da8dSAndroid Build Coastguard Worker - allow_abbrev -- Allow long options to be abbreviated unambiguously 1733*cda5da8dSAndroid Build Coastguard Worker - exit_on_error -- Determines whether or not ArgumentParser exits with 1734*cda5da8dSAndroid Build Coastguard Worker error info when an error occurs 1735*cda5da8dSAndroid Build Coastguard Worker """ 1736*cda5da8dSAndroid Build Coastguard Worker 1737*cda5da8dSAndroid Build Coastguard Worker def __init__(self, 1738*cda5da8dSAndroid Build Coastguard Worker prog=None, 1739*cda5da8dSAndroid Build Coastguard Worker usage=None, 1740*cda5da8dSAndroid Build Coastguard Worker description=None, 1741*cda5da8dSAndroid Build Coastguard Worker epilog=None, 1742*cda5da8dSAndroid Build Coastguard Worker parents=[], 1743*cda5da8dSAndroid Build Coastguard Worker formatter_class=HelpFormatter, 1744*cda5da8dSAndroid Build Coastguard Worker prefix_chars='-', 1745*cda5da8dSAndroid Build Coastguard Worker fromfile_prefix_chars=None, 1746*cda5da8dSAndroid Build Coastguard Worker argument_default=None, 1747*cda5da8dSAndroid Build Coastguard Worker conflict_handler='error', 1748*cda5da8dSAndroid Build Coastguard Worker add_help=True, 1749*cda5da8dSAndroid Build Coastguard Worker allow_abbrev=True, 1750*cda5da8dSAndroid Build Coastguard Worker exit_on_error=True): 1751*cda5da8dSAndroid Build Coastguard Worker 1752*cda5da8dSAndroid Build Coastguard Worker superinit = super(ArgumentParser, self).__init__ 1753*cda5da8dSAndroid Build Coastguard Worker superinit(description=description, 1754*cda5da8dSAndroid Build Coastguard Worker prefix_chars=prefix_chars, 1755*cda5da8dSAndroid Build Coastguard Worker argument_default=argument_default, 1756*cda5da8dSAndroid Build Coastguard Worker conflict_handler=conflict_handler) 1757*cda5da8dSAndroid Build Coastguard Worker 1758*cda5da8dSAndroid Build Coastguard Worker # default setting for prog 1759*cda5da8dSAndroid Build Coastguard Worker if prog is None: 1760*cda5da8dSAndroid Build Coastguard Worker prog = _os.path.basename(_sys.argv[0]) 1761*cda5da8dSAndroid Build Coastguard Worker 1762*cda5da8dSAndroid Build Coastguard Worker self.prog = prog 1763*cda5da8dSAndroid Build Coastguard Worker self.usage = usage 1764*cda5da8dSAndroid Build Coastguard Worker self.epilog = epilog 1765*cda5da8dSAndroid Build Coastguard Worker self.formatter_class = formatter_class 1766*cda5da8dSAndroid Build Coastguard Worker self.fromfile_prefix_chars = fromfile_prefix_chars 1767*cda5da8dSAndroid Build Coastguard Worker self.add_help = add_help 1768*cda5da8dSAndroid Build Coastguard Worker self.allow_abbrev = allow_abbrev 1769*cda5da8dSAndroid Build Coastguard Worker self.exit_on_error = exit_on_error 1770*cda5da8dSAndroid Build Coastguard Worker 1771*cda5da8dSAndroid Build Coastguard Worker add_group = self.add_argument_group 1772*cda5da8dSAndroid Build Coastguard Worker self._positionals = add_group(_('positional arguments')) 1773*cda5da8dSAndroid Build Coastguard Worker self._optionals = add_group(_('options')) 1774*cda5da8dSAndroid Build Coastguard Worker self._subparsers = None 1775*cda5da8dSAndroid Build Coastguard Worker 1776*cda5da8dSAndroid Build Coastguard Worker # register types 1777*cda5da8dSAndroid Build Coastguard Worker def identity(string): 1778*cda5da8dSAndroid Build Coastguard Worker return string 1779*cda5da8dSAndroid Build Coastguard Worker self.register('type', None, identity) 1780*cda5da8dSAndroid Build Coastguard Worker 1781*cda5da8dSAndroid Build Coastguard Worker # add help argument if necessary 1782*cda5da8dSAndroid Build Coastguard Worker # (using explicit default to override global argument_default) 1783*cda5da8dSAndroid Build Coastguard Worker default_prefix = '-' if '-' in prefix_chars else prefix_chars[0] 1784*cda5da8dSAndroid Build Coastguard Worker if self.add_help: 1785*cda5da8dSAndroid Build Coastguard Worker self.add_argument( 1786*cda5da8dSAndroid Build Coastguard Worker default_prefix+'h', default_prefix*2+'help', 1787*cda5da8dSAndroid Build Coastguard Worker action='help', default=SUPPRESS, 1788*cda5da8dSAndroid Build Coastguard Worker help=_('show this help message and exit')) 1789*cda5da8dSAndroid Build Coastguard Worker 1790*cda5da8dSAndroid Build Coastguard Worker # add parent arguments and defaults 1791*cda5da8dSAndroid Build Coastguard Worker for parent in parents: 1792*cda5da8dSAndroid Build Coastguard Worker self._add_container_actions(parent) 1793*cda5da8dSAndroid Build Coastguard Worker try: 1794*cda5da8dSAndroid Build Coastguard Worker defaults = parent._defaults 1795*cda5da8dSAndroid Build Coastguard Worker except AttributeError: 1796*cda5da8dSAndroid Build Coastguard Worker pass 1797*cda5da8dSAndroid Build Coastguard Worker else: 1798*cda5da8dSAndroid Build Coastguard Worker self._defaults.update(defaults) 1799*cda5da8dSAndroid Build Coastguard Worker 1800*cda5da8dSAndroid Build Coastguard Worker # ======================= 1801*cda5da8dSAndroid Build Coastguard Worker # Pretty __repr__ methods 1802*cda5da8dSAndroid Build Coastguard Worker # ======================= 1803*cda5da8dSAndroid Build Coastguard Worker def _get_kwargs(self): 1804*cda5da8dSAndroid Build Coastguard Worker names = [ 1805*cda5da8dSAndroid Build Coastguard Worker 'prog', 1806*cda5da8dSAndroid Build Coastguard Worker 'usage', 1807*cda5da8dSAndroid Build Coastguard Worker 'description', 1808*cda5da8dSAndroid Build Coastguard Worker 'formatter_class', 1809*cda5da8dSAndroid Build Coastguard Worker 'conflict_handler', 1810*cda5da8dSAndroid Build Coastguard Worker 'add_help', 1811*cda5da8dSAndroid Build Coastguard Worker ] 1812*cda5da8dSAndroid Build Coastguard Worker return [(name, getattr(self, name)) for name in names] 1813*cda5da8dSAndroid Build Coastguard Worker 1814*cda5da8dSAndroid Build Coastguard Worker # ================================== 1815*cda5da8dSAndroid Build Coastguard Worker # Optional/Positional adding methods 1816*cda5da8dSAndroid Build Coastguard Worker # ================================== 1817*cda5da8dSAndroid Build Coastguard Worker def add_subparsers(self, **kwargs): 1818*cda5da8dSAndroid Build Coastguard Worker if self._subparsers is not None: 1819*cda5da8dSAndroid Build Coastguard Worker self.error(_('cannot have multiple subparser arguments')) 1820*cda5da8dSAndroid Build Coastguard Worker 1821*cda5da8dSAndroid Build Coastguard Worker # add the parser class to the arguments if it's not present 1822*cda5da8dSAndroid Build Coastguard Worker kwargs.setdefault('parser_class', type(self)) 1823*cda5da8dSAndroid Build Coastguard Worker 1824*cda5da8dSAndroid Build Coastguard Worker if 'title' in kwargs or 'description' in kwargs: 1825*cda5da8dSAndroid Build Coastguard Worker title = _(kwargs.pop('title', 'subcommands')) 1826*cda5da8dSAndroid Build Coastguard Worker description = _(kwargs.pop('description', None)) 1827*cda5da8dSAndroid Build Coastguard Worker self._subparsers = self.add_argument_group(title, description) 1828*cda5da8dSAndroid Build Coastguard Worker else: 1829*cda5da8dSAndroid Build Coastguard Worker self._subparsers = self._positionals 1830*cda5da8dSAndroid Build Coastguard Worker 1831*cda5da8dSAndroid Build Coastguard Worker # prog defaults to the usage message of this parser, skipping 1832*cda5da8dSAndroid Build Coastguard Worker # optional arguments and with no "usage:" prefix 1833*cda5da8dSAndroid Build Coastguard Worker if kwargs.get('prog') is None: 1834*cda5da8dSAndroid Build Coastguard Worker formatter = self._get_formatter() 1835*cda5da8dSAndroid Build Coastguard Worker positionals = self._get_positional_actions() 1836*cda5da8dSAndroid Build Coastguard Worker groups = self._mutually_exclusive_groups 1837*cda5da8dSAndroid Build Coastguard Worker formatter.add_usage(self.usage, positionals, groups, '') 1838*cda5da8dSAndroid Build Coastguard Worker kwargs['prog'] = formatter.format_help().strip() 1839*cda5da8dSAndroid Build Coastguard Worker 1840*cda5da8dSAndroid Build Coastguard Worker # create the parsers action and add it to the positionals list 1841*cda5da8dSAndroid Build Coastguard Worker parsers_class = self._pop_action_class(kwargs, 'parsers') 1842*cda5da8dSAndroid Build Coastguard Worker action = parsers_class(option_strings=[], **kwargs) 1843*cda5da8dSAndroid Build Coastguard Worker self._subparsers._add_action(action) 1844*cda5da8dSAndroid Build Coastguard Worker 1845*cda5da8dSAndroid Build Coastguard Worker # return the created parsers action 1846*cda5da8dSAndroid Build Coastguard Worker return action 1847*cda5da8dSAndroid Build Coastguard Worker 1848*cda5da8dSAndroid Build Coastguard Worker def _add_action(self, action): 1849*cda5da8dSAndroid Build Coastguard Worker if action.option_strings: 1850*cda5da8dSAndroid Build Coastguard Worker self._optionals._add_action(action) 1851*cda5da8dSAndroid Build Coastguard Worker else: 1852*cda5da8dSAndroid Build Coastguard Worker self._positionals._add_action(action) 1853*cda5da8dSAndroid Build Coastguard Worker return action 1854*cda5da8dSAndroid Build Coastguard Worker 1855*cda5da8dSAndroid Build Coastguard Worker def _get_optional_actions(self): 1856*cda5da8dSAndroid Build Coastguard Worker return [action 1857*cda5da8dSAndroid Build Coastguard Worker for action in self._actions 1858*cda5da8dSAndroid Build Coastguard Worker if action.option_strings] 1859*cda5da8dSAndroid Build Coastguard Worker 1860*cda5da8dSAndroid Build Coastguard Worker def _get_positional_actions(self): 1861*cda5da8dSAndroid Build Coastguard Worker return [action 1862*cda5da8dSAndroid Build Coastguard Worker for action in self._actions 1863*cda5da8dSAndroid Build Coastguard Worker if not action.option_strings] 1864*cda5da8dSAndroid Build Coastguard Worker 1865*cda5da8dSAndroid Build Coastguard Worker # ===================================== 1866*cda5da8dSAndroid Build Coastguard Worker # Command line argument parsing methods 1867*cda5da8dSAndroid Build Coastguard Worker # ===================================== 1868*cda5da8dSAndroid Build Coastguard Worker def parse_args(self, args=None, namespace=None): 1869*cda5da8dSAndroid Build Coastguard Worker args, argv = self.parse_known_args(args, namespace) 1870*cda5da8dSAndroid Build Coastguard Worker if argv: 1871*cda5da8dSAndroid Build Coastguard Worker msg = _('unrecognized arguments: %s') 1872*cda5da8dSAndroid Build Coastguard Worker self.error(msg % ' '.join(argv)) 1873*cda5da8dSAndroid Build Coastguard Worker return args 1874*cda5da8dSAndroid Build Coastguard Worker 1875*cda5da8dSAndroid Build Coastguard Worker def parse_known_args(self, args=None, namespace=None): 1876*cda5da8dSAndroid Build Coastguard Worker if args is None: 1877*cda5da8dSAndroid Build Coastguard Worker # args default to the system args 1878*cda5da8dSAndroid Build Coastguard Worker args = _sys.argv[1:] 1879*cda5da8dSAndroid Build Coastguard Worker else: 1880*cda5da8dSAndroid Build Coastguard Worker # make sure that args are mutable 1881*cda5da8dSAndroid Build Coastguard Worker args = list(args) 1882*cda5da8dSAndroid Build Coastguard Worker 1883*cda5da8dSAndroid Build Coastguard Worker # default Namespace built from parser defaults 1884*cda5da8dSAndroid Build Coastguard Worker if namespace is None: 1885*cda5da8dSAndroid Build Coastguard Worker namespace = Namespace() 1886*cda5da8dSAndroid Build Coastguard Worker 1887*cda5da8dSAndroid Build Coastguard Worker # add any action defaults that aren't present 1888*cda5da8dSAndroid Build Coastguard Worker for action in self._actions: 1889*cda5da8dSAndroid Build Coastguard Worker if action.dest is not SUPPRESS: 1890*cda5da8dSAndroid Build Coastguard Worker if not hasattr(namespace, action.dest): 1891*cda5da8dSAndroid Build Coastguard Worker if action.default is not SUPPRESS: 1892*cda5da8dSAndroid Build Coastguard Worker setattr(namespace, action.dest, action.default) 1893*cda5da8dSAndroid Build Coastguard Worker 1894*cda5da8dSAndroid Build Coastguard Worker # add any parser defaults that aren't present 1895*cda5da8dSAndroid Build Coastguard Worker for dest in self._defaults: 1896*cda5da8dSAndroid Build Coastguard Worker if not hasattr(namespace, dest): 1897*cda5da8dSAndroid Build Coastguard Worker setattr(namespace, dest, self._defaults[dest]) 1898*cda5da8dSAndroid Build Coastguard Worker 1899*cda5da8dSAndroid Build Coastguard Worker # parse the arguments and exit if there are any errors 1900*cda5da8dSAndroid Build Coastguard Worker if self.exit_on_error: 1901*cda5da8dSAndroid Build Coastguard Worker try: 1902*cda5da8dSAndroid Build Coastguard Worker namespace, args = self._parse_known_args(args, namespace) 1903*cda5da8dSAndroid Build Coastguard Worker except ArgumentError as err: 1904*cda5da8dSAndroid Build Coastguard Worker self.error(str(err)) 1905*cda5da8dSAndroid Build Coastguard Worker else: 1906*cda5da8dSAndroid Build Coastguard Worker namespace, args = self._parse_known_args(args, namespace) 1907*cda5da8dSAndroid Build Coastguard Worker 1908*cda5da8dSAndroid Build Coastguard Worker if hasattr(namespace, _UNRECOGNIZED_ARGS_ATTR): 1909*cda5da8dSAndroid Build Coastguard Worker args.extend(getattr(namespace, _UNRECOGNIZED_ARGS_ATTR)) 1910*cda5da8dSAndroid Build Coastguard Worker delattr(namespace, _UNRECOGNIZED_ARGS_ATTR) 1911*cda5da8dSAndroid Build Coastguard Worker return namespace, args 1912*cda5da8dSAndroid Build Coastguard Worker 1913*cda5da8dSAndroid Build Coastguard Worker def _parse_known_args(self, arg_strings, namespace): 1914*cda5da8dSAndroid Build Coastguard Worker # replace arg strings that are file references 1915*cda5da8dSAndroid Build Coastguard Worker if self.fromfile_prefix_chars is not None: 1916*cda5da8dSAndroid Build Coastguard Worker arg_strings = self._read_args_from_files(arg_strings) 1917*cda5da8dSAndroid Build Coastguard Worker 1918*cda5da8dSAndroid Build Coastguard Worker # map all mutually exclusive arguments to the other arguments 1919*cda5da8dSAndroid Build Coastguard Worker # they can't occur with 1920*cda5da8dSAndroid Build Coastguard Worker action_conflicts = {} 1921*cda5da8dSAndroid Build Coastguard Worker for mutex_group in self._mutually_exclusive_groups: 1922*cda5da8dSAndroid Build Coastguard Worker group_actions = mutex_group._group_actions 1923*cda5da8dSAndroid Build Coastguard Worker for i, mutex_action in enumerate(mutex_group._group_actions): 1924*cda5da8dSAndroid Build Coastguard Worker conflicts = action_conflicts.setdefault(mutex_action, []) 1925*cda5da8dSAndroid Build Coastguard Worker conflicts.extend(group_actions[:i]) 1926*cda5da8dSAndroid Build Coastguard Worker conflicts.extend(group_actions[i + 1:]) 1927*cda5da8dSAndroid Build Coastguard Worker 1928*cda5da8dSAndroid Build Coastguard Worker # find all option indices, and determine the arg_string_pattern 1929*cda5da8dSAndroid Build Coastguard Worker # which has an 'O' if there is an option at an index, 1930*cda5da8dSAndroid Build Coastguard Worker # an 'A' if there is an argument, or a '-' if there is a '--' 1931*cda5da8dSAndroid Build Coastguard Worker option_string_indices = {} 1932*cda5da8dSAndroid Build Coastguard Worker arg_string_pattern_parts = [] 1933*cda5da8dSAndroid Build Coastguard Worker arg_strings_iter = iter(arg_strings) 1934*cda5da8dSAndroid Build Coastguard Worker for i, arg_string in enumerate(arg_strings_iter): 1935*cda5da8dSAndroid Build Coastguard Worker 1936*cda5da8dSAndroid Build Coastguard Worker # all args after -- are non-options 1937*cda5da8dSAndroid Build Coastguard Worker if arg_string == '--': 1938*cda5da8dSAndroid Build Coastguard Worker arg_string_pattern_parts.append('-') 1939*cda5da8dSAndroid Build Coastguard Worker for arg_string in arg_strings_iter: 1940*cda5da8dSAndroid Build Coastguard Worker arg_string_pattern_parts.append('A') 1941*cda5da8dSAndroid Build Coastguard Worker 1942*cda5da8dSAndroid Build Coastguard Worker # otherwise, add the arg to the arg strings 1943*cda5da8dSAndroid Build Coastguard Worker # and note the index if it was an option 1944*cda5da8dSAndroid Build Coastguard Worker else: 1945*cda5da8dSAndroid Build Coastguard Worker option_tuple = self._parse_optional(arg_string) 1946*cda5da8dSAndroid Build Coastguard Worker if option_tuple is None: 1947*cda5da8dSAndroid Build Coastguard Worker pattern = 'A' 1948*cda5da8dSAndroid Build Coastguard Worker else: 1949*cda5da8dSAndroid Build Coastguard Worker option_string_indices[i] = option_tuple 1950*cda5da8dSAndroid Build Coastguard Worker pattern = 'O' 1951*cda5da8dSAndroid Build Coastguard Worker arg_string_pattern_parts.append(pattern) 1952*cda5da8dSAndroid Build Coastguard Worker 1953*cda5da8dSAndroid Build Coastguard Worker # join the pieces together to form the pattern 1954*cda5da8dSAndroid Build Coastguard Worker arg_strings_pattern = ''.join(arg_string_pattern_parts) 1955*cda5da8dSAndroid Build Coastguard Worker 1956*cda5da8dSAndroid Build Coastguard Worker # converts arg strings to the appropriate and then takes the action 1957*cda5da8dSAndroid Build Coastguard Worker seen_actions = set() 1958*cda5da8dSAndroid Build Coastguard Worker seen_non_default_actions = set() 1959*cda5da8dSAndroid Build Coastguard Worker 1960*cda5da8dSAndroid Build Coastguard Worker def take_action(action, argument_strings, option_string=None): 1961*cda5da8dSAndroid Build Coastguard Worker seen_actions.add(action) 1962*cda5da8dSAndroid Build Coastguard Worker argument_values = self._get_values(action, argument_strings) 1963*cda5da8dSAndroid Build Coastguard Worker 1964*cda5da8dSAndroid Build Coastguard Worker # error if this argument is not allowed with other previously 1965*cda5da8dSAndroid Build Coastguard Worker # seen arguments, assuming that actions that use the default 1966*cda5da8dSAndroid Build Coastguard Worker # value don't really count as "present" 1967*cda5da8dSAndroid Build Coastguard Worker if argument_values is not action.default: 1968*cda5da8dSAndroid Build Coastguard Worker seen_non_default_actions.add(action) 1969*cda5da8dSAndroid Build Coastguard Worker for conflict_action in action_conflicts.get(action, []): 1970*cda5da8dSAndroid Build Coastguard Worker if conflict_action in seen_non_default_actions: 1971*cda5da8dSAndroid Build Coastguard Worker msg = _('not allowed with argument %s') 1972*cda5da8dSAndroid Build Coastguard Worker action_name = _get_action_name(conflict_action) 1973*cda5da8dSAndroid Build Coastguard Worker raise ArgumentError(action, msg % action_name) 1974*cda5da8dSAndroid Build Coastguard Worker 1975*cda5da8dSAndroid Build Coastguard Worker # take the action if we didn't receive a SUPPRESS value 1976*cda5da8dSAndroid Build Coastguard Worker # (e.g. from a default) 1977*cda5da8dSAndroid Build Coastguard Worker if argument_values is not SUPPRESS: 1978*cda5da8dSAndroid Build Coastguard Worker action(self, namespace, argument_values, option_string) 1979*cda5da8dSAndroid Build Coastguard Worker 1980*cda5da8dSAndroid Build Coastguard Worker # function to convert arg_strings into an optional action 1981*cda5da8dSAndroid Build Coastguard Worker def consume_optional(start_index): 1982*cda5da8dSAndroid Build Coastguard Worker 1983*cda5da8dSAndroid Build Coastguard Worker # get the optional identified at this index 1984*cda5da8dSAndroid Build Coastguard Worker option_tuple = option_string_indices[start_index] 1985*cda5da8dSAndroid Build Coastguard Worker action, option_string, explicit_arg = option_tuple 1986*cda5da8dSAndroid Build Coastguard Worker 1987*cda5da8dSAndroid Build Coastguard Worker # identify additional optionals in the same arg string 1988*cda5da8dSAndroid Build Coastguard Worker # (e.g. -xyz is the same as -x -y -z if no args are required) 1989*cda5da8dSAndroid Build Coastguard Worker match_argument = self._match_argument 1990*cda5da8dSAndroid Build Coastguard Worker action_tuples = [] 1991*cda5da8dSAndroid Build Coastguard Worker while True: 1992*cda5da8dSAndroid Build Coastguard Worker 1993*cda5da8dSAndroid Build Coastguard Worker # if we found no optional action, skip it 1994*cda5da8dSAndroid Build Coastguard Worker if action is None: 1995*cda5da8dSAndroid Build Coastguard Worker extras.append(arg_strings[start_index]) 1996*cda5da8dSAndroid Build Coastguard Worker return start_index + 1 1997*cda5da8dSAndroid Build Coastguard Worker 1998*cda5da8dSAndroid Build Coastguard Worker # if there is an explicit argument, try to match the 1999*cda5da8dSAndroid Build Coastguard Worker # optional's string arguments to only this 2000*cda5da8dSAndroid Build Coastguard Worker if explicit_arg is not None: 2001*cda5da8dSAndroid Build Coastguard Worker arg_count = match_argument(action, 'A') 2002*cda5da8dSAndroid Build Coastguard Worker 2003*cda5da8dSAndroid Build Coastguard Worker # if the action is a single-dash option and takes no 2004*cda5da8dSAndroid Build Coastguard Worker # arguments, try to parse more single-dash options out 2005*cda5da8dSAndroid Build Coastguard Worker # of the tail of the option string 2006*cda5da8dSAndroid Build Coastguard Worker chars = self.prefix_chars 2007*cda5da8dSAndroid Build Coastguard Worker if ( 2008*cda5da8dSAndroid Build Coastguard Worker arg_count == 0 2009*cda5da8dSAndroid Build Coastguard Worker and option_string[1] not in chars 2010*cda5da8dSAndroid Build Coastguard Worker and explicit_arg != '' 2011*cda5da8dSAndroid Build Coastguard Worker ): 2012*cda5da8dSAndroid Build Coastguard Worker action_tuples.append((action, [], option_string)) 2013*cda5da8dSAndroid Build Coastguard Worker char = option_string[0] 2014*cda5da8dSAndroid Build Coastguard Worker option_string = char + explicit_arg[0] 2015*cda5da8dSAndroid Build Coastguard Worker new_explicit_arg = explicit_arg[1:] or None 2016*cda5da8dSAndroid Build Coastguard Worker optionals_map = self._option_string_actions 2017*cda5da8dSAndroid Build Coastguard Worker if option_string in optionals_map: 2018*cda5da8dSAndroid Build Coastguard Worker action = optionals_map[option_string] 2019*cda5da8dSAndroid Build Coastguard Worker explicit_arg = new_explicit_arg 2020*cda5da8dSAndroid Build Coastguard Worker else: 2021*cda5da8dSAndroid Build Coastguard Worker msg = _('ignored explicit argument %r') 2022*cda5da8dSAndroid Build Coastguard Worker raise ArgumentError(action, msg % explicit_arg) 2023*cda5da8dSAndroid Build Coastguard Worker 2024*cda5da8dSAndroid Build Coastguard Worker # if the action expect exactly one argument, we've 2025*cda5da8dSAndroid Build Coastguard Worker # successfully matched the option; exit the loop 2026*cda5da8dSAndroid Build Coastguard Worker elif arg_count == 1: 2027*cda5da8dSAndroid Build Coastguard Worker stop = start_index + 1 2028*cda5da8dSAndroid Build Coastguard Worker args = [explicit_arg] 2029*cda5da8dSAndroid Build Coastguard Worker action_tuples.append((action, args, option_string)) 2030*cda5da8dSAndroid Build Coastguard Worker break 2031*cda5da8dSAndroid Build Coastguard Worker 2032*cda5da8dSAndroid Build Coastguard Worker # error if a double-dash option did not use the 2033*cda5da8dSAndroid Build Coastguard Worker # explicit argument 2034*cda5da8dSAndroid Build Coastguard Worker else: 2035*cda5da8dSAndroid Build Coastguard Worker msg = _('ignored explicit argument %r') 2036*cda5da8dSAndroid Build Coastguard Worker raise ArgumentError(action, msg % explicit_arg) 2037*cda5da8dSAndroid Build Coastguard Worker 2038*cda5da8dSAndroid Build Coastguard Worker # if there is no explicit argument, try to match the 2039*cda5da8dSAndroid Build Coastguard Worker # optional's string arguments with the following strings 2040*cda5da8dSAndroid Build Coastguard Worker # if successful, exit the loop 2041*cda5da8dSAndroid Build Coastguard Worker else: 2042*cda5da8dSAndroid Build Coastguard Worker start = start_index + 1 2043*cda5da8dSAndroid Build Coastguard Worker selected_patterns = arg_strings_pattern[start:] 2044*cda5da8dSAndroid Build Coastguard Worker arg_count = match_argument(action, selected_patterns) 2045*cda5da8dSAndroid Build Coastguard Worker stop = start + arg_count 2046*cda5da8dSAndroid Build Coastguard Worker args = arg_strings[start:stop] 2047*cda5da8dSAndroid Build Coastguard Worker action_tuples.append((action, args, option_string)) 2048*cda5da8dSAndroid Build Coastguard Worker break 2049*cda5da8dSAndroid Build Coastguard Worker 2050*cda5da8dSAndroid Build Coastguard Worker # add the Optional to the list and return the index at which 2051*cda5da8dSAndroid Build Coastguard Worker # the Optional's string args stopped 2052*cda5da8dSAndroid Build Coastguard Worker assert action_tuples 2053*cda5da8dSAndroid Build Coastguard Worker for action, args, option_string in action_tuples: 2054*cda5da8dSAndroid Build Coastguard Worker take_action(action, args, option_string) 2055*cda5da8dSAndroid Build Coastguard Worker return stop 2056*cda5da8dSAndroid Build Coastguard Worker 2057*cda5da8dSAndroid Build Coastguard Worker # the list of Positionals left to be parsed; this is modified 2058*cda5da8dSAndroid Build Coastguard Worker # by consume_positionals() 2059*cda5da8dSAndroid Build Coastguard Worker positionals = self._get_positional_actions() 2060*cda5da8dSAndroid Build Coastguard Worker 2061*cda5da8dSAndroid Build Coastguard Worker # function to convert arg_strings into positional actions 2062*cda5da8dSAndroid Build Coastguard Worker def consume_positionals(start_index): 2063*cda5da8dSAndroid Build Coastguard Worker # match as many Positionals as possible 2064*cda5da8dSAndroid Build Coastguard Worker match_partial = self._match_arguments_partial 2065*cda5da8dSAndroid Build Coastguard Worker selected_pattern = arg_strings_pattern[start_index:] 2066*cda5da8dSAndroid Build Coastguard Worker arg_counts = match_partial(positionals, selected_pattern) 2067*cda5da8dSAndroid Build Coastguard Worker 2068*cda5da8dSAndroid Build Coastguard Worker # slice off the appropriate arg strings for each Positional 2069*cda5da8dSAndroid Build Coastguard Worker # and add the Positional and its args to the list 2070*cda5da8dSAndroid Build Coastguard Worker for action, arg_count in zip(positionals, arg_counts): 2071*cda5da8dSAndroid Build Coastguard Worker args = arg_strings[start_index: start_index + arg_count] 2072*cda5da8dSAndroid Build Coastguard Worker start_index += arg_count 2073*cda5da8dSAndroid Build Coastguard Worker take_action(action, args) 2074*cda5da8dSAndroid Build Coastguard Worker 2075*cda5da8dSAndroid Build Coastguard Worker # slice off the Positionals that we just parsed and return the 2076*cda5da8dSAndroid Build Coastguard Worker # index at which the Positionals' string args stopped 2077*cda5da8dSAndroid Build Coastguard Worker positionals[:] = positionals[len(arg_counts):] 2078*cda5da8dSAndroid Build Coastguard Worker return start_index 2079*cda5da8dSAndroid Build Coastguard Worker 2080*cda5da8dSAndroid Build Coastguard Worker # consume Positionals and Optionals alternately, until we have 2081*cda5da8dSAndroid Build Coastguard Worker # passed the last option string 2082*cda5da8dSAndroid Build Coastguard Worker extras = [] 2083*cda5da8dSAndroid Build Coastguard Worker start_index = 0 2084*cda5da8dSAndroid Build Coastguard Worker if option_string_indices: 2085*cda5da8dSAndroid Build Coastguard Worker max_option_string_index = max(option_string_indices) 2086*cda5da8dSAndroid Build Coastguard Worker else: 2087*cda5da8dSAndroid Build Coastguard Worker max_option_string_index = -1 2088*cda5da8dSAndroid Build Coastguard Worker while start_index <= max_option_string_index: 2089*cda5da8dSAndroid Build Coastguard Worker 2090*cda5da8dSAndroid Build Coastguard Worker # consume any Positionals preceding the next option 2091*cda5da8dSAndroid Build Coastguard Worker next_option_string_index = min([ 2092*cda5da8dSAndroid Build Coastguard Worker index 2093*cda5da8dSAndroid Build Coastguard Worker for index in option_string_indices 2094*cda5da8dSAndroid Build Coastguard Worker if index >= start_index]) 2095*cda5da8dSAndroid Build Coastguard Worker if start_index != next_option_string_index: 2096*cda5da8dSAndroid Build Coastguard Worker positionals_end_index = consume_positionals(start_index) 2097*cda5da8dSAndroid Build Coastguard Worker 2098*cda5da8dSAndroid Build Coastguard Worker # only try to parse the next optional if we didn't consume 2099*cda5da8dSAndroid Build Coastguard Worker # the option string during the positionals parsing 2100*cda5da8dSAndroid Build Coastguard Worker if positionals_end_index > start_index: 2101*cda5da8dSAndroid Build Coastguard Worker start_index = positionals_end_index 2102*cda5da8dSAndroid Build Coastguard Worker continue 2103*cda5da8dSAndroid Build Coastguard Worker else: 2104*cda5da8dSAndroid Build Coastguard Worker start_index = positionals_end_index 2105*cda5da8dSAndroid Build Coastguard Worker 2106*cda5da8dSAndroid Build Coastguard Worker # if we consumed all the positionals we could and we're not 2107*cda5da8dSAndroid Build Coastguard Worker # at the index of an option string, there were extra arguments 2108*cda5da8dSAndroid Build Coastguard Worker if start_index not in option_string_indices: 2109*cda5da8dSAndroid Build Coastguard Worker strings = arg_strings[start_index:next_option_string_index] 2110*cda5da8dSAndroid Build Coastguard Worker extras.extend(strings) 2111*cda5da8dSAndroid Build Coastguard Worker start_index = next_option_string_index 2112*cda5da8dSAndroid Build Coastguard Worker 2113*cda5da8dSAndroid Build Coastguard Worker # consume the next optional and any arguments for it 2114*cda5da8dSAndroid Build Coastguard Worker start_index = consume_optional(start_index) 2115*cda5da8dSAndroid Build Coastguard Worker 2116*cda5da8dSAndroid Build Coastguard Worker # consume any positionals following the last Optional 2117*cda5da8dSAndroid Build Coastguard Worker stop_index = consume_positionals(start_index) 2118*cda5da8dSAndroid Build Coastguard Worker 2119*cda5da8dSAndroid Build Coastguard Worker # if we didn't consume all the argument strings, there were extras 2120*cda5da8dSAndroid Build Coastguard Worker extras.extend(arg_strings[stop_index:]) 2121*cda5da8dSAndroid Build Coastguard Worker 2122*cda5da8dSAndroid Build Coastguard Worker # make sure all required actions were present and also convert 2123*cda5da8dSAndroid Build Coastguard Worker # action defaults which were not given as arguments 2124*cda5da8dSAndroid Build Coastguard Worker required_actions = [] 2125*cda5da8dSAndroid Build Coastguard Worker for action in self._actions: 2126*cda5da8dSAndroid Build Coastguard Worker if action not in seen_actions: 2127*cda5da8dSAndroid Build Coastguard Worker if action.required: 2128*cda5da8dSAndroid Build Coastguard Worker required_actions.append(_get_action_name(action)) 2129*cda5da8dSAndroid Build Coastguard Worker else: 2130*cda5da8dSAndroid Build Coastguard Worker # Convert action default now instead of doing it before 2131*cda5da8dSAndroid Build Coastguard Worker # parsing arguments to avoid calling convert functions 2132*cda5da8dSAndroid Build Coastguard Worker # twice (which may fail) if the argument was given, but 2133*cda5da8dSAndroid Build Coastguard Worker # only if it was defined already in the namespace 2134*cda5da8dSAndroid Build Coastguard Worker if (action.default is not None and 2135*cda5da8dSAndroid Build Coastguard Worker isinstance(action.default, str) and 2136*cda5da8dSAndroid Build Coastguard Worker hasattr(namespace, action.dest) and 2137*cda5da8dSAndroid Build Coastguard Worker action.default is getattr(namespace, action.dest)): 2138*cda5da8dSAndroid Build Coastguard Worker setattr(namespace, action.dest, 2139*cda5da8dSAndroid Build Coastguard Worker self._get_value(action, action.default)) 2140*cda5da8dSAndroid Build Coastguard Worker 2141*cda5da8dSAndroid Build Coastguard Worker if required_actions: 2142*cda5da8dSAndroid Build Coastguard Worker self.error(_('the following arguments are required: %s') % 2143*cda5da8dSAndroid Build Coastguard Worker ', '.join(required_actions)) 2144*cda5da8dSAndroid Build Coastguard Worker 2145*cda5da8dSAndroid Build Coastguard Worker # make sure all required groups had one option present 2146*cda5da8dSAndroid Build Coastguard Worker for group in self._mutually_exclusive_groups: 2147*cda5da8dSAndroid Build Coastguard Worker if group.required: 2148*cda5da8dSAndroid Build Coastguard Worker for action in group._group_actions: 2149*cda5da8dSAndroid Build Coastguard Worker if action in seen_non_default_actions: 2150*cda5da8dSAndroid Build Coastguard Worker break 2151*cda5da8dSAndroid Build Coastguard Worker 2152*cda5da8dSAndroid Build Coastguard Worker # if no actions were used, report the error 2153*cda5da8dSAndroid Build Coastguard Worker else: 2154*cda5da8dSAndroid Build Coastguard Worker names = [_get_action_name(action) 2155*cda5da8dSAndroid Build Coastguard Worker for action in group._group_actions 2156*cda5da8dSAndroid Build Coastguard Worker if action.help is not SUPPRESS] 2157*cda5da8dSAndroid Build Coastguard Worker msg = _('one of the arguments %s is required') 2158*cda5da8dSAndroid Build Coastguard Worker self.error(msg % ' '.join(names)) 2159*cda5da8dSAndroid Build Coastguard Worker 2160*cda5da8dSAndroid Build Coastguard Worker # return the updated namespace and the extra arguments 2161*cda5da8dSAndroid Build Coastguard Worker return namespace, extras 2162*cda5da8dSAndroid Build Coastguard Worker 2163*cda5da8dSAndroid Build Coastguard Worker def _read_args_from_files(self, arg_strings): 2164*cda5da8dSAndroid Build Coastguard Worker # expand arguments referencing files 2165*cda5da8dSAndroid Build Coastguard Worker new_arg_strings = [] 2166*cda5da8dSAndroid Build Coastguard Worker for arg_string in arg_strings: 2167*cda5da8dSAndroid Build Coastguard Worker 2168*cda5da8dSAndroid Build Coastguard Worker # for regular arguments, just add them back into the list 2169*cda5da8dSAndroid Build Coastguard Worker if not arg_string or arg_string[0] not in self.fromfile_prefix_chars: 2170*cda5da8dSAndroid Build Coastguard Worker new_arg_strings.append(arg_string) 2171*cda5da8dSAndroid Build Coastguard Worker 2172*cda5da8dSAndroid Build Coastguard Worker # replace arguments referencing files with the file content 2173*cda5da8dSAndroid Build Coastguard Worker else: 2174*cda5da8dSAndroid Build Coastguard Worker try: 2175*cda5da8dSAndroid Build Coastguard Worker with open(arg_string[1:]) as args_file: 2176*cda5da8dSAndroid Build Coastguard Worker arg_strings = [] 2177*cda5da8dSAndroid Build Coastguard Worker for arg_line in args_file.read().splitlines(): 2178*cda5da8dSAndroid Build Coastguard Worker for arg in self.convert_arg_line_to_args(arg_line): 2179*cda5da8dSAndroid Build Coastguard Worker arg_strings.append(arg) 2180*cda5da8dSAndroid Build Coastguard Worker arg_strings = self._read_args_from_files(arg_strings) 2181*cda5da8dSAndroid Build Coastguard Worker new_arg_strings.extend(arg_strings) 2182*cda5da8dSAndroid Build Coastguard Worker except OSError as err: 2183*cda5da8dSAndroid Build Coastguard Worker self.error(str(err)) 2184*cda5da8dSAndroid Build Coastguard Worker 2185*cda5da8dSAndroid Build Coastguard Worker # return the modified argument list 2186*cda5da8dSAndroid Build Coastguard Worker return new_arg_strings 2187*cda5da8dSAndroid Build Coastguard Worker 2188*cda5da8dSAndroid Build Coastguard Worker def convert_arg_line_to_args(self, arg_line): 2189*cda5da8dSAndroid Build Coastguard Worker return [arg_line] 2190*cda5da8dSAndroid Build Coastguard Worker 2191*cda5da8dSAndroid Build Coastguard Worker def _match_argument(self, action, arg_strings_pattern): 2192*cda5da8dSAndroid Build Coastguard Worker # match the pattern for this action to the arg strings 2193*cda5da8dSAndroid Build Coastguard Worker nargs_pattern = self._get_nargs_pattern(action) 2194*cda5da8dSAndroid Build Coastguard Worker match = _re.match(nargs_pattern, arg_strings_pattern) 2195*cda5da8dSAndroid Build Coastguard Worker 2196*cda5da8dSAndroid Build Coastguard Worker # raise an exception if we weren't able to find a match 2197*cda5da8dSAndroid Build Coastguard Worker if match is None: 2198*cda5da8dSAndroid Build Coastguard Worker nargs_errors = { 2199*cda5da8dSAndroid Build Coastguard Worker None: _('expected one argument'), 2200*cda5da8dSAndroid Build Coastguard Worker OPTIONAL: _('expected at most one argument'), 2201*cda5da8dSAndroid Build Coastguard Worker ONE_OR_MORE: _('expected at least one argument'), 2202*cda5da8dSAndroid Build Coastguard Worker } 2203*cda5da8dSAndroid Build Coastguard Worker msg = nargs_errors.get(action.nargs) 2204*cda5da8dSAndroid Build Coastguard Worker if msg is None: 2205*cda5da8dSAndroid Build Coastguard Worker msg = ngettext('expected %s argument', 2206*cda5da8dSAndroid Build Coastguard Worker 'expected %s arguments', 2207*cda5da8dSAndroid Build Coastguard Worker action.nargs) % action.nargs 2208*cda5da8dSAndroid Build Coastguard Worker raise ArgumentError(action, msg) 2209*cda5da8dSAndroid Build Coastguard Worker 2210*cda5da8dSAndroid Build Coastguard Worker # return the number of arguments matched 2211*cda5da8dSAndroid Build Coastguard Worker return len(match.group(1)) 2212*cda5da8dSAndroid Build Coastguard Worker 2213*cda5da8dSAndroid Build Coastguard Worker def _match_arguments_partial(self, actions, arg_strings_pattern): 2214*cda5da8dSAndroid Build Coastguard Worker # progressively shorten the actions list by slicing off the 2215*cda5da8dSAndroid Build Coastguard Worker # final actions until we find a match 2216*cda5da8dSAndroid Build Coastguard Worker result = [] 2217*cda5da8dSAndroid Build Coastguard Worker for i in range(len(actions), 0, -1): 2218*cda5da8dSAndroid Build Coastguard Worker actions_slice = actions[:i] 2219*cda5da8dSAndroid Build Coastguard Worker pattern = ''.join([self._get_nargs_pattern(action) 2220*cda5da8dSAndroid Build Coastguard Worker for action in actions_slice]) 2221*cda5da8dSAndroid Build Coastguard Worker match = _re.match(pattern, arg_strings_pattern) 2222*cda5da8dSAndroid Build Coastguard Worker if match is not None: 2223*cda5da8dSAndroid Build Coastguard Worker result.extend([len(string) for string in match.groups()]) 2224*cda5da8dSAndroid Build Coastguard Worker break 2225*cda5da8dSAndroid Build Coastguard Worker 2226*cda5da8dSAndroid Build Coastguard Worker # return the list of arg string counts 2227*cda5da8dSAndroid Build Coastguard Worker return result 2228*cda5da8dSAndroid Build Coastguard Worker 2229*cda5da8dSAndroid Build Coastguard Worker def _parse_optional(self, arg_string): 2230*cda5da8dSAndroid Build Coastguard Worker # if it's an empty string, it was meant to be a positional 2231*cda5da8dSAndroid Build Coastguard Worker if not arg_string: 2232*cda5da8dSAndroid Build Coastguard Worker return None 2233*cda5da8dSAndroid Build Coastguard Worker 2234*cda5da8dSAndroid Build Coastguard Worker # if it doesn't start with a prefix, it was meant to be positional 2235*cda5da8dSAndroid Build Coastguard Worker if not arg_string[0] in self.prefix_chars: 2236*cda5da8dSAndroid Build Coastguard Worker return None 2237*cda5da8dSAndroid Build Coastguard Worker 2238*cda5da8dSAndroid Build Coastguard Worker # if the option string is present in the parser, return the action 2239*cda5da8dSAndroid Build Coastguard Worker if arg_string in self._option_string_actions: 2240*cda5da8dSAndroid Build Coastguard Worker action = self._option_string_actions[arg_string] 2241*cda5da8dSAndroid Build Coastguard Worker return action, arg_string, None 2242*cda5da8dSAndroid Build Coastguard Worker 2243*cda5da8dSAndroid Build Coastguard Worker # if it's just a single character, it was meant to be positional 2244*cda5da8dSAndroid Build Coastguard Worker if len(arg_string) == 1: 2245*cda5da8dSAndroid Build Coastguard Worker return None 2246*cda5da8dSAndroid Build Coastguard Worker 2247*cda5da8dSAndroid Build Coastguard Worker # if the option string before the "=" is present, return the action 2248*cda5da8dSAndroid Build Coastguard Worker if '=' in arg_string: 2249*cda5da8dSAndroid Build Coastguard Worker option_string, explicit_arg = arg_string.split('=', 1) 2250*cda5da8dSAndroid Build Coastguard Worker if option_string in self._option_string_actions: 2251*cda5da8dSAndroid Build Coastguard Worker action = self._option_string_actions[option_string] 2252*cda5da8dSAndroid Build Coastguard Worker return action, option_string, explicit_arg 2253*cda5da8dSAndroid Build Coastguard Worker 2254*cda5da8dSAndroid Build Coastguard Worker # search through all possible prefixes of the option string 2255*cda5da8dSAndroid Build Coastguard Worker # and all actions in the parser for possible interpretations 2256*cda5da8dSAndroid Build Coastguard Worker option_tuples = self._get_option_tuples(arg_string) 2257*cda5da8dSAndroid Build Coastguard Worker 2258*cda5da8dSAndroid Build Coastguard Worker # if multiple actions match, the option string was ambiguous 2259*cda5da8dSAndroid Build Coastguard Worker if len(option_tuples) > 1: 2260*cda5da8dSAndroid Build Coastguard Worker options = ', '.join([option_string 2261*cda5da8dSAndroid Build Coastguard Worker for action, option_string, explicit_arg in option_tuples]) 2262*cda5da8dSAndroid Build Coastguard Worker args = {'option': arg_string, 'matches': options} 2263*cda5da8dSAndroid Build Coastguard Worker msg = _('ambiguous option: %(option)s could match %(matches)s') 2264*cda5da8dSAndroid Build Coastguard Worker self.error(msg % args) 2265*cda5da8dSAndroid Build Coastguard Worker 2266*cda5da8dSAndroid Build Coastguard Worker # if exactly one action matched, this segmentation is good, 2267*cda5da8dSAndroid Build Coastguard Worker # so return the parsed action 2268*cda5da8dSAndroid Build Coastguard Worker elif len(option_tuples) == 1: 2269*cda5da8dSAndroid Build Coastguard Worker option_tuple, = option_tuples 2270*cda5da8dSAndroid Build Coastguard Worker return option_tuple 2271*cda5da8dSAndroid Build Coastguard Worker 2272*cda5da8dSAndroid Build Coastguard Worker # if it was not found as an option, but it looks like a negative 2273*cda5da8dSAndroid Build Coastguard Worker # number, it was meant to be positional 2274*cda5da8dSAndroid Build Coastguard Worker # unless there are negative-number-like options 2275*cda5da8dSAndroid Build Coastguard Worker if self._negative_number_matcher.match(arg_string): 2276*cda5da8dSAndroid Build Coastguard Worker if not self._has_negative_number_optionals: 2277*cda5da8dSAndroid Build Coastguard Worker return None 2278*cda5da8dSAndroid Build Coastguard Worker 2279*cda5da8dSAndroid Build Coastguard Worker # if it contains a space, it was meant to be a positional 2280*cda5da8dSAndroid Build Coastguard Worker if ' ' in arg_string: 2281*cda5da8dSAndroid Build Coastguard Worker return None 2282*cda5da8dSAndroid Build Coastguard Worker 2283*cda5da8dSAndroid Build Coastguard Worker # it was meant to be an optional but there is no such option 2284*cda5da8dSAndroid Build Coastguard Worker # in this parser (though it might be a valid option in a subparser) 2285*cda5da8dSAndroid Build Coastguard Worker return None, arg_string, None 2286*cda5da8dSAndroid Build Coastguard Worker 2287*cda5da8dSAndroid Build Coastguard Worker def _get_option_tuples(self, option_string): 2288*cda5da8dSAndroid Build Coastguard Worker result = [] 2289*cda5da8dSAndroid Build Coastguard Worker 2290*cda5da8dSAndroid Build Coastguard Worker # option strings starting with two prefix characters are only 2291*cda5da8dSAndroid Build Coastguard Worker # split at the '=' 2292*cda5da8dSAndroid Build Coastguard Worker chars = self.prefix_chars 2293*cda5da8dSAndroid Build Coastguard Worker if option_string[0] in chars and option_string[1] in chars: 2294*cda5da8dSAndroid Build Coastguard Worker if self.allow_abbrev: 2295*cda5da8dSAndroid Build Coastguard Worker if '=' in option_string: 2296*cda5da8dSAndroid Build Coastguard Worker option_prefix, explicit_arg = option_string.split('=', 1) 2297*cda5da8dSAndroid Build Coastguard Worker else: 2298*cda5da8dSAndroid Build Coastguard Worker option_prefix = option_string 2299*cda5da8dSAndroid Build Coastguard Worker explicit_arg = None 2300*cda5da8dSAndroid Build Coastguard Worker for option_string in self._option_string_actions: 2301*cda5da8dSAndroid Build Coastguard Worker if option_string.startswith(option_prefix): 2302*cda5da8dSAndroid Build Coastguard Worker action = self._option_string_actions[option_string] 2303*cda5da8dSAndroid Build Coastguard Worker tup = action, option_string, explicit_arg 2304*cda5da8dSAndroid Build Coastguard Worker result.append(tup) 2305*cda5da8dSAndroid Build Coastguard Worker 2306*cda5da8dSAndroid Build Coastguard Worker # single character options can be concatenated with their arguments 2307*cda5da8dSAndroid Build Coastguard Worker # but multiple character options always have to have their argument 2308*cda5da8dSAndroid Build Coastguard Worker # separate 2309*cda5da8dSAndroid Build Coastguard Worker elif option_string[0] in chars and option_string[1] not in chars: 2310*cda5da8dSAndroid Build Coastguard Worker option_prefix = option_string 2311*cda5da8dSAndroid Build Coastguard Worker explicit_arg = None 2312*cda5da8dSAndroid Build Coastguard Worker short_option_prefix = option_string[:2] 2313*cda5da8dSAndroid Build Coastguard Worker short_explicit_arg = option_string[2:] 2314*cda5da8dSAndroid Build Coastguard Worker 2315*cda5da8dSAndroid Build Coastguard Worker for option_string in self._option_string_actions: 2316*cda5da8dSAndroid Build Coastguard Worker if option_string == short_option_prefix: 2317*cda5da8dSAndroid Build Coastguard Worker action = self._option_string_actions[option_string] 2318*cda5da8dSAndroid Build Coastguard Worker tup = action, option_string, short_explicit_arg 2319*cda5da8dSAndroid Build Coastguard Worker result.append(tup) 2320*cda5da8dSAndroid Build Coastguard Worker elif option_string.startswith(option_prefix): 2321*cda5da8dSAndroid Build Coastguard Worker action = self._option_string_actions[option_string] 2322*cda5da8dSAndroid Build Coastguard Worker tup = action, option_string, explicit_arg 2323*cda5da8dSAndroid Build Coastguard Worker result.append(tup) 2324*cda5da8dSAndroid Build Coastguard Worker 2325*cda5da8dSAndroid Build Coastguard Worker # shouldn't ever get here 2326*cda5da8dSAndroid Build Coastguard Worker else: 2327*cda5da8dSAndroid Build Coastguard Worker self.error(_('unexpected option string: %s') % option_string) 2328*cda5da8dSAndroid Build Coastguard Worker 2329*cda5da8dSAndroid Build Coastguard Worker # return the collected option tuples 2330*cda5da8dSAndroid Build Coastguard Worker return result 2331*cda5da8dSAndroid Build Coastguard Worker 2332*cda5da8dSAndroid Build Coastguard Worker def _get_nargs_pattern(self, action): 2333*cda5da8dSAndroid Build Coastguard Worker # in all examples below, we have to allow for '--' args 2334*cda5da8dSAndroid Build Coastguard Worker # which are represented as '-' in the pattern 2335*cda5da8dSAndroid Build Coastguard Worker nargs = action.nargs 2336*cda5da8dSAndroid Build Coastguard Worker 2337*cda5da8dSAndroid Build Coastguard Worker # the default (None) is assumed to be a single argument 2338*cda5da8dSAndroid Build Coastguard Worker if nargs is None: 2339*cda5da8dSAndroid Build Coastguard Worker nargs_pattern = '(-*A-*)' 2340*cda5da8dSAndroid Build Coastguard Worker 2341*cda5da8dSAndroid Build Coastguard Worker # allow zero or one arguments 2342*cda5da8dSAndroid Build Coastguard Worker elif nargs == OPTIONAL: 2343*cda5da8dSAndroid Build Coastguard Worker nargs_pattern = '(-*A?-*)' 2344*cda5da8dSAndroid Build Coastguard Worker 2345*cda5da8dSAndroid Build Coastguard Worker # allow zero or more arguments 2346*cda5da8dSAndroid Build Coastguard Worker elif nargs == ZERO_OR_MORE: 2347*cda5da8dSAndroid Build Coastguard Worker nargs_pattern = '(-*[A-]*)' 2348*cda5da8dSAndroid Build Coastguard Worker 2349*cda5da8dSAndroid Build Coastguard Worker # allow one or more arguments 2350*cda5da8dSAndroid Build Coastguard Worker elif nargs == ONE_OR_MORE: 2351*cda5da8dSAndroid Build Coastguard Worker nargs_pattern = '(-*A[A-]*)' 2352*cda5da8dSAndroid Build Coastguard Worker 2353*cda5da8dSAndroid Build Coastguard Worker # allow any number of options or arguments 2354*cda5da8dSAndroid Build Coastguard Worker elif nargs == REMAINDER: 2355*cda5da8dSAndroid Build Coastguard Worker nargs_pattern = '([-AO]*)' 2356*cda5da8dSAndroid Build Coastguard Worker 2357*cda5da8dSAndroid Build Coastguard Worker # allow one argument followed by any number of options or arguments 2358*cda5da8dSAndroid Build Coastguard Worker elif nargs == PARSER: 2359*cda5da8dSAndroid Build Coastguard Worker nargs_pattern = '(-*A[-AO]*)' 2360*cda5da8dSAndroid Build Coastguard Worker 2361*cda5da8dSAndroid Build Coastguard Worker # suppress action, like nargs=0 2362*cda5da8dSAndroid Build Coastguard Worker elif nargs == SUPPRESS: 2363*cda5da8dSAndroid Build Coastguard Worker nargs_pattern = '(-*-*)' 2364*cda5da8dSAndroid Build Coastguard Worker 2365*cda5da8dSAndroid Build Coastguard Worker # all others should be integers 2366*cda5da8dSAndroid Build Coastguard Worker else: 2367*cda5da8dSAndroid Build Coastguard Worker nargs_pattern = '(-*%s-*)' % '-*'.join('A' * nargs) 2368*cda5da8dSAndroid Build Coastguard Worker 2369*cda5da8dSAndroid Build Coastguard Worker # if this is an optional action, -- is not allowed 2370*cda5da8dSAndroid Build Coastguard Worker if action.option_strings: 2371*cda5da8dSAndroid Build Coastguard Worker nargs_pattern = nargs_pattern.replace('-*', '') 2372*cda5da8dSAndroid Build Coastguard Worker nargs_pattern = nargs_pattern.replace('-', '') 2373*cda5da8dSAndroid Build Coastguard Worker 2374*cda5da8dSAndroid Build Coastguard Worker # return the pattern 2375*cda5da8dSAndroid Build Coastguard Worker return nargs_pattern 2376*cda5da8dSAndroid Build Coastguard Worker 2377*cda5da8dSAndroid Build Coastguard Worker # ======================== 2378*cda5da8dSAndroid Build Coastguard Worker # Alt command line argument parsing, allowing free intermix 2379*cda5da8dSAndroid Build Coastguard Worker # ======================== 2380*cda5da8dSAndroid Build Coastguard Worker 2381*cda5da8dSAndroid Build Coastguard Worker def parse_intermixed_args(self, args=None, namespace=None): 2382*cda5da8dSAndroid Build Coastguard Worker args, argv = self.parse_known_intermixed_args(args, namespace) 2383*cda5da8dSAndroid Build Coastguard Worker if argv: 2384*cda5da8dSAndroid Build Coastguard Worker msg = _('unrecognized arguments: %s') 2385*cda5da8dSAndroid Build Coastguard Worker self.error(msg % ' '.join(argv)) 2386*cda5da8dSAndroid Build Coastguard Worker return args 2387*cda5da8dSAndroid Build Coastguard Worker 2388*cda5da8dSAndroid Build Coastguard Worker def parse_known_intermixed_args(self, args=None, namespace=None): 2389*cda5da8dSAndroid Build Coastguard Worker # returns a namespace and list of extras 2390*cda5da8dSAndroid Build Coastguard Worker # 2391*cda5da8dSAndroid Build Coastguard Worker # positional can be freely intermixed with optionals. optionals are 2392*cda5da8dSAndroid Build Coastguard Worker # first parsed with all positional arguments deactivated. The 'extras' 2393*cda5da8dSAndroid Build Coastguard Worker # are then parsed. If the parser definition is incompatible with the 2394*cda5da8dSAndroid Build Coastguard Worker # intermixed assumptions (e.g. use of REMAINDER, subparsers) a 2395*cda5da8dSAndroid Build Coastguard Worker # TypeError is raised. 2396*cda5da8dSAndroid Build Coastguard Worker # 2397*cda5da8dSAndroid Build Coastguard Worker # positionals are 'deactivated' by setting nargs and default to 2398*cda5da8dSAndroid Build Coastguard Worker # SUPPRESS. This blocks the addition of that positional to the 2399*cda5da8dSAndroid Build Coastguard Worker # namespace 2400*cda5da8dSAndroid Build Coastguard Worker 2401*cda5da8dSAndroid Build Coastguard Worker positionals = self._get_positional_actions() 2402*cda5da8dSAndroid Build Coastguard Worker a = [action for action in positionals 2403*cda5da8dSAndroid Build Coastguard Worker if action.nargs in [PARSER, REMAINDER]] 2404*cda5da8dSAndroid Build Coastguard Worker if a: 2405*cda5da8dSAndroid Build Coastguard Worker raise TypeError('parse_intermixed_args: positional arg' 2406*cda5da8dSAndroid Build Coastguard Worker ' with nargs=%s'%a[0].nargs) 2407*cda5da8dSAndroid Build Coastguard Worker 2408*cda5da8dSAndroid Build Coastguard Worker if [action.dest for group in self._mutually_exclusive_groups 2409*cda5da8dSAndroid Build Coastguard Worker for action in group._group_actions if action in positionals]: 2410*cda5da8dSAndroid Build Coastguard Worker raise TypeError('parse_intermixed_args: positional in' 2411*cda5da8dSAndroid Build Coastguard Worker ' mutuallyExclusiveGroup') 2412*cda5da8dSAndroid Build Coastguard Worker 2413*cda5da8dSAndroid Build Coastguard Worker try: 2414*cda5da8dSAndroid Build Coastguard Worker save_usage = self.usage 2415*cda5da8dSAndroid Build Coastguard Worker try: 2416*cda5da8dSAndroid Build Coastguard Worker if self.usage is None: 2417*cda5da8dSAndroid Build Coastguard Worker # capture the full usage for use in error messages 2418*cda5da8dSAndroid Build Coastguard Worker self.usage = self.format_usage()[7:] 2419*cda5da8dSAndroid Build Coastguard Worker for action in positionals: 2420*cda5da8dSAndroid Build Coastguard Worker # deactivate positionals 2421*cda5da8dSAndroid Build Coastguard Worker action.save_nargs = action.nargs 2422*cda5da8dSAndroid Build Coastguard Worker # action.nargs = 0 2423*cda5da8dSAndroid Build Coastguard Worker action.nargs = SUPPRESS 2424*cda5da8dSAndroid Build Coastguard Worker action.save_default = action.default 2425*cda5da8dSAndroid Build Coastguard Worker action.default = SUPPRESS 2426*cda5da8dSAndroid Build Coastguard Worker namespace, remaining_args = self.parse_known_args(args, 2427*cda5da8dSAndroid Build Coastguard Worker namespace) 2428*cda5da8dSAndroid Build Coastguard Worker for action in positionals: 2429*cda5da8dSAndroid Build Coastguard Worker # remove the empty positional values from namespace 2430*cda5da8dSAndroid Build Coastguard Worker if (hasattr(namespace, action.dest) 2431*cda5da8dSAndroid Build Coastguard Worker and getattr(namespace, action.dest)==[]): 2432*cda5da8dSAndroid Build Coastguard Worker from warnings import warn 2433*cda5da8dSAndroid Build Coastguard Worker warn('Do not expect %s in %s' % (action.dest, namespace)) 2434*cda5da8dSAndroid Build Coastguard Worker delattr(namespace, action.dest) 2435*cda5da8dSAndroid Build Coastguard Worker finally: 2436*cda5da8dSAndroid Build Coastguard Worker # restore nargs and usage before exiting 2437*cda5da8dSAndroid Build Coastguard Worker for action in positionals: 2438*cda5da8dSAndroid Build Coastguard Worker action.nargs = action.save_nargs 2439*cda5da8dSAndroid Build Coastguard Worker action.default = action.save_default 2440*cda5da8dSAndroid Build Coastguard Worker optionals = self._get_optional_actions() 2441*cda5da8dSAndroid Build Coastguard Worker try: 2442*cda5da8dSAndroid Build Coastguard Worker # parse positionals. optionals aren't normally required, but 2443*cda5da8dSAndroid Build Coastguard Worker # they could be, so make sure they aren't. 2444*cda5da8dSAndroid Build Coastguard Worker for action in optionals: 2445*cda5da8dSAndroid Build Coastguard Worker action.save_required = action.required 2446*cda5da8dSAndroid Build Coastguard Worker action.required = False 2447*cda5da8dSAndroid Build Coastguard Worker for group in self._mutually_exclusive_groups: 2448*cda5da8dSAndroid Build Coastguard Worker group.save_required = group.required 2449*cda5da8dSAndroid Build Coastguard Worker group.required = False 2450*cda5da8dSAndroid Build Coastguard Worker namespace, extras = self.parse_known_args(remaining_args, 2451*cda5da8dSAndroid Build Coastguard Worker namespace) 2452*cda5da8dSAndroid Build Coastguard Worker finally: 2453*cda5da8dSAndroid Build Coastguard Worker # restore parser values before exiting 2454*cda5da8dSAndroid Build Coastguard Worker for action in optionals: 2455*cda5da8dSAndroid Build Coastguard Worker action.required = action.save_required 2456*cda5da8dSAndroid Build Coastguard Worker for group in self._mutually_exclusive_groups: 2457*cda5da8dSAndroid Build Coastguard Worker group.required = group.save_required 2458*cda5da8dSAndroid Build Coastguard Worker finally: 2459*cda5da8dSAndroid Build Coastguard Worker self.usage = save_usage 2460*cda5da8dSAndroid Build Coastguard Worker return namespace, extras 2461*cda5da8dSAndroid Build Coastguard Worker 2462*cda5da8dSAndroid Build Coastguard Worker # ======================== 2463*cda5da8dSAndroid Build Coastguard Worker # Value conversion methods 2464*cda5da8dSAndroid Build Coastguard Worker # ======================== 2465*cda5da8dSAndroid Build Coastguard Worker def _get_values(self, action, arg_strings): 2466*cda5da8dSAndroid Build Coastguard Worker # for everything but PARSER, REMAINDER args, strip out first '--' 2467*cda5da8dSAndroid Build Coastguard Worker if action.nargs not in [PARSER, REMAINDER]: 2468*cda5da8dSAndroid Build Coastguard Worker try: 2469*cda5da8dSAndroid Build Coastguard Worker arg_strings.remove('--') 2470*cda5da8dSAndroid Build Coastguard Worker except ValueError: 2471*cda5da8dSAndroid Build Coastguard Worker pass 2472*cda5da8dSAndroid Build Coastguard Worker 2473*cda5da8dSAndroid Build Coastguard Worker # optional argument produces a default when not present 2474*cda5da8dSAndroid Build Coastguard Worker if not arg_strings and action.nargs == OPTIONAL: 2475*cda5da8dSAndroid Build Coastguard Worker if action.option_strings: 2476*cda5da8dSAndroid Build Coastguard Worker value = action.const 2477*cda5da8dSAndroid Build Coastguard Worker else: 2478*cda5da8dSAndroid Build Coastguard Worker value = action.default 2479*cda5da8dSAndroid Build Coastguard Worker if isinstance(value, str): 2480*cda5da8dSAndroid Build Coastguard Worker value = self._get_value(action, value) 2481*cda5da8dSAndroid Build Coastguard Worker self._check_value(action, value) 2482*cda5da8dSAndroid Build Coastguard Worker 2483*cda5da8dSAndroid Build Coastguard Worker # when nargs='*' on a positional, if there were no command-line 2484*cda5da8dSAndroid Build Coastguard Worker # args, use the default if it is anything other than None 2485*cda5da8dSAndroid Build Coastguard Worker elif (not arg_strings and action.nargs == ZERO_OR_MORE and 2486*cda5da8dSAndroid Build Coastguard Worker not action.option_strings): 2487*cda5da8dSAndroid Build Coastguard Worker if action.default is not None: 2488*cda5da8dSAndroid Build Coastguard Worker value = action.default 2489*cda5da8dSAndroid Build Coastguard Worker else: 2490*cda5da8dSAndroid Build Coastguard Worker value = arg_strings 2491*cda5da8dSAndroid Build Coastguard Worker self._check_value(action, value) 2492*cda5da8dSAndroid Build Coastguard Worker 2493*cda5da8dSAndroid Build Coastguard Worker # single argument or optional argument produces a single value 2494*cda5da8dSAndroid Build Coastguard Worker elif len(arg_strings) == 1 and action.nargs in [None, OPTIONAL]: 2495*cda5da8dSAndroid Build Coastguard Worker arg_string, = arg_strings 2496*cda5da8dSAndroid Build Coastguard Worker value = self._get_value(action, arg_string) 2497*cda5da8dSAndroid Build Coastguard Worker self._check_value(action, value) 2498*cda5da8dSAndroid Build Coastguard Worker 2499*cda5da8dSAndroid Build Coastguard Worker # REMAINDER arguments convert all values, checking none 2500*cda5da8dSAndroid Build Coastguard Worker elif action.nargs == REMAINDER: 2501*cda5da8dSAndroid Build Coastguard Worker value = [self._get_value(action, v) for v in arg_strings] 2502*cda5da8dSAndroid Build Coastguard Worker 2503*cda5da8dSAndroid Build Coastguard Worker # PARSER arguments convert all values, but check only the first 2504*cda5da8dSAndroid Build Coastguard Worker elif action.nargs == PARSER: 2505*cda5da8dSAndroid Build Coastguard Worker value = [self._get_value(action, v) for v in arg_strings] 2506*cda5da8dSAndroid Build Coastguard Worker self._check_value(action, value[0]) 2507*cda5da8dSAndroid Build Coastguard Worker 2508*cda5da8dSAndroid Build Coastguard Worker # SUPPRESS argument does not put anything in the namespace 2509*cda5da8dSAndroid Build Coastguard Worker elif action.nargs == SUPPRESS: 2510*cda5da8dSAndroid Build Coastguard Worker value = SUPPRESS 2511*cda5da8dSAndroid Build Coastguard Worker 2512*cda5da8dSAndroid Build Coastguard Worker # all other types of nargs produce a list 2513*cda5da8dSAndroid Build Coastguard Worker else: 2514*cda5da8dSAndroid Build Coastguard Worker value = [self._get_value(action, v) for v in arg_strings] 2515*cda5da8dSAndroid Build Coastguard Worker for v in value: 2516*cda5da8dSAndroid Build Coastguard Worker self._check_value(action, v) 2517*cda5da8dSAndroid Build Coastguard Worker 2518*cda5da8dSAndroid Build Coastguard Worker # return the converted value 2519*cda5da8dSAndroid Build Coastguard Worker return value 2520*cda5da8dSAndroid Build Coastguard Worker 2521*cda5da8dSAndroid Build Coastguard Worker def _get_value(self, action, arg_string): 2522*cda5da8dSAndroid Build Coastguard Worker type_func = self._registry_get('type', action.type, action.type) 2523*cda5da8dSAndroid Build Coastguard Worker if not callable(type_func): 2524*cda5da8dSAndroid Build Coastguard Worker msg = _('%r is not callable') 2525*cda5da8dSAndroid Build Coastguard Worker raise ArgumentError(action, msg % type_func) 2526*cda5da8dSAndroid Build Coastguard Worker 2527*cda5da8dSAndroid Build Coastguard Worker # convert the value to the appropriate type 2528*cda5da8dSAndroid Build Coastguard Worker try: 2529*cda5da8dSAndroid Build Coastguard Worker result = type_func(arg_string) 2530*cda5da8dSAndroid Build Coastguard Worker 2531*cda5da8dSAndroid Build Coastguard Worker # ArgumentTypeErrors indicate errors 2532*cda5da8dSAndroid Build Coastguard Worker except ArgumentTypeError as err: 2533*cda5da8dSAndroid Build Coastguard Worker name = getattr(action.type, '__name__', repr(action.type)) 2534*cda5da8dSAndroid Build Coastguard Worker msg = str(err) 2535*cda5da8dSAndroid Build Coastguard Worker raise ArgumentError(action, msg) 2536*cda5da8dSAndroid Build Coastguard Worker 2537*cda5da8dSAndroid Build Coastguard Worker # TypeErrors or ValueErrors also indicate errors 2538*cda5da8dSAndroid Build Coastguard Worker except (TypeError, ValueError): 2539*cda5da8dSAndroid Build Coastguard Worker name = getattr(action.type, '__name__', repr(action.type)) 2540*cda5da8dSAndroid Build Coastguard Worker args = {'type': name, 'value': arg_string} 2541*cda5da8dSAndroid Build Coastguard Worker msg = _('invalid %(type)s value: %(value)r') 2542*cda5da8dSAndroid Build Coastguard Worker raise ArgumentError(action, msg % args) 2543*cda5da8dSAndroid Build Coastguard Worker 2544*cda5da8dSAndroid Build Coastguard Worker # return the converted value 2545*cda5da8dSAndroid Build Coastguard Worker return result 2546*cda5da8dSAndroid Build Coastguard Worker 2547*cda5da8dSAndroid Build Coastguard Worker def _check_value(self, action, value): 2548*cda5da8dSAndroid Build Coastguard Worker # converted value must be one of the choices (if specified) 2549*cda5da8dSAndroid Build Coastguard Worker if action.choices is not None and value not in action.choices: 2550*cda5da8dSAndroid Build Coastguard Worker args = {'value': value, 2551*cda5da8dSAndroid Build Coastguard Worker 'choices': ', '.join(map(repr, action.choices))} 2552*cda5da8dSAndroid Build Coastguard Worker msg = _('invalid choice: %(value)r (choose from %(choices)s)') 2553*cda5da8dSAndroid Build Coastguard Worker raise ArgumentError(action, msg % args) 2554*cda5da8dSAndroid Build Coastguard Worker 2555*cda5da8dSAndroid Build Coastguard Worker # ======================= 2556*cda5da8dSAndroid Build Coastguard Worker # Help-formatting methods 2557*cda5da8dSAndroid Build Coastguard Worker # ======================= 2558*cda5da8dSAndroid Build Coastguard Worker def format_usage(self): 2559*cda5da8dSAndroid Build Coastguard Worker formatter = self._get_formatter() 2560*cda5da8dSAndroid Build Coastguard Worker formatter.add_usage(self.usage, self._actions, 2561*cda5da8dSAndroid Build Coastguard Worker self._mutually_exclusive_groups) 2562*cda5da8dSAndroid Build Coastguard Worker return formatter.format_help() 2563*cda5da8dSAndroid Build Coastguard Worker 2564*cda5da8dSAndroid Build Coastguard Worker def format_help(self): 2565*cda5da8dSAndroid Build Coastguard Worker formatter = self._get_formatter() 2566*cda5da8dSAndroid Build Coastguard Worker 2567*cda5da8dSAndroid Build Coastguard Worker # usage 2568*cda5da8dSAndroid Build Coastguard Worker formatter.add_usage(self.usage, self._actions, 2569*cda5da8dSAndroid Build Coastguard Worker self._mutually_exclusive_groups) 2570*cda5da8dSAndroid Build Coastguard Worker 2571*cda5da8dSAndroid Build Coastguard Worker # description 2572*cda5da8dSAndroid Build Coastguard Worker formatter.add_text(self.description) 2573*cda5da8dSAndroid Build Coastguard Worker 2574*cda5da8dSAndroid Build Coastguard Worker # positionals, optionals and user-defined groups 2575*cda5da8dSAndroid Build Coastguard Worker for action_group in self._action_groups: 2576*cda5da8dSAndroid Build Coastguard Worker formatter.start_section(action_group.title) 2577*cda5da8dSAndroid Build Coastguard Worker formatter.add_text(action_group.description) 2578*cda5da8dSAndroid Build Coastguard Worker formatter.add_arguments(action_group._group_actions) 2579*cda5da8dSAndroid Build Coastguard Worker formatter.end_section() 2580*cda5da8dSAndroid Build Coastguard Worker 2581*cda5da8dSAndroid Build Coastguard Worker # epilog 2582*cda5da8dSAndroid Build Coastguard Worker formatter.add_text(self.epilog) 2583*cda5da8dSAndroid Build Coastguard Worker 2584*cda5da8dSAndroid Build Coastguard Worker # determine help from format above 2585*cda5da8dSAndroid Build Coastguard Worker return formatter.format_help() 2586*cda5da8dSAndroid Build Coastguard Worker 2587*cda5da8dSAndroid Build Coastguard Worker def _get_formatter(self): 2588*cda5da8dSAndroid Build Coastguard Worker return self.formatter_class(prog=self.prog) 2589*cda5da8dSAndroid Build Coastguard Worker 2590*cda5da8dSAndroid Build Coastguard Worker # ===================== 2591*cda5da8dSAndroid Build Coastguard Worker # Help-printing methods 2592*cda5da8dSAndroid Build Coastguard Worker # ===================== 2593*cda5da8dSAndroid Build Coastguard Worker def print_usage(self, file=None): 2594*cda5da8dSAndroid Build Coastguard Worker if file is None: 2595*cda5da8dSAndroid Build Coastguard Worker file = _sys.stdout 2596*cda5da8dSAndroid Build Coastguard Worker self._print_message(self.format_usage(), file) 2597*cda5da8dSAndroid Build Coastguard Worker 2598*cda5da8dSAndroid Build Coastguard Worker def print_help(self, file=None): 2599*cda5da8dSAndroid Build Coastguard Worker if file is None: 2600*cda5da8dSAndroid Build Coastguard Worker file = _sys.stdout 2601*cda5da8dSAndroid Build Coastguard Worker self._print_message(self.format_help(), file) 2602*cda5da8dSAndroid Build Coastguard Worker 2603*cda5da8dSAndroid Build Coastguard Worker def _print_message(self, message, file=None): 2604*cda5da8dSAndroid Build Coastguard Worker if message: 2605*cda5da8dSAndroid Build Coastguard Worker file = file or _sys.stderr 2606*cda5da8dSAndroid Build Coastguard Worker try: 2607*cda5da8dSAndroid Build Coastguard Worker file.write(message) 2608*cda5da8dSAndroid Build Coastguard Worker except (AttributeError, OSError): 2609*cda5da8dSAndroid Build Coastguard Worker pass 2610*cda5da8dSAndroid Build Coastguard Worker 2611*cda5da8dSAndroid Build Coastguard Worker # =============== 2612*cda5da8dSAndroid Build Coastguard Worker # Exiting methods 2613*cda5da8dSAndroid Build Coastguard Worker # =============== 2614*cda5da8dSAndroid Build Coastguard Worker def exit(self, status=0, message=None): 2615*cda5da8dSAndroid Build Coastguard Worker if message: 2616*cda5da8dSAndroid Build Coastguard Worker self._print_message(message, _sys.stderr) 2617*cda5da8dSAndroid Build Coastguard Worker _sys.exit(status) 2618*cda5da8dSAndroid Build Coastguard Worker 2619*cda5da8dSAndroid Build Coastguard Worker def error(self, message): 2620*cda5da8dSAndroid Build Coastguard Worker """error(message: string) 2621*cda5da8dSAndroid Build Coastguard Worker 2622*cda5da8dSAndroid Build Coastguard Worker Prints a usage message incorporating the message to stderr and 2623*cda5da8dSAndroid Build Coastguard Worker exits. 2624*cda5da8dSAndroid Build Coastguard Worker 2625*cda5da8dSAndroid Build Coastguard Worker If you override this in a subclass, it should not return -- it 2626*cda5da8dSAndroid Build Coastguard Worker should either exit or raise an exception. 2627*cda5da8dSAndroid Build Coastguard Worker """ 2628*cda5da8dSAndroid Build Coastguard Worker self.print_usage(_sys.stderr) 2629*cda5da8dSAndroid Build Coastguard Worker args = {'prog': self.prog, 'message': message} 2630*cda5da8dSAndroid Build Coastguard Worker self.exit(2, _('%(prog)s: error: %(message)s\n') % args) 2631