diff -r 8a364deb0225 Lib/argparse.py --- a/Lib/argparse.py Thu May 02 10:44:04 2013 -0700 +++ b/Lib/argparse.py Thu May 16 21:58:45 2013 -0700 @@ -92,6 +92,15 @@ from gettext import gettext as _, ngettext +import logging as _logging +_logging.basicConfig(filename='issue9338.log',level=_logging.DEBUG) + +def _log(*args): + pass +_log = print +def _log(*args): + _logging.info(args) + SUPPRESS = '==SUPPRESS==' @@ -1795,6 +1804,8 @@ # join the pieces together to form the pattern arg_strings_pattern = ''.join(arg_string_pattern_parts) + alt_opt_length = self._get_alt_length(arg_strings,option_string_indices) + # converts arg strings to the appropriate and then takes the action seen_actions = set() seen_non_default_actions = set() @@ -1880,6 +1891,14 @@ start = start_index + 1 selected_patterns = arg_strings_pattern[start:] arg_count = match_argument(action, selected_patterns) + + alt_count = alt_opt_length.get(action.dest,None) + if alt_count is not None: + _log('opt counts', action.dest, arg_count, alt_count, selected_patterns) + if alt_count1: + pat_opts.extend(pat_opts) + pat_opts = ''.join(pat_opts) + # combine the pieces + pat = [pat_opts] + for p in pos: + #pp = '(?P<%s>A%s)'%p no need to name positionals groups + pp = '(A%s)'%p[1] + pat.append(pp) + pat.append(pat_opts) + pat = ''.join(pat) + pat = _re.compile(pat) + _log('pattern:', pat.pattern) + + # construct the argument strings patterns, modeled on the '-OA' + # but with explicit optionals strings + # + alt_pattern_parts = [] + arg_strings_iter = iter(arg_strings) + for i, arg_string in enumerate(arg_strings_iter): + + # all args after -- are non-options + if arg_string == '--': + for arg_string in arg_strings_iter: + alt_pattern_parts.append('A') + + # otherwise, add the arg to the arg strings + # and note the index if it was an option + else: + option_tuple = self._parse_optional(arg_string) + if option_tuple is None: + alt_pattern_parts.append('A') + else: + action, option_string, explicit_arg = option_tuple + if action and action.dest in ['help','version']: + # don't do anything more if -h + return {} + if 'A' in option_string: + return {'error':'"A" in option string'} + alt_pattern_parts.append(option_string) + if explicit_arg is not None: + return {'warning': 'explicit arg: %s'%arg_string} + # --foo=1 and -f1 shouldn't cause issue problems + # since the arg is bound to the optional + # but they are hard to fit in this pattern matching + alt_pattern = ''.join(alt_pattern_parts) + _log('arg_pat:', alt_pattern) + + # can I focus on the args that are an issue and ignore rest? + # e.g. optional with variable nargs (?+*) followed by positional + # + + m = pat.match(alt_pattern) + if m: + # look for optionals in the match groups + # extract the number of arguments allowed for each + pat = '(-[^A]*)(A*)' + for g in m.groups(): + if g: + mm1 = _re.search(pat, g) + if mm1: + ostr = mm1.group(1); args = mm1.group(2) + ostr = self._option_string_actions[ostr].dest + alt_opt_length[ostr] = len(args) + else: + if not _re.match('A*',g): + # not a normal positional + return {'error':'group not opt: %s'%(g)} + else: + return {'error': 'global pattern does not match'} + return alt_opt_length + + # ======================== # Value conversion methods # ========================