Reputation: 27
With argparse, currently my main.py --help
looks like this
usage: main.py [--options] <command>
options:
-h, --help show this help message and exit
--debug Logs extra information for debugging
--version show program's version number and exit
--license reads the GPLv3
commands:
install install packages
remove remove packages
update update package list and upgrade the system
is there an easy way to make the subparser commands display before the global options?
my configuration is a bit long to post at the moment but I can if context is needed. I don't have anything crazy going on, this is the important stuff.
formatter = lambda prog: argparse.RawDescriptionHelpFormatter(prog,
max_help_position=64)
bin_name = Path(argv[0]).name
version = __version__
parser = nalaParser( formatter_class=formatter,
usage=f'{bin_name} [--options] <command>',
)
subparsers = parser.add_subparsers(title='commands', metavar='', dest='command')
parser._optionals.title = "options"
install_parser = subparsers.add_parser('install', help='install packages')
remove_parser = subparsers.add_parser('remove', help='remove packages')
update_parser = subparsers.add_parser('update', help='update package list and upgrade the system')
parser.add_argument('--debug', action='store_true', help='Logs extra information for debugging')
parser.add_argument('--version', action='version', version=f'{bin_name} {version}')
parser.add_argument('--license', action=GPLv3)
Since I was already subclassing I just added this method below to nalaParser
def format_help(self):
formatter = self._get_formatter()
# usage
formatter.add_usage(self.usage, self._actions,
self._mutually_exclusive_groups)
# description
formatter.add_text(self.description)
index = -1
# Put options last in the group
for action_group in self._action_groups[:]:
index = + 1
if action_group.title == 'options':
self._action_groups.append(self._action_groups.pop(index))
# positionals, optionals and user-defined groups
for action_group in self._action_groups:
formatter.start_section(action_group.title)
formatter.add_text(action_group.description)
formatter.add_arguments(action_group._group_actions)
formatter.end_section()
# epilog
formatter.add_text(self.epilog)
# determine help from format above
return formatter.format_help()
Upvotes: 0
Views: 387
Reputation: 12047
You could override the format_help
method of argparse.ArgumentParser
and rearrange the order of the action groups before calling super()
.
class MyParser(ArgumentParser):
def format_help(self):
# Put options last in the group
opitions_action_group = [a for a in self._action_groups if a.title == 'options']
self._action_groups = [a for a in self._action_groups if a.title != 'options']
if opitions_action_group:
self._action_groups.append(opitions_action_group[0])
return super().format_help()
# Parent parser (so 'help' is available for all sub-parsers).
parent_parser = MyParser()
# Main parser.
desc = ('Take some action as described below.')
main_parser = MyParser(description=desc, add_help=False, formatter_class=HelpFormatter, parents=[parent_parser])
# Sub-parsers.
subparsers = main_parser.add_subparsers(title='action')
subparsers.add_parser('action1', add_help=False, parents=[parent_parser], description='Description of action1.')
subparsers.add_parser('action2', add_help=False, parents=[parent_parser], description='Description of action2.')
subparsers.add_parser('action3', add_help=False, parents=[parent_parser], description='Description of action3.')
main_parser.parse_args()
Parsing the above with -h
results in the following...
usage: cs-aws [-h] {action1,action2,action3} ...
Take some action as described below.
action:
{action1,action2,action3}
options:
-h, --help show this help message and exit
Upvotes: 0
Reputation: 231355
parser.format_help
passes the action_groups
to the formatter in the order that they were created.
In [24]: parser._action_groups
Out[24]:
[<argparse._ArgumentGroup at 0x7f8167ac02e0>,
<argparse._ArgumentGroup at 0x7f8167ac0850>,
<argparse._ArgumentGroup at 0x7f8167ac0490>]
In [25]: [a.title for a in parser._action_groups]
Out[25]: ['positional arguments', 'options', 'commands']
The default groups are positional
and options
. add_subparsers
puts its Action in the positional
group, except when given a title
. In that case it makes a new group.
You could tweak the format_help
to reorder the groups that it passes to the formatter.
Or it might work to change the 'positional arguments' title as you did with the optionals (instead of giving subparsers
the title
parameter).
Anyways, the key to the behavior is in these two methods.
Upvotes: 1