Skip to content

argparse sometimes tracebacks when all options in a mutually exclusive group are suppressed #96310

Closed
@dmach

Description

@dmach

Bug report

When a subparser contains a mutually exclusive group and the all options in the group are suppressed,
it sometimes errors out with a traceback. The crash depends on other options (their ordering and length) and terminal size.

Reproducer:

#!/usr/bin/python3

import argparse

parser = argparse.ArgumentParser()
commands = parser.add_subparsers(title="commands", dest="command")
cmd_foo = commands.add_parser("foo")
group = cmd_foo.add_mutually_exclusive_group()
group.add_argument('--verbose', action='store_true', help=argparse.SUPPRESS)
group.add_argument('--quiet', action='store_true', help=argparse.SUPPRESS)
cmd_foo.add_argument("--longlonglonglonglonglonglonglonglonglonglonglonglonglonglonglonglonglonglonglonglonglonglonglonglonglonglonglonglonglonglonglong")

parser.parse_args()
$ python3.11 reproducer.py foo --help
Traceback (most recent call last):
  File ".../reproducer.py", line 13, in <module>
    parser.parse_args()
  File "/usr/lib64/python3.11/argparse.py", line 1862, in parse_args
    args, argv = self.parse_known_args(args, namespace)
                 ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/usr/lib64/python3.11/argparse.py", line 1895, in parse_known_args
    namespace, args = self._parse_known_args(args, namespace)
                      ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/usr/lib64/python3.11/argparse.py", line 2085, in _parse_known_args
    positionals_end_index = consume_positionals(start_index)
                            ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/usr/lib64/python3.11/argparse.py", line 2062, in consume_positionals
    take_action(action, args)
  File "/usr/lib64/python3.11/argparse.py", line 1971, in take_action
    action(self, namespace, argument_values, option_string)
  File "/usr/lib64/python3.11/argparse.py", line 1234, in __call__
    subnamespace, arg_strings = parser.parse_known_args(arg_strings, None)
                                ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/usr/lib64/python3.11/argparse.py", line 1895, in parse_known_args
    namespace, args = self._parse_known_args(args, namespace)
                      ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/usr/lib64/python3.11/argparse.py", line 2103, in _parse_known_args
    start_index = consume_optional(start_index)
                  ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/usr/lib64/python3.11/argparse.py", line 2043, in consume_optional
    take_action(action, args, option_string)
  File "/usr/lib64/python3.11/argparse.py", line 1971, in take_action
    action(self, namespace, argument_values, option_string)
  File "/usr/lib64/python3.11/argparse.py", line 1112, in __call__
    parser.print_help()
  File "/usr/lib64/python3.11/argparse.py", line 2590, in print_help
    self._print_message(self.format_help(), file)
                        ^^^^^^^^^^^^^^^^^^
  File "/usr/lib64/python3.11/argparse.py", line 2574, in format_help
    return formatter.format_help()
           ^^^^^^^^^^^^^^^^^^^^^^^
  File "/usr/lib64/python3.11/argparse.py", line 286, in format_help
    help = self._root_section.format_help()
           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/usr/lib64/python3.11/argparse.py", line 217, in format_help
    item_help = join([func(*args) for func, args in self.items])
                     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/usr/lib64/python3.11/argparse.py", line 217, in <listcomp>
    item_help = join([func(*args) for func, args in self.items])
                      ^^^^^^^^^^^
  File "/usr/lib64/python3.11/argparse.py", line 341, in _format_usage
    assert ' '.join(opt_parts) == opt_usage
AssertionError

Please note that setting COLUMNS to a high number doesn't trigger the traceback:

COLUMNS=1000 python3.11 reproducer.py foo --help
usage: reproducer.py foo [-h]  [--longlonglonglonglonglonglonglonglonglonglonglonglonglonglonglonglonglonglonglonglonglonglonglonglonglonglonglonglonglonglonglong LONGLONGLONGLONGLONGLONGLONGLONGLONGLONGLONGLONGLONGLONGLONGLONGLONGLONGLONGLONGLONGLONGLONGLONGLONGLONGLONGLONGLONGLONGLONGLONG]

options:
  -h, --help            show this help message and exit
  --longlonglonglonglonglonglonglonglonglonglonglonglonglonglonglonglonglonglonglonglonglonglonglonglonglonglonglonglonglonglonglong LONGLONGLONGLONGLONGLONGLONGLONGLONGLONGLONGLONGLONGLONGLONGLONGLONGLONGLONGLONGLONGLONGLONGLONGLONGLONGLONGLONGLONGLONGLONGLONG

Your environment

  • CPython versions tested on: 3.8.13, 3.10.6, 3.11.0b5
  • openSUSE Tumbleweed 20220823

Linked PRs

Metadata

Metadata

Assignees

No one assigned

    Labels

    stdlibPython modules in the Lib dirtype-bugAn unexpected behavior, bug, or error

    Projects

    Status

    Doc issues

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions