"""
Assembles subcommands and provides top-level script.
"""
import argparse
from argparse import (RawDescriptionHelpFormatter, OPTIONAL,
ZERO_OR_MORE, ONE_OR_MORE, REMAINDER, PARSER)
import logging
import pkgutil
import sys
from importlib import import_module
from dawgtools import commands, __doc__ as docstring, __version__
[docs]
def parse_arguments(argv):
"""
Create the argument parser
"""
parser = argparse.ArgumentParser(
description=docstring, formatter_class=MyRawDescriptionHelpFormatter)
parser.add_argument('-V', '--version', action='version',
version=__version__,
help='Print the version number and exit')
parser.add_argument('-v', '--verbose',
action='count', dest='verbosity', default=1,
help='Increase verbosity of screen output (eg, -v is verbose, '
'-vv more so)')
parser.add_argument('-q', '--quiet',
action='store_const', dest='verbosity', const=0,
help='Suppress output')
##########################
# Setup all sub-commands #
##########################
subparsers = parser.add_subparsers(dest='subparser_name', title='actions')
# Begin help sub-command
parser_help = subparsers.add_parser(
'help', help='Detailed help for actions using `help <action>`')
parser_help.add_argument('action', nargs=1)
# End help sub-command
# Organize submodules by argv
modules = [name for _, name, _ in pkgutil.iter_modules(commands.__path__)]
modules = [m for m in modules if not m.startswith('_')]
# `run` will contain the module corresponding to a single
# subcommand if provided; otherwise, generate top-level help
# message from all submodules in `modules`.
run = list(filter(lambda name: name in argv, modules))
actions = {}
for name in run or modules:
# set up subcommand help text. The first line of the dosctring
# in the module is displayed as the help text in the
# script-level help message (`script -h`). The entire
# docstring is displayed in the help message for the
# individual subcommand ((`script action -h`))
# if no individual subcommand is specified (run_action[False]),
# a full list of docstrings is displayed
mod = import_module('{}.{}'.format(commands.__name__, name))
if mod.__doc__.strip():
helpstr = mod.__doc__.lstrip().split('\n', 1)[0]
else:
helpstr = '<add help text in docstring>'
subparser = subparsers.add_parser(
name, help=helpstr,
description=mod.__doc__,
formatter_class=MyRawDescriptionHelpFormatter)
mod.build_parser(subparser)
actions[name] = mod.action
# Determine we have called ourself (e.g. "help <action>")
# Set arguments to display help if parameter is set
# *or*
# Set arguments to perform an action with any specified options.
arguments = parser.parse_args(argv)
# Determine which action is in play.
action = arguments.subparser_name
# Support help <action> by simply having this function call itself and
# translate the arguments into something that argparse can work with.
if action is None:
return parse_arguments(['-h'])
elif action == 'help':
return parse_arguments([str(arguments.action[0]), '-h'])
else:
return actions[action], arguments
def main(argv=None):
if argv is None:
argv = sys.argv[1:]
action, arguments = parse_arguments(argv)
loglevel = {
0: logging.ERROR,
1: logging.WARNING,
2: logging.INFO,
3: logging.DEBUG,
}.get(arguments.verbosity, logging.DEBUG)
if arguments.verbosity > 1:
logformat = '%(levelname)s %(module)s.%(funcName)s() %(lineno)s %(message)s'
else:
logformat = '%(message)s'
logging.basicConfig(stream=sys.stderr, format=logformat, level=loglevel)
return action(arguments)