Issue 22909: [argparse] Using parse_known_args, unknown arg with space in value is interpreted as first positional arg (original) (raw)

If using parse_known_args() to get argument pass-through, and one of the "unknown" arguments has a value with a space in it (even if quoted!), the entire unknown argument (key=value) will be interpreted as the value of the first positional argument instead.

Example:

import argparse
parser = argparse.ArgumentParser()
parser.add_argument("pos", nargs="?", default=None)

parser.parse_known_args(["--foo='bar'"])
# (Namespace(pos=None), ['--foo=bar'])
# As expected.

parse.parse_known_args(["--foo='bar baz'"])
# (Namespace(pos="--foo='bar baz'"), [])
# What?!?

Since known arguments with spaces in them are parsed fine, this looks to be regression in a lesser-used feature.

This an issue for parse_args as well. parse_args just calls parse_known_args, and raises an error if extras is not empty.

Early on in parsing, it tries to classify argument strings as either optionals (--flags) or positionals (arguments). And there's an explicit test for spaces:

def _parse_optional(self, arg_string):
    ...
    # if it contains a space, it was meant to be a positional
    if ' ' in arg_string:
        return None

Basically, if it can't match the string with a define optional, and it contains a space (anywhere) it is classed as positional. That's what your example shows.

It sounds familiar, so I suspect it was raised in an earlier issue. I'll have to look it up.