• 
      

    Fix redundant help information being displayed for multi-commands.

    Review Request #12179 — Created March 18, 2022 and submitted — Latest diff uploaded

    Information

    RBTools
    release-3.x

    Reviewers

    Multi-commands (such as rbt review) had an issue where usage and help
    output would be displayed multiple times. On Python 2.7, we'd get a
    usage + help block, followed by a usage block, followed by another
    usage + help block. On newer versions, we'd just get two usage + help
    blocks.

    The reason this was happening has to do with how we handle help in
    RBTools. We have our own custom --help handler that's invoked before
    any commands are set up, which allows us to do rbt --help,
    rbt <command> --help, or rbt --help <command>, along with supporting
    passing --help to any third-party rbt-* scripts.

    When handling help for internal commands, we locate the right command
    class, check if it's a multi-command or a standard command, and attempt
    to get the right help information. For multi-commands, we do an explicit
    parse of the options, which will funnel the --help to the right
    subcommand if needed.

    This is where the problem was found. This test parse will see the
    --help and will result in ArgumentParser.print_help() being called,
    resulting in one usage + help block.

    Then, on Python 2.7, the argument parser notes that we haven't passed
    any required arguments for the subparser and triggers
    ArgumentParser.error(), which prints a second usage block.

    We then return formatted help, which includes the final usage + help
    block. This gets printed to the console.

    Solving this requires babysitting argparse a bit more.

    We no longer leave invocation to chance. Instead, we first check if
    there's a multi-command class, and then grab the first positional
    argument. If it matches a known subcommand, we pull out the class and
    build a new, fixed set of command line arguments that will generate new
    help output.

    This gives us full control of how help output is generated. We no longer
    need to stub argparse when invoking --help on a subcommand, and
    we're far less sensitive to Python version differences or the position
    of help or -h/--help.

    Tested the following on Python 2.7 and 3.8:

    • rbt help
    • rbt help <command>
    • rbt help <multi-command>
    • rbt help <multi-command> <subcommand>
    • rbt --help
    • rbt --help <command>
    • rbt --help <multi-command>
    • rbt --help <multi-command> <subcommand>
    • rbt <command> --help
    • rbt <multi-command> --help
    • rbt <multi-command> --help <subcommand>
    • rbt <multi-command> <subcommand> --help

    Commits

    Files