Python argparse option concatenation
Question: Normally you can concatenate options like '-abbb', which will expand to '-a -b
-b -b'. Counts would be 1 for a, abd 3 for b.

However when mixing prefix_chars I see something different ...

    
    
    import argparse
    parser = argparse.ArgumentParser( prefix_chars='-+' )
    parser.add_argument( '-x', action='count', dest='counter1' )
    parser.add_argument( '+x', action='count', dest='counter2' )
    args = parser.parse_args( '-xxx +xxx -xxx'.split() )
    print( 'counter1 = ' + str(args.counter1) )
    print( 'counter2 = ' + str(args.counter2) )
    

Running this results in:

    
    
    counter1 = 8
    counter2 = 1
    

Apparently '+xxx' doesn't expand to '+x +x +x', but to '+x -x -x'.

Changing the prefix_chars to '+-' results in:

    
    
    counter1 = 2
    counter2 = 7
    

Now '-xxx' expands to '-x +x +x'.

Is this defined behaviour, or am I missing something?


Answer: This was patched in late 2010, in early 2.7

<http://bugs.python.org/issue9352>

================

I'm not aware of bug/issues or code changes that would affect this, but I
could dig into it.

For a start, strings of single prefix options are handled rather deeply in the
parsing. In the current `argparse.py` the relevant code is:

    
    
    class ArgumentParser
      def _parse_known_args
        # function to convert arg_strings into an optional action
          def consume_optional(start_index):
    
            match_argument = self._match_argument
            action_tuples = []
            while True:
                ...
                    chars = self.prefix_chars  # e.g. the `-+` parameter
                    if arg_count == 0 and option_string[1] not in chars:
                        action_tuples.append((action, [], option_string))
                        char = option_string[0]
                        option_string = char + explicit_arg[0]
                        new_explicit_arg = explicit_arg[1:] or None
                        optionals_map = self._option_string_actions
                        if option_string in optionals_map:
                            action = optionals_map[option_string]
                            explicit_arg = new_explicit_arg
                        else:
                            msg = _('ignored explicit argument %r')
                            raise ArgumentError(action, msg % explicit_arg)
    

It's the pair of lines:

    
    
     char = option_string[0]
     option_string = char + explicit_arg[0]
    

that preserves the initial `-/+` when handling the repeated characters (in the
unparsed `explicit_arg` string.

I can imagine the case where the code split `+xyz` into `+x`,`-y`,`-z`, and
was corrected to use `+x`,`+y`,`+z`. But it will require some digging into
bug/issues and/or the Python repository to find out if and when that change
was made.

What does your problem `argparse.py` have at this point?

