KEMBAR78
allow_abbrev=False does not work for single-dash long options · Issue #104860 · python/cpython · GitHub
Skip to content

allow_abbrev=False does not work for single-dash long options #104860

@SunCrazy

Description

@SunCrazy

Bug report

The following codes get different results between python3.6.9 and python3.8.10

import argparse


if __name__ == "__main__":
    parser = argparse.ArgumentParser(
        allow_abbrev=False
    )

    parser.add_argument('-on', "--output-name", type=str, help="output")

    args, _ = parser.parse_known_args(["-on", "name", "-o", "dir"])
    print(args)

python3.6.9

[chenf@b12e0231:/mnt/ssd/chenf/projects/test_hhb_2.4/debug/cmd_config]$ python3 --version
Python 3.6.9
[chenf@b12e0231:/mnt/ssd/chenf/projects/test_hhb_2.4/debug/cmd_config]$ python3 ~/test.py
Namespace(output_name='name')

python3.8.10

[chenf@b11b0623:/mnt/ssd/chenf/project/hhb_test_2.4/cmd_config]$ python3 --version
Python 3.8.10
[chenf@b11b0623:/mnt/ssd/chenf/project/hhb_test_2.4/cmd_config]$ python3 ~/test.py
Namespace(output_name='dir')

Debug

I have tried to debug the codes and get some clues.

I have set the allow_abbrev=False to disable prefix match, but it works in python3.6.9 and fails in python3.8.10.
When I div into argparse.py and find that it considers the allow_abbrev in python3.6.9 but not in python3.8.10 as follow:

in python3.6.9 argparse.py

def _parse_optional(self, arg_string):
    ....

    if self.allow_abbrev:
            # search through all possible prefixes of the option string
            # and all actions in the parser for possible interpretations
            option_tuples = self._get_option_tuples(arg_string)

            # if multiple actions match, the option string was ambiguous
            if len(option_tuples) > 1:
                options = ', '.join([option_string
                    for action, option_string, explicit_arg in option_tuples])
                args = {'option': arg_string, 'matches': options}
                msg = _('ambiguous option: %(option)s could match %(matches)s')
                self.error(msg % args)

            # if exactly one action matched, this segmentation is good,
            # so return the parsed action
            elif len(option_tuples) == 1:
                option_tuple, = option_tuples
                return option_tuple
    ....

in python3.8.10 argparse.py

def _parse_optional(self, arg_string):
    ....

    # search through all possible prefixes of the option string
        # and all actions in the parser for possible interpretations
        option_tuples = self._get_option_tuples(arg_string)

        # if multiple actions match, the option string was ambiguous
        if len(option_tuples) > 1:
            options = ', '.join([option_string
                for action, option_string, explicit_arg in option_tuples])
            args = {'option': arg_string, 'matches': options}
            msg = _('ambiguous option: %(option)s could match %(matches)s')
            self.error(msg % args)

        # if exactly one action matched, this segmentation is good,
        # so return the parsed action
        elif len(option_tuples) == 1:
            option_tuple, = option_tuples
            return option_tuple
    
    ....

Linked PRs

Metadata

Metadata

Labels

3.12only security fixes3.13bugs and security fixes3.14bugs and security fixesstdlibStandard Library Python modules in the Lib/ directorytype-bugAn unexpected behavior, bug, or error

Projects

Status

Doc issues

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions