Rietveld Code Review Tool
Help | Bug tracker | Discussion group | Source code | Sign in
(62)

Delta Between Two Patch Sets: Lib/argparse.py

Issue 14191: argparse: nargs='*' doesn't get out-of-order positional parameters
Left Patch Set: Created 6 years, 11 months ago
Right Patch Set: Created 6 years, 10 months ago
Left:
Right:
Use n/p to move between diff chunks; N/P to move between comments. Please Sign in to add in-line comments.
Jump to:
Left: Side by side diff | Download
Right: Side by side diff | Download
« no previous file with change/comment | « Doc/library/argparse.rst ('k') | Lib/test/test_argparse.py » ('j') | no next file with change/comment »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
LEFTRIGHT
1 # Author: Steven J. Bethard <steven.bethard@gmail.com>. 1 # Author: Steven J. Bethard <steven.bethard@gmail.com>.
2 2
3 """Command-line parsing library 3 """Command-line parsing library
4 4
5 This module is an optparse-inspired command-line parsing library that: 5 This module is an optparse-inspired command-line parsing library that:
6 6
7 - handles both optional and positional arguments 7 - handles both optional and positional arguments
8 - produces highly informative usage messages 8 - produces highly informative usage messages
9 - supports parsers that dispatch to sub-parsers 9 - supports parsers that dispatch to sub-parsers
10 10
(...skipping 563 matching lines...) Expand 10 before | Expand all | Expand 10 after
574 elif action.nargs == OPTIONAL: 574 elif action.nargs == OPTIONAL:
575 result = '[%s]' % get_metavar(1) 575 result = '[%s]' % get_metavar(1)
576 elif action.nargs == ZERO_OR_MORE: 576 elif action.nargs == ZERO_OR_MORE:
577 result = '[%s [%s ...]]' % get_metavar(2) 577 result = '[%s [%s ...]]' % get_metavar(2)
578 elif action.nargs == ONE_OR_MORE: 578 elif action.nargs == ONE_OR_MORE:
579 result = '%s [%s ...]' % get_metavar(2) 579 result = '%s [%s ...]' % get_metavar(2)
580 elif action.nargs == REMAINDER: 580 elif action.nargs == REMAINDER:
581 result = '...' 581 result = '...'
582 elif action.nargs == PARSER: 582 elif action.nargs == PARSER:
583 result = '%s ...' % get_metavar(1) 583 result = '%s ...' % get_metavar(1)
584 elif action.nargs == SUPPRESS:
585 result = ''
584 else: 586 else:
585 formats = ['%s' for _ in range(action.nargs)] 587 formats = ['%s' for _ in range(action.nargs)]
586 result = ' '.join(formats) % get_metavar(action.nargs) 588 result = ' '.join(formats) % get_metavar(action.nargs)
587 return result 589 return result
588 590
589 def _expand_help(self, action): 591 def _expand_help(self, action):
590 params = dict(vars(action), prog=self._prog) 592 params = dict(vars(action), prog=self._prog)
591 for name in list(params): 593 for name in list(params):
592 if params[name] is SUPPRESS: 594 if params[name] is SUPPRESS:
593 del params[name] 595 del params[name]
(...skipping 1594 matching lines...) Expand 10 before | Expand all | Expand 10 after
2188 nargs_pattern = '(-*A[A-]*)' 2190 nargs_pattern = '(-*A[A-]*)'
2189 2191
2190 # allow any number of options or arguments 2192 # allow any number of options or arguments
2191 elif nargs == REMAINDER: 2193 elif nargs == REMAINDER:
2192 nargs_pattern = '([-AO]*)' 2194 nargs_pattern = '([-AO]*)'
2193 2195
2194 # allow one argument followed by any number of options or arguments 2196 # allow one argument followed by any number of options or arguments
2195 elif nargs == PARSER: 2197 elif nargs == PARSER:
2196 nargs_pattern = '(-*A[-AO]*)' 2198 nargs_pattern = '(-*A[-AO]*)'
2197 2199
2200 # suppress action, like nargs=0
2201 elif nargs == SUPPRESS:
2202 nargs_pattern = '(-*-*)'
2203
2198 # all others should be integers 2204 # all others should be integers
2199 else: 2205 else:
2200 nargs_pattern = '(-*%s-*)' % '-*'.join('A' * nargs) 2206 nargs_pattern = '(-*%s-*)' % '-*'.join('A' * nargs)
2201 2207
2202 # if this is an optional action, -- is not allowed 2208 # if this is an optional action, -- is not allowed
2203 if action.option_strings: 2209 if action.option_strings:
2204 nargs_pattern = nargs_pattern.replace('-*', '') 2210 nargs_pattern = nargs_pattern.replace('-*', '')
2205 nargs_pattern = nargs_pattern.replace('-', '') 2211 nargs_pattern = nargs_pattern.replace('-', '')
2206 2212
2207 # return the pattern 2213 # return the pattern
2208 return nargs_pattern 2214 return nargs_pattern
2209 2215
2210 # ======================== 2216 # ========================
2211 # Alt command line argument parsing, allowing free intermix 2217 # Alt command line argument parsing, allowing free intermix
2212 # ======================== 2218 # ========================
2213 2219
2214 def parse_intermixed_args(self, args=None, namespace=None): 2220 def parse_intermixed_args(self, args=None, namespace=None):
2215 args, argv = self.parse_known_intermixed_args(args, namespace) 2221 args, argv = self.parse_known_intermixed_args(args, namespace)
2216 if argv: 2222 if argv:
2217 msg = _('unrecognized arguments: %s') 2223 msg = _('unrecognized arguments: %s')
2218 self.error(msg % ' '.join(argv)) 2224 self.error(msg % ' '.join(argv))
2219 return args 2225 return args
2220 2226
2221 def parse_known_intermixed_args(self, args=None, namespace=None, _fallback=N one): 2227 def parse_known_intermixed_args(self, args=None, namespace=None):
2222 # self - argparse parser 2228 # self - argparse parser
2223 # args, namespace - as used by parse_known_args 2229 # args, namespace - as used by parse_known_args
2224 # _fallback - action to take if it can't handle this parser's arguments
2225 # (default raises an error)
2226 # returns a namespace and list of extras 2230 # returns a namespace and list of extras
2227 2231
2228 # positional can be freely intermixed with optionals 2232 # positional can be freely intermixed with optionals
2229 # optionals are first parsed with all positional arguments deactivated 2233 # optionals are first parsed with all positional arguments deactivated
2230 # the 'extras' are then parsed 2234 # the 'extras' are then parsed
2231 # positionals 'deactivated' by setting nargs=0 2235 # if parser definition is incompatible with the intermixed assumptions
2236 # returns a TypeError (e.g. use of REMAINDER, subparsers)
2237
2238 # positionals are 'deactivated' by setting nargs and default to SUPPRESS .
2239 # This blocks the addition of that positional to the namespace
2232 2240
2233 positionals = self._get_positional_actions() 2241 positionals = self._get_positional_actions()
2234 a = [action for action in positionals if action.nargs in [PARSER, REMAIN DER]] 2242 a = [action for action in positionals if action.nargs in [PARSER, REMAIN DER]]
2235 if a: 2243 if a:
2236 if _fallback is None: 2244 raise TypeError('parse_intermixed_args: positional arg with nargs=%s '%a[0].nargs)
2237 a = a[0]
2238 err = ArgumentError(a, 'parse_intermixed_args: positional arg wi th nargs=%s'%a.nargs)
2239 self.error(str(err))
2240 else:
2241 return _fallback(args, namespace)
2242 2245
2243 if [action.dest for group in self._mutually_exclusive_groups 2246 if [action.dest for group in self._mutually_exclusive_groups
2244 for action in group._group_actions if action in positionals]: 2247 for action in group._group_actions if action in positionals]:
2245 if _fallback is None: 2248 raise TypeError('parse_intermixed_args: positional in mutuallyExclus iveGroup')
2246 self.error('parse_intermixed_args: positional in mutuallyExclusi veGroup')
2247 else:
2248 return _fallback(args, namespace)
2249 2249
2250 save_usage = self.usage 2250 save_usage = self.usage
2251 if self.usage is None:
2252 # capture the full usage for use in error messages
2253 self.usage = self.format_usage()[7:]
2254 for action in positionals:
2255 # deactivate positionals
2256 action.save_nargs = action.nargs
2257 action.nargs = 0
2258 try: 2251 try:
2259 namespace, remaining_args = self.parse_known_args(args, namespace) 2252 if self.usage is None:
2253 # capture the full usage for use in error messages
2254 self.usage = self.format_usage()[7:]
2260 for action in positionals: 2255 for action in positionals:
2261 # remove the empty positional values from namespace 2256 # deactivate positionals
2262 if hasattr(namespace, action.dest): 2257 action.save_nargs = action.nargs
2263 delattr(namespace, action.dest) 2258 # action.nargs = 0
2264 except SystemExit: 2259 action.nargs = SUPPRESS
2265 # warn('error from 1st parse_known_args') 2260 action.save_default = action.default
2266 raise 2261 action.default = SUPPRESS
2262 try:
2263 namespace, remaining_args = self.parse_known_args(args, namespac e)
2264 for action in positionals:
2265 # remove the empty positional values from namespace
2266 if hasattr(namespace, action.dest) and getattr(namespace, ac tion.dest)==[]:
2267 from warnings import warn
2268 warn('Do not expect %s in %s'%(action.dest,namespace))
2269 delattr(namespace, action.dest)
2270 finally:
2271 # restore nargs and usage before exiting
2272 for action in positionals:
2273 action.nargs = action.save_nargs
2274 action.default = action.save_default
2275 # parse positionals
2276 # optionals aren't normally required, but just in case, turn that of f
2277 optionals = self._get_optional_actions()
2278 for action in optionals:
2279 action.save_required = action.required
2280 action.required = False
2281 for group in self._mutually_exclusive_groups:
2282 group.save_required = group.required
2283 group.required = False
2284 try:
2285 namespace, extras = self.parse_known_args(remaining_args, namesp ace)
2286 finally:
2287 # restore parser values before exiting
2288 for action in optionals:
2289 action.required = action.save_required
2290 for group in self._mutually_exclusive_groups:
2291 group.required = group.save_required
2267 finally: 2292 finally:
2268 # restore nargs and usage before exiting
2269 for action in positionals:
2270 action.nargs = action.save_nargs
2271 self.usage = save_usage
2272 # logging.info('1st: %s,%s'%(namespace, remaining_args))
2273 # parse positionals
2274 # optionals aren't normally required, but just in case, turn that off
2275 optionals = self._get_optional_actions()
2276 for action in optionals:
2277 action.save_required = action.required
2278 action.required = False
2279 for group in self._mutually_exclusive_groups:
2280 group.save_required = group.required
2281 group.required = False
2282 try:
2283 namespace, extras = self.parse_known_args(remaining_args, namespace)
2284 except SystemExit:
2285 # warn('error from 2nd parse_known_args')
2286 raise
2287 finally:
2288 # restore parser values before exiting
2289 for action in optionals:
2290 action.required = action.save_required
2291 for group in self._mutually_exclusive_groups:
2292 group.required = group.save_required
2293 self.usage = save_usage 2293 self.usage = save_usage
2294 return namespace, extras 2294 return namespace, extras
2295 2295
2296 # ======================== 2296 # ========================
2297 # Value conversion methods 2297 # Value conversion methods
2298 # ======================== 2298 # ========================
2299 def _get_values(self, action, arg_strings): 2299 def _get_values(self, action, arg_strings):
2300 # for everything but PARSER, REMAINDER args, strip out first '--' 2300 # for everything but PARSER, REMAINDER args, strip out first '--'
2301 if action.nargs not in [PARSER, REMAINDER]: 2301 if action.nargs not in [PARSER, REMAINDER]:
2302 try: 2302 try:
(...skipping 29 matching lines...) Expand all
2332 2332
2333 # REMAINDER arguments convert all values, checking none 2333 # REMAINDER arguments convert all values, checking none
2334 elif action.nargs == REMAINDER: 2334 elif action.nargs == REMAINDER:
2335 value = [self._get_value(action, v) for v in arg_strings] 2335 value = [self._get_value(action, v) for v in arg_strings]
2336 2336
2337 # PARSER arguments convert all values, but check only the first 2337 # PARSER arguments convert all values, but check only the first
2338 elif action.nargs == PARSER: 2338 elif action.nargs == PARSER:
2339 value = [self._get_value(action, v) for v in arg_strings] 2339 value = [self._get_value(action, v) for v in arg_strings]
2340 self._check_value(action, value[0]) 2340 self._check_value(action, value[0])
2341 2341
2342 # SUPPRESS argument does not put anything in the namespace
2343 elif action.nargs == SUPPRESS:
2344 value = SUPPRESS
2345
2342 # all other types of nargs produce a list 2346 # all other types of nargs produce a list
2343 else: 2347 else:
2344 value = [self._get_value(action, v) for v in arg_strings] 2348 value = [self._get_value(action, v) for v in arg_strings]
2345 for v in value: 2349 for v in value:
2346 self._check_value(action, v) 2350 self._check_value(action, v)
2347 2351
2348 # return the converted value 2352 # return the converted value
2349 return value 2353 return value
2350 2354
2351 def _get_value(self, action, arg_string): 2355 def _get_value(self, action, arg_string):
(...skipping 97 matching lines...) Expand 10 before | Expand all | Expand 10 after
2449 2453
2450 Prints a usage message incorporating the message to stderr and 2454 Prints a usage message incorporating the message to stderr and
2451 exits. 2455 exits.
2452 2456
2453 If you override this in a subclass, it should not return -- it 2457 If you override this in a subclass, it should not return -- it
2454 should either exit or raise an exception. 2458 should either exit or raise an exception.
2455 """ 2459 """
2456 self.print_usage(_sys.stderr) 2460 self.print_usage(_sys.stderr)
2457 args = {'prog': self.prog, 'message': message} 2461 args = {'prog': self.prog, 'message': message}
2458 self.exit(2, _('%(prog)s: error: %(message)s\n') % args) 2462 self.exit(2, _('%(prog)s: error: %(message)s\n') % args)
LEFTRIGHT

RSS Feeds Recent Issues | This issue
This is Rietveld 894c83f36cb7+