From 23fd41ce03631afaf2024521c5bc65c04ed41b89 Mon Sep 17 00:00:00 2001 From: TheOnePath Date: Tue, 4 Jul 2023 20:51:45 +0100 Subject: [PATCH] Added parser.py Added soypak parser module using argparse to parse arguments, also have a custom help screen. --- soypak/cli/parser.py | 74 ++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 74 insertions(+) create mode 100644 soypak/cli/parser.py diff --git a/soypak/cli/parser.py b/soypak/cli/parser.py new file mode 100644 index 0000000..ca5fcbc --- /dev/null +++ b/soypak/cli/parser.py @@ -0,0 +1,74 @@ +import argparse +import textwrap +from typing import Iterable + +import soypak.__version__ as module_info + + +class OverrideHelpFormatter(argparse.RawDescriptionHelpFormatter, argparse.HelpFormatter): + """Override class for argparse help message display. + + Using both `argparse@RawDescriptionHelpFormatter` and `argparse@HelpFormatter` to gain custom epilogue and usage + title. To be used as parameter value for `formatter_class=` during `argparse@ArgumentParser` construction. + """ + def add_usage(self, usage: str | None, actions: Iterable[argparse.Action], + groups: Iterable[argparse._MutuallyExclusiveGroup], prefix: str | None = None) -> None: + return super().add_usage(usage, actions, groups, 'Usage: ') + + +class SoypakParser(argparse.ArgumentParser): + """soypak parsing and translating program arguments given by `sys.argv`. + + Class constructs a custom help message display which is shown with arguments `-h|--help` or when an invalid argument + is passed. There is mangling of attributes in in the parent class to provide a modern, simplistic, and coherent help + message display found with other package managers. + """ + def __init__(self) -> None: + self.NAME = module_info.__title__ + USAGE = "%(prog)s [options] [arguments]" + DESC = module_info.__description__ + EPILOGUE = textwrap.dedent("""\ + Author(s): %(authors)s. + Contacts: %(emails)s + + Thanks for using our software %(biscuit)s + %(copyright)s. Licensed under %(licence)s + """ % { + "authors": ", ".join(module_info.__authors__), + "emails": ", ".join(module_info.__emails__), + "copyright": module_info.__copyright__, + "licence": module_info.__licence__, + "biscuit": module_info.__biscuit__ + }) + self.VERSION = "%s %s" % (self.NAME, module_info.__version__) + + super().__init__( + prog=self.NAME, usage=USAGE, description=DESC, epilog=EPILOGUE, + allow_abbrev=False, formatter_class=OverrideHelpFormatter, + ) + + # override the default title for positional arguments + self._positionals.title = "Where is one of" + self._optionals.title = "Options" + + # this argument will take the value of whatever the first argument supplied is. Any additional positional + # arguments will be collected separately + self.add_argument("command", nargs='?') + + # overwrite the action group. @Note: this is to give custom positional arguments in the help message but aren't + # actual arguments. They are stored in the "command" attribute (defined above). + # :@TODO: When commands are registered, allow the register to submit info for the action group. This overwrite + # will then be configured using all the register commands. + self._positionals._group_actions = [] + ### argparse._StoreAction(option_strings=[], dest=cmd, help=desc) + + # optional arguments + self.add_argument("--version", action="store_true", + help="show the program's version number and exit") + + + def parse_args(self) -> tuple[str, list]: + # we use `parse_known_args` to allow for splitting of largs/rargs + self.namespace, self.rargs = self.parse_known_args() + + return (self.namespace.command, self.rargs)