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

Unified Diff: Lib/argparse.py

Issue 14191: argparse: nargs='*' doesn't get out-of-order positional parameters
Patch Set: Created 6 years, 10 months ago
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 side-by-side diff with in-line comments
Download patch
« no previous file with comments | « Doc/library/argparse.rst ('k') | Lib/test/test_argparse.py » ('j') | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
--- a/Lib/argparse.py Mon May 27 23:53:02 2013 -0400
+++ b/Lib/argparse.py Wed May 29 22:27:18 2013 -0700
@@ -581,6 +581,8 @@
result = '...'
elif action.nargs == PARSER:
result = '%s ...' % get_metavar(1)
+ elif action.nargs == SUPPRESS:
+ result = ''
else:
formats = ['%s' for _ in range(action.nargs)]
result = ' '.join(formats) % get_metavar(action.nargs)
@@ -2195,6 +2197,10 @@
elif nargs == PARSER:
nargs_pattern = '(-*A[-AO]*)'
+ # suppress action, like nargs=0
+ elif nargs == SUPPRESS:
+ nargs_pattern = '(-*-*)'
+
# all others should be integers
else:
nargs_pattern = '(-*%s-*)' % '-*'.join('A' * nargs)
@@ -2208,6 +2214,86 @@
return nargs_pattern
# ========================
+ # Alt command line argument parsing, allowing free intermix
+ # ========================
+
+ def parse_intermixed_args(self, args=None, namespace=None):
+ args, argv = self.parse_known_intermixed_args(args, namespace)
+ if argv:
+ msg = _('unrecognized arguments: %s')
+ self.error(msg % ' '.join(argv))
+ return args
+
+ def parse_known_intermixed_args(self, args=None, namespace=None):
+ # self - argparse parser
+ # args, namespace - as used by parse_known_args
+ # returns a namespace and list of extras
+
+ # positional can be freely intermixed with optionals
+ # optionals are first parsed with all positional arguments deactivated
+ # the 'extras' are then parsed
+ # if parser definition is incompatible with the intermixed assumptions
+ # returns a TypeError (e.g. use of REMAINDER, subparsers)
+
+ # positionals are 'deactivated' by setting nargs and default to SUPPRESS.
+ # This blocks the addition of that positional to the namespace
+
+ positionals = self._get_positional_actions()
+ a = [action for action in positionals if action.nargs in [PARSER, REMAINDER]]
+ if a:
+ raise TypeError('parse_intermixed_args: positional arg with nargs=%s'%a[0].nargs)
+
+ if [action.dest for group in self._mutually_exclusive_groups
+ for action in group._group_actions if action in positionals]:
+ raise TypeError('parse_intermixed_args: positional in mutuallyExclusiveGroup')
+
+ save_usage = self.usage
+ try:
+ if self.usage is None:
+ # capture the full usage for use in error messages
+ self.usage = self.format_usage()[7:]
+ for action in positionals:
+ # deactivate positionals
+ action.save_nargs = action.nargs
+ # action.nargs = 0
+ action.nargs = SUPPRESS
+ action.save_default = action.default
+ action.default = SUPPRESS
+ try:
+ namespace, remaining_args = self.parse_known_args(args, namespace)
+ for action in positionals:
+ # remove the empty positional values from namespace
+ if hasattr(namespace, action.dest) and getattr(namespace, action.dest)==[]:
+ from warnings import warn
+ warn('Do not expect %s in %s'%(action.dest,namespace))
+ delattr(namespace, action.dest)
+ finally:
+ # restore nargs and usage before exiting
+ for action in positionals:
+ action.nargs = action.save_nargs
+ action.default = action.save_default
+ # parse positionals
+ # optionals aren't normally required, but just in case, turn that off
+ optionals = self._get_optional_actions()
+ for action in optionals:
+ action.save_required = action.required
+ action.required = False
+ for group in self._mutually_exclusive_groups:
+ group.save_required = group.required
+ group.required = False
+ try:
+ namespace, extras = self.parse_known_args(remaining_args, namespace)
+ finally:
+ # restore parser values before exiting
+ for action in optionals:
+ action.required = action.save_required
+ for group in self._mutually_exclusive_groups:
+ group.required = group.save_required
+ finally:
+ self.usage = save_usage
+ return namespace, extras
+
+ # ========================
# Value conversion methods
# ========================
def _get_values(self, action, arg_strings):
@@ -2253,6 +2339,10 @@
value = [self._get_value(action, v) for v in arg_strings]
self._check_value(action, value[0])
+ # SUPPRESS argument does not put anything in the namespace
+ elif action.nargs == SUPPRESS:
+ value = SUPPRESS
+
# all other types of nargs produce a list
else:
value = [self._get_value(action, v) for v in arg_strings]
« 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+