diff options
author | Kevin Van Brunt <kmvanbrunt@gmail.com> | 2021-08-25 16:54:47 -0400 |
---|---|---|
committer | Kevin Van Brunt <kmvanbrunt@gmail.com> | 2021-09-01 13:33:22 -0400 |
commit | bf558c5c774685c5806e38d349ab2e129b76ef6b (patch) | |
tree | 8f6c1df1c9c22a5129a3de0f36e3bd5e5d511b26 /cmd2/argparse_custom.py | |
parent | 30b30cd48d2b3ac1e886e1e0bb868dc823414bef (diff) | |
download | cmd2-git-bf558c5c774685c5806e38d349ab2e129b76ef6b.tar.gz |
Refactored custom ArgparseCompleter functionality so they will now be set using methods on ArgumentParser objects.
This fixes issue where subcommands did not use the correct custom ArgparseCompleter type.
Diffstat (limited to 'cmd2/argparse_custom.py')
-rw-r--r-- | cmd2/argparse_custom.py | 68 |
1 files changed, 65 insertions, 3 deletions
diff --git a/cmd2/argparse_custom.py b/cmd2/argparse_custom.py index 44e7a90b..dd4db570 100644 --- a/cmd2/argparse_custom.py +++ b/cmd2/argparse_custom.py @@ -207,6 +207,13 @@ for cases in which you need to manually access the cmd2-specific attributes. - ``argparse.Action.set_suppress_tab_hint()`` - See :func:`_action_set_suppress_tab_hint` for more details. +cmd2 has patched ``argparse.ArgumentParser`` to include the following accessor methods + +- ``argparse.ArgumentParser.get_ap_completer_type()`` - See + :func:`_ArgumentParser_get_ap_completer_type` for more details. +- ``argparse.Action.set_ap_completer_type()`` - See + :func:`_ArgumentParser_set_ap_completer_type` for more details. + **Subcommand removal** cmd2 has patched ``argparse._SubParsersAction`` to include a ``remove_parser()`` @@ -232,6 +239,7 @@ from gettext import ( ) from typing import ( IO, + TYPE_CHECKING, Any, Callable, Dict, @@ -264,6 +272,12 @@ except ImportError: ) +if TYPE_CHECKING: # pragma: no cover + from .argparse_completer import ( + ArgparseCompleter, + ) + + def generate_range_error(range_min: int, range_max: Union[int, float]) -> str: """Generate an error message when the the number of arguments provided is not within the expected range""" err_str = "expected " @@ -659,6 +673,7 @@ def register_argparse_argument_parameter(param_name: str, param_type: Optional[T and ``set_{param_name}(value)``. :param param_name: Name of the parameter to add. + :param param_type: Type of the parameter to add. """ attr_name = f'{_CUSTOM_ATTRIB_PFX}{param_name}' if param_name in CUSTOM_ACTION_ATTRIBS or hasattr(argparse.Action, attr_name): @@ -715,6 +730,7 @@ def register_argparse_argument_parameter(param_name: str, param_type: Optional[T orig_actions_container_add_argument = argparse._ActionsContainer.add_argument +# noinspection PyProtectedMember def _add_argument_wrapper( self: argparse._ActionsContainer, *args: Any, @@ -916,10 +932,54 @@ setattr(argparse.ArgumentParser, '_match_argument', _match_argument_wrapper) ############################################################################################################ -# Patch argparse._SubParsersAction to add remove_parser function +# Patch argparse.ArgumentParser with accessors for ap_completer_type attribute ############################################################################################################ +# An ArgumentParser attribute which specifies a subclass of ArgparseCompleter for custom tab completion behavior on a +# given parser. If this is None or not present, then cmd2 will use argparse_completer.DEFAULT_AP_COMPLETER when tab +# completing a parser's arguments +ATTR_AP_COMPLETER_TYPE = 'ap_completer_type' + + # noinspection PyPep8Naming +def _ArgumentParser_get_ap_completer_type(self: argparse.ArgumentParser) -> Optional[Type['ArgparseCompleter']]: + """ + Get the ap_completer_type attribute of an argparse ArgumentParser. + + This function is added by cmd2 as a method called ``get_ap_completer_type()`` to ``argparse.ArgumentParser`` class. + + To call: ``parser.get_ap_completer_type()`` + + :param self: ArgumentParser being queried + :return: An ArgparseCompleter-based class or None if attribute does not exist + """ + return cast(Optional[Type['ArgparseCompleter']], getattr(self, ATTR_AP_COMPLETER_TYPE, None)) + + +setattr(argparse.ArgumentParser, 'get_ap_completer_type', _ArgumentParser_get_ap_completer_type) + + +# noinspection PyPep8Naming +def _ArgumentParser_set_ap_completer_type(self: argparse.ArgumentParser, ap_completer_type: Type['ArgparseCompleter']) -> None: + """ + Set the ap_completer_type attribute of an argparse ArgumentParser. + + This function is added by cmd2 as a method called ``set_ap_completer_type()`` to ``argparse.ArgumentParser`` class. + + :param self: ArgumentParser being edited + :param ap_completer_type: the custom ArgparseCompleter-based class to use when tab completing arguments for this parser + """ + setattr(self, ATTR_AP_COMPLETER_TYPE, ap_completer_type) + + +setattr(argparse.ArgumentParser, 'set_ap_completer_type', _ArgumentParser_set_ap_completer_type) + + +############################################################################################################ +# Patch argparse._SubParsersAction to add remove_parser function +############################################################################################################ + +# noinspection PyPep8Naming,PyProtectedMember def _SubParsersAction_remove_parser(self: argparse._SubParsersAction, name: str) -> None: """ Removes a sub-parser from a sub-parsers group. Used to remove subcommands from a parser. @@ -964,6 +1024,7 @@ setattr(argparse._SubParsersAction, 'remove_parser', _SubParsersAction_remove_pa class Cmd2HelpFormatter(argparse.RawTextHelpFormatter): """Custom help formatter to configure ordering of help text""" + # noinspection PyProtectedMember def _format_usage( self, usage: Optional[str], @@ -1207,6 +1268,7 @@ class Cmd2ArgumentParser(argparse.ArgumentParser): allow_abbrev=allow_abbrev, ) + # noinspection PyProtectedMember def add_subparsers(self, **kwargs: Any) -> argparse._SubParsersAction: """ Custom override. Sets a default title if one was not given. @@ -1321,10 +1383,10 @@ class Cmd2AttributeWrapper: DEFAULT_ARGUMENT_PARSER: Type[argparse.ArgumentParser] = Cmd2ArgumentParser -def set_default_argument_parser(parser: Type[argparse.ArgumentParser]) -> None: +def set_default_argument_parser_type(parser_type: Type[argparse.ArgumentParser]) -> None: """ Set the default ArgumentParser class for a cmd2 app. This must be called prior to loading cmd2.py if you want to override the parser for cmd2's built-in commands. See examples/override_parser.py. """ global DEFAULT_ARGUMENT_PARSER - DEFAULT_ARGUMENT_PARSER = parser + DEFAULT_ARGUMENT_PARSER = parser_type |