|
"""Console script""" |
|
import sys |
|
import os |
|
import json |
|
import argparse |
|
import logging |
|
import platform |
|
import traceback |
|
import argcomplete |
|
|
|
from .states import cli as states_cli |
|
from . import __version__ |
|
|
|
|
|
class SupercommandArgumentParser(argparse.ArgumentParser): |
|
""" |
|
Super command argument parser. |
|
|
|
A super command is an argparse command with sub-commands |
|
that can be attached to it. |
|
|
|
This is implemented as an extension of the argparse.ArgParser |
|
class, but it also stores a list of subparsers in a |
|
private attribute self._subparsers. |
|
|
|
argument parsers can be registered as subparsers of this |
|
parent argument parser by registering with the add_parser_func() |
|
method. |
|
""" |
|
|
|
def __init__(self, *args, **kwargs): |
|
super(*args, **kwargs) |
|
self._subparsers = None |
|
|
|
def add_parser_func(self, func, **kwargs): |
|
if self._subparsers is None: |
|
self._subparsers = self.add_subparsers() |
|
|
|
# we were passed a function, add a subparser action corresponding to it. |
|
# auto-generate a safe name for this parser based on the function name. |
|
# func.__name__ is the magic here. |
|
subparser = self._subparsers.add_parser(func.__name__.replace("_", "-"), **kwargs) |
|
|
|
# set the entry point for this command line option to execute the function |
|
subparser.set_defaults(entry_point=func) |
|
|
|
# trust fall |
|
command = subparser.prog[len(self.prog) + 1 :].replace("-", "_").replace(" ", "_") |
|
subparser.set_defaults({}) |
|
# If the subparser has a description, use that. |
|
# Otherwise, if the "help" keyword arg was provided, use that. |
|
# Otherwise, use the docstring. |
|
if subparser.description is None: |
|
subparser.description = kwargs.get("help", func.__doc__) |
|
|
|
# Not sure why this is necessary... |
|
self._defaults.pop("entry_point", None) |
|
|
|
return subparser |
|
|
|
def print_help(self, file=None): |
|
formatted_help = self.format_help() |
|
formatted_help = formatted_help.replace("positional arguments:", "Positional Arguments:") |
|
formatted_help = formatted_help.replace("optional arguments:", "Optional Arguments:") |
|
print(formatted_help) |
|
self.exit() |
|
|
|
|
|
def get_parser(help_menu=False): |
|
|
|
parser = SupercommandArgumentParser( |
|
description=__doc__, formatter_class=argparse.RawTextHelpFormatter |
|
) |
|
version_string = "%(prog)s {version} ({python_impl} {python_version} {platform})".format( |
|
version=__version__, |
|
python_impl=platform.python_implementation(), |
|
python_version=platform.python_version(), |
|
platform=platform.platform(), |
|
) |
|
parser.add_argument("--version", action="version", version=version_string) |
|
|
|
# Add help options for this parser |
|
def halp(args): |
|
"""Print help message""" |
|
parser.print_help() |
|
|
|
parser.add_parser_func(halp) |
|
|
|
# Add subparser |
|
states_cli.add_commands(parser._subparsers, help_menu=help_menu) |
|
|
|
argcomplete.autocomplete(parser) |
|
return parser |
|
|
|
|
|
def main(args=None): |
|
|
|
if not args: |
|
args = sys.argv[1:] |
|
|
|
if "--help" in args or "-h" in args: |
|
parser = get_parser(help_menu=True) |
|
else: |
|
parser = get_parser() |
|
|
|
if len(args) < 1: |
|
parser.print_help() |
|
parser.exit(1) |
|
|
|
# Parse the arguments provided to main() function |
|
parsed_args = parser.parse_args(args=args) |
|
|
|
# Set logging levels for external libraries |
|
logging.basicConfig(level=logging.ERROR) |
|
|
|
try: |
|
# Call the entry point function, passing the parsed arguments |
|
result = parsed_args.entry_point(parsed_args) |
|
|
|
except Exception as e: |
|
# O noes!!1 |
|
err_msg = traceback.format_exc() |
|
print(err_msg, file=sys.stderr) |
|
exit(os.EX_SOFTWARE) |
|
|
|
else: |
|
if isinstance(result, SystemExit): |
|
raise result |
|
|
|
elif result is not None: |
|
if isinstance(result, bytes): |
|
sys.stdout.buffer.write(result) |
|
else: |
|
# The default arg here ensures smooth handling of datetime |
|
print(json.dumps(result, indent=4, default=lambda x: str(x))) |