summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorEric Lin <anselor@gmail.com>2020-07-30 01:32:29 -0400
committeranselor <anselor@gmail.com>2020-08-04 13:38:08 -0400
commitdac009f17c58df4b8d4dbcd3c621bf6ef2481a96 (patch)
tree24f2ff3cc3897ac247a290dbdc5a518e734661aa
parent105369bdd15c2067b3ee6bdd6a737733a34c38ef (diff)
downloadcmd2-git-dac009f17c58df4b8d4dbcd3c621bf6ef2481a96.tar.gz
Removed sub-class and instead patch argparse._SubParsersAction
-rw-r--r--cmd2/argparse_custom.py50
-rw-r--r--cmd2/cmd2.py6
-rw-r--r--isolated_tests/test_commandset/test_commandset.py2
3 files changed, 30 insertions, 28 deletions
diff --git a/cmd2/argparse_custom.py b/cmd2/argparse_custom.py
index 9dde5347..6cfa66ae 100644
--- a/cmd2/argparse_custom.py
+++ b/cmd2/argparse_custom.py
@@ -528,6 +528,31 @@ def _match_argument_wrapper(self, action, arg_strings_pattern) -> int:
# noinspection PyProtectedMember
argparse.ArgumentParser._match_argument = _match_argument_wrapper
+
+############################################################################################################
+# Patch argparse._SubParsersAction to add remove_parser function
+############################################################################################################
+
+def _SubParsersAction_remove_parser(self, name):
+ """Removes a sub-parser from the sub-parsers group"""
+ for choice_action in self._choices_actions:
+ if choice_action.dest == name:
+ self._choices_actions.remove(choice_action)
+ break
+
+ subparser = self._name_parser_map[name]
+ to_remove = []
+ for name, parser in self._name_parser_map.items():
+ if parser is subparser:
+ to_remove.append(name)
+ for name in to_remove:
+ del self._name_parser_map[name]
+
+
+# noinspection PyProtectedMember
+setattr(argparse._SubParsersAction, 'remove_parser', _SubParsersAction_remove_parser)
+
+
############################################################################################################
# Unless otherwise noted, everything below this point are copied from Python's
# argparse implementation with minor tweaks to adjust output.
@@ -724,24 +749,6 @@ class Cmd2HelpFormatter(argparse.RawTextHelpFormatter):
return result
-class _UnloadableSubParsersAction(argparse._SubParsersAction):
- """Extends the argparse internal SubParsers action to allow sub-parsers to be removed dynamically"""
- def remove_parser(self, name):
- """Removes a sub-parser from the sub-parsers group"""
- for choice_action in self._choices_actions:
- if choice_action.dest == name:
- self._choices_actions.remove(choice_action)
- break
-
- subparser = self._name_parser_map[name]
- to_remove = []
- for name, parser in self._name_parser_map.items():
- if parser is subparser:
- to_remove.append(name)
- for name in to_remove:
- del self._name_parser_map[name]
-
-
# noinspection PyCompatibility
class Cmd2ArgumentParser(argparse.ArgumentParser):
"""Custom ArgumentParser class that improves error and help output"""
@@ -772,22 +779,17 @@ class Cmd2ArgumentParser(argparse.ArgumentParser):
conflict_handler=conflict_handler,
add_help=add_help,
allow_abbrev=allow_abbrev)
- self.register('action', 'unloadable_parsers', _UnloadableSubParsersAction)
- def add_subparsers(self, unloadable: bool = False, **kwargs):
+ def add_subparsers(self, **kwargs):
"""
Custom override. Sets a default title if one was not given.
- :param unloadable: Flag whether this sub-parsers group will support unloading parsers
:param kwargs: additional keyword arguments
:return: argparse Subparser Action
"""
if 'title' not in kwargs:
kwargs['title'] = 'subcommands'
- if unloadable:
- kwargs['action'] = 'unloadable_parsers'
-
return super().add_subparsers(**kwargs)
def error(self, message: str) -> None:
diff --git a/cmd2/cmd2.py b/cmd2/cmd2.py
index e15a856e..c933db99 100644
--- a/cmd2/cmd2.py
+++ b/cmd2/cmd2.py
@@ -43,7 +43,7 @@ from contextlib import redirect_stdout
from typing import Any, Callable, Dict, Iterable, List, Mapping, Optional, Tuple, Type, Union
from . import ansi, constants, plugin, utils
-from .argparse_custom import DEFAULT_ARGUMENT_PARSER, CompletionItem, _UnloadableSubParsersAction
+from .argparse_custom import DEFAULT_ARGUMENT_PARSER, CompletionItem
from .clipboard import can_clip, get_paste_buffer, write_to_paste_buffer
from .command_definition import CommandSet, _partial_passthru
from .constants import COMMAND_FUNC_PREFIX, COMPLETER_FUNC_PREFIX, HELP_FUNC_PREFIX
@@ -567,7 +567,7 @@ class Cmd(cmd.Cmd):
subcmd_parser.set_defaults(handler=command_handler)
for action in command_parser._actions:
- if isinstance(action, _UnloadableSubParsersAction):
+ if isinstance(action, argparse._SubParsersAction):
action.add_parser(subcommand_name, parents=[subcmd_parser], **parser_args)
def _unregister_subcommands(self, cmdset: Union[CommandSet, 'Cmd']) -> None:
@@ -604,7 +604,7 @@ class Cmd(cmd.Cmd):
.format(command_name, str(method)))
for action in command_parser._actions:
- if isinstance(action, _UnloadableSubParsersAction):
+ if isinstance(action, argparse._SubParsersAction):
action.remove_parser(subcommand_name)
def add_settable(self, settable: Settable) -> None:
diff --git a/isolated_tests/test_commandset/test_commandset.py b/isolated_tests/test_commandset/test_commandset.py
index 98385772..f16a6ff4 100644
--- a/isolated_tests/test_commandset/test_commandset.py
+++ b/isolated_tests/test_commandset/test_commandset.py
@@ -272,7 +272,7 @@ class LoadableBase(cmd2.CommandSet):
self._dummy = dummy # prevents autoload
cut_parser = cmd2.Cmd2ArgumentParser('cut')
- cut_subparsers = cut_parser.add_subparsers(title='item', help='item to cut', unloadable=True)
+ cut_subparsers = cut_parser.add_subparsers(title='item', help='item to cut')
@cmd2.with_argparser(cut_parser)
def do_cut(self, ns: argparse.Namespace):