classification
Title: argparse: parse_known_args: raising exception on unknown arg following known one
Type: Stage:
Components: Library (Lib) Versions: Python 3.6
process
Status: open Resolution:
Dependencies: Superseder:
Assigned To: Nosy List: actionless, bethard, paul.j3
Priority: normal Keywords:

Created on 2018-02-03 12:31 by actionless, last changed 2018-03-19 17:26 by paul.j3.

Pull Requests
URL Status Linked Edit
PR 5512 open actionless, 2018-02-03 12:31
Messages (6)
msg311546 - (view) Author: Yauhen (actionless) * Date: 2018-02-03 12:31
steps to reproduce:

    import argparse
    import sys
    
    parser = argparse.ArgumentParser(prog=sys.argv[0], add_help=False)
    parser.add_argument('-a', action='store_true')
    parsed_args, unknown_args = parser.parse_known_args(sys.argv[1:])
    print(parsed_args)
    print(unknown_args)


Expected result:

$ python arparse_test.py -ab
Namespace(a=True)
['b']


Actual result:

$ python arparse_test.py -ab
usage: arparse_test.py [-a]
arparse_test.py: error: argument -a: ignored explicit argument 'b'
msg311548 - (view) Author: Yauhen (actionless) * Date: 2018-02-03 12:42
It was a mistake in expected result, should be:

$ python arparse_test.py -ab -c
Namespace(a=True)
['-b', '-c']
msg312151 - (view) Author: paul j3 (paul.j3) * Date: 2018-02-14 02:23
This error message is intentional.

In         def consume_optional(start_index):

            # identify additional optionals in the same arg string
            # (e.g. -xyz is the same as -x -y -z if no args are required)

                    # if the action is a single-dash option and takes no
                    # arguments, try to parse more single-dash options out
                    # of the tail of the option string
                    chars = self.prefix_chars
                    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)

In other words, it doesn't just split off that extra character and add it to 'argument_strings' for further handling.

Either 'b' is an argument for the '-a' flag or it is a '-b' flag itself.  It can't be a positional or extra.
msg312152 - (view) Author: paul j3 (paul.j3) * Date: 2018-02-14 02:27
Try adding a simple positional argument.  '-ab' would still produce this error.
msg312171 - (view) Author: Yauhen (actionless) * Date: 2018-02-14 11:22
I am adding one more testcase in order to clarify more the problem:



import argparse
import sys

parser = argparse.ArgumentParser(prog=sys.argv[0], add_help=False)
parser.add_argument('-a', action='store_true')
parser.add_argument('-b', action='store_true')
parser.add_argument('-c', action='store_true')
parsed_args, unknown_args = parser.parse_known_args(sys.argv[1:])
print(parsed_args)
print(unknown_args)



$ python argparse_test.py -ab
Namespace(a=True, b=True, c=False)
[]


Expected result:
$ python argparse_test.py -ab -cd
Namespace(a=True, b=True, c=True)
['-d']

Actual result:
$ python argparse_test.py -ab -cd
usage: argparse_test.py [-a] [-b] [-c]
argparse_test.py: error: argument -c: ignored explicit argument 'd'
msg314104 - (view) Author: paul j3 (paul.j3) * Date: 2018-03-19 17:26
From the documentation, 16.4.4.1. Option value syntax

> For short options (options only one character long), the option and its value can be concatenated:

> Several short options can be joined together, using only a single - prefix, as long as only the last option (or none of them) requires a value:

It does not promise that an short option and an unrelated (not-required) value will work.  The only value that works in such a construct is one required by the last short option.

I think this should be closed, unless you can support your expectations from documentation, or examples from other parsers.
History
Date User Action Args
2018-03-19 17:26:11paul.j3setmessages: + msg314104
2018-02-14 11:22:55actionlesssetmessages: + msg312171
2018-02-14 02:27:23paul.j3setmessages: + msg312152
2018-02-14 02:23:57paul.j3setmessages: + msg312151
2018-02-12 22:04:53paul.j3setnosy: + paul.j3
2018-02-09 23:18:48terry.reedysetnosy: + bethard
2018-02-03 12:42:53actionlesssetmessages: + msg311548
2018-02-03 12:31:44actionlesscreate