@@ -893,7 +893,7 @@ def _get_subparsers_action(self) -> argparse._SubParsersAction: # type: ignore[
893893 def update_prog (self , prog : str ) -> None :
894894 """Recursively update the prog attribute of this parser and all of its subparsers.
895895
896- :param prog: new value for the parser's prog attribute
896+ :param prog: new value for this parser's prog attribute
897897 """
898898 # Set the prog value for this parser
899899 self .prog = prog
@@ -916,26 +916,21 @@ def update_prog(self, prog: str) -> None:
916916 formatter .add_usage (self .usage , positionals , self ._mutually_exclusive_groups , '' )
917917 action ._prog_prefix = formatter .format_help ().strip ()
918918
919- # The keys of action.choices are subcommand names as well as subcommand aliases.
920- # The aliases point to the same parser as the actual subcommand. We want to avoid
921- # placing an alias into a parser's prog value. Unfortunately there is nothing about
922- # an action.choices entry which tells us it's an alias. In most cases we can filter out
923- # the aliases by checking the contents of action._choices_actions. This list only contains
924- # help information and names for the subcommands and not aliases. However, subcommands
925- # without help text won't show up in that list. Since dictionaries are ordered and
926- # argparse inserts the subcommand name into choices dictionary before aliases, we should
927- # be OK assuming the first time we see a parser, the dictionary key is a subcommand and
928- # not an alias.
929- processed_parsers : list [argparse .ArgumentParser ] = []
919+ # Note: action.choices contains both subcommand names and aliases.
920+ # To ensure subcommands (and not aliases) are used in 'prog':
921+ # 1. We can't use action._choices_actions because it excludes subcommands without help text.
922+ # 2. Since dictionaries are ordered and argparse inserts the primary name before aliases,
923+ # we assume the first time we encounter a parser, the key is the true subcommand name.
924+ updated_parsers : set [argparse .ArgumentParser ] = set ()
930925
931926 # Set the prog value for each subcommand's parser
932927 for subcmd_name , subcmd_parser in action .choices .items ():
933- if subcmd_parser in processed_parsers :
928+ if subcmd_parser in updated_parsers :
934929 continue
935930
936931 subcmd_prog = f"{ action ._prog_prefix } { subcmd_name } "
937932 subcmd_parser .update_prog (subcmd_prog ) # type: ignore[attr-defined]
938- processed_parsers . append (subcmd_parser )
933+ updated_parsers . add (subcmd_parser )
939934
940935 # We can break since argparse only allows 1 group of subcommands per level
941936 break
0 commit comments