CLI subcommands with precise help output

Chapter 160: CLI subcommands with precise help output

Different ways to create subcommands like in hg or svn with the exact command line interface and help output as shown in Remarks section.

Parsing Command Line arguments covers broader topic of arguments parsing.

Section 160.1: Native way (no libraries)

"""
usage: sub
commands:
status - show status
list - print list
"""
import sys
def check():
print("status")
return 0
if sys.argv[1:] == ['status']:
sys.exit(check())
elif sys.argv[1:] == ['list']:
print("list")
else:
print(doc.strip())

Output without arguments:

usage: sub
commands:
status - show status
list - print list

Pros:

no deps

everybody should be able to read that

complete control over help formatting

Section 160.2: argparse (default help formatter)

import argparse
import sys
def check():
print("status")
return 0

GoalKicker.com – Python® Notes for Professionals 639

parser = argparse.ArgumentParser(prog="sub", add_help=False)
subparser = parser.add_subparsers(dest="cmd")
subparser.add_parser('status', help='show status')
subparser.add_parser('list', help='print list')
hack to show help when no arguments supplied if len(sys.argv) == 1:
parser.print_help() sys.exit(0)
args = parser.parse_args()
if args.cmd == 'list':
print('list')
elif args.cmd == 'status':
sys.exit(check())

Output without arguments:

usage: sub {status,list} …
positional arguments:
{status,list}
status show status
list print list

Pros:

comes with Python

option parsing is included

Section 160.3: argparse (custom help formatter)

import argparse
import sys
class CustomHelpFormatter(argparse.HelpFormatter):
def _format_action(self, action):
if type(action) == argparse._SubParsersAction:
inject new class variable for subcommand formatting subactions = action._get_subactions()
invocations = [self._format_action_invocation(a) for a in subactions] self._subcommand_max_length = max(len(i) for i in invocations)
if type(action) == argparse._SubParsersAction._ChoicesPseudoAction:

format subcommand help line

subcommand = self._format_action_invocation(action) # type: str width = self._subcommand_max_length help_text = ""
if action.help:
help_text = self._expand_help(action)
return " {:{width}} - {}\n".format(subcommand, help_text, width=width)
elif type(action) == argparse._SubParsersAction:
process subcommand help section msg = '\n'
for subaction in action._get_subactions(): msg += self._format_action(subaction)
return msg

GoalKicker.com – Python® Notes for Professionals 640

else:
return super(CustomHelpFormatter, self)._format_action(action)
def check():
print("status")
return 0
parser = argparse.ArgumentParser(usage="sub ", add_help=False, formatter_class=CustomHelpFormatter)
subparser = parser.add_subparsers(dest="cmd")
subparser.add_parser('status', help='show status')
subparser.add_parser('list', help='print list')

custom help message

parser._positionals.title = "commands"
hack to show help when no arguments supplied if len(sys.argv) == 1:
parser.print_help() sys.exit(0)
args = parser.parse_args()
if args.cmd == 'list':
print('list')
elif args.cmd == 'status':
sys.exit(check())

Output without arguments:

usage: sub
commands:
status - show status
list - print list

Leave a Comment