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

Side by Side Diff: Lib/argparse.py

Issue 14191: argparse: nargs='*' doesn't get out-of-order positional parameters
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:
View unified diff | Download patch
« no previous file with comments | « Doc/library/argparse.rst ('k') | Lib/test/test_argparse.py » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
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 1593 matching lines...) Expand 10 before | Expand all | Expand 10 after
2187 elif nargs == ONE_OR_MORE: 2189 elif nargs == ONE_OR_MORE:
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]*)'
2199
2200 # suppress action, like nargs=0
2201 elif nargs == SUPPRESS:
2202 nargs_pattern = '(-*-*)'
2197 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
2215
2216 # ========================
2217 # Alt command line argument parsing, allowing free intermix
2218 # ========================
2219
2220 def parse_intermixed_args(self, args=None, namespace=None):
2221 args, argv = self.parse_known_intermixed_args(args, namespace)
2222 if argv:
2223 msg = _('unrecognized arguments: %s')
2224 self.error(msg % ' '.join(argv))
2225 return args
2226
2227 def parse_known_intermixed_args(self, args=None, namespace=None):
2228 # self - argparse parser
2229 # args, namespace - as used by parse_known_args
2230 # returns a namespace and list of extras
2231
2232 # positional can be freely intermixed with optionals
2233 # optionals are first parsed with all positional arguments deactivated
2234 # the 'extras' are then parsed
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
2240
2241 positionals = self._get_positional_actions()
2242 a = [action for action in positionals if action.nargs in [PARSER, REMAIN DER]]
2243 if a:
2244 raise TypeError('parse_intermixed_args: positional arg with nargs=%s '%a[0].nargs)
2245
2246 if [action.dest for group in self._mutually_exclusive_groups
2247 for action in group._group_actions if action in positionals]:
2248 raise TypeError('parse_intermixed_args: positional in mutuallyExclus iveGroup')
2249
2250 save_usage = self.usage
2251 try:
2252 if self.usage is None:
2253 # capture the full usage for use in error messages
2254 self.usage = self.format_usage()[7:]
2255 for action in positionals:
2256 # deactivate positionals
2257 action.save_nargs = action.nargs
2258 # action.nargs = 0
2259 action.nargs = SUPPRESS
2260 action.save_default = action.default
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
2292 finally:
2293 self.usage = save_usage
2294 return namespace, extras
2209 2295
2210 # ======================== 2296 # ========================
2211 # Value conversion methods 2297 # Value conversion methods
2212 # ======================== 2298 # ========================
2213 def _get_values(self, action, arg_strings): 2299 def _get_values(self, action, arg_strings):
2214 # for everything but PARSER, REMAINDER args, strip out first '--' 2300 # for everything but PARSER, REMAINDER args, strip out first '--'
2215 if action.nargs not in [PARSER, REMAINDER]: 2301 if action.nargs not in [PARSER, REMAINDER]:
2216 try: 2302 try:
2217 arg_strings.remove('--') 2303 arg_strings.remove('--')
2218 except ValueError: 2304 except ValueError:
(...skipping 26 matching lines...) Expand all
2245 self._check_value(action, value) 2331 self._check_value(action, value)
2246 2332
2247 # REMAINDER arguments convert all values, checking none 2333 # REMAINDER arguments convert all values, checking none
2248 elif action.nargs == REMAINDER: 2334 elif action.nargs == REMAINDER:
2249 value = [self._get_value(action, v) for v in arg_strings] 2335 value = [self._get_value(action, v) for v in arg_strings]
2250 2336
2251 # PARSER arguments convert all values, but check only the first 2337 # PARSER arguments convert all values, but check only the first
2252 elif action.nargs == PARSER: 2338 elif action.nargs == PARSER:
2253 value = [self._get_value(action, v) for v in arg_strings] 2339 value = [self._get_value(action, v) for v in arg_strings]
2254 self._check_value(action, value[0]) 2340 self._check_value(action, value[0])
2341
2342 # SUPPRESS argument does not put anything in the namespace
2343 elif action.nargs == SUPPRESS:
2344 value = SUPPRESS
2255 2345
2256 # all other types of nargs produce a list 2346 # all other types of nargs produce a list
2257 else: 2347 else:
2258 value = [self._get_value(action, v) for v in arg_strings] 2348 value = [self._get_value(action, v) for v in arg_strings]
2259 for v in value: 2349 for v in value:
2260 self._check_value(action, v) 2350 self._check_value(action, v)
2261 2351
2262 # return the converted value 2352 # return the converted value
2263 return value 2353 return value
2264 2354
(...skipping 98 matching lines...) Expand 10 before | Expand all | Expand 10 after
2363 2453
2364 Prints a usage message incorporating the message to stderr and 2454 Prints a usage message incorporating the message to stderr and
2365 exits. 2455 exits.
2366 2456
2367 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
2368 should either exit or raise an exception. 2458 should either exit or raise an exception.
2369 """ 2459 """
2370 self.print_usage(_sys.stderr) 2460 self.print_usage(_sys.stderr)
2371 args = {'prog': self.prog, 'message': message} 2461 args = {'prog': self.prog, 'message': message}
2372 self.exit(2, _('%(prog)s: error: %(message)s\n') % args) 2462 self.exit(2, _('%(prog)s: error: %(message)s\n') % args)
OLDNEW
« no previous file with comments | « Doc/library/argparse.rst ('k') | Lib/test/test_argparse.py » ('j') | no next file with comments »

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