Skip to content

Commit 457ee75

Browse files
committed
Fixed issue where instantiating more than one cmd2-based class which uses the @as_subcommand_to
decorator resulted in duplicated help text in the base command the subcommands belong to.
1 parent ad646aa commit 457ee75

File tree

3 files changed

+23
-11
lines changed

3 files changed

+23
-11
lines changed

CHANGELOG.md

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,8 @@
22
* Bug Fixes
33
* Fixed issue where quoted redirectors and terminators in aliases and macros were not being
44
restored when read from a startup script.
5+
* Fixed issue where instantiating more than one cmd2-based class which uses the `@as_subcommand_to`
6+
decorator resulted in duplicated help text in the base command the subcommands belong to.
57

68
## 1.3.10 (September 17, 2020)
79
* Enhancements

cmd2/argparse_custom.py

Lines changed: 13 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -550,6 +550,7 @@ def _match_argument_wrapper(self, action, arg_strings_pattern) -> int:
550550
# Patch argparse._SubParsersAction to add remove_parser function
551551
############################################################################################################
552552

553+
# noinspection PyPep8Naming
553554
def _SubParsersAction_remove_parser(self, name: str):
554555
"""
555556
Removes a sub-parser from a sub-parsers group
@@ -558,23 +559,23 @@ def _SubParsersAction_remove_parser(self, name: str):
558559
class so cmd2 can remove subcommands from a parser.
559560
560561
:param self: instance of the _SubParsersAction being edited
561-
:param name: name of the sub-parser to remove
562+
:param name: name of the subcommand for the sub-parser to remove
562563
"""
564+
# Remove this subcommand from its base command's help text
563565
for choice_action in self._choices_actions:
564566
if choice_action.dest == name:
565567
self._choices_actions.remove(choice_action)
566568
break
567569

568-
subparser = self._name_parser_map[name]
569-
to_remove = []
570-
for name, parser in self._name_parser_map.items():
571-
if parser is subparser:
572-
to_remove.append(name)
573-
for name in to_remove:
574-
del self._name_parser_map[name]
575-
576-
if name in self.choices:
577-
del self.choices[name]
570+
# Remove this subcommand and all its aliases from the base command
571+
subparser = self._name_parser_map.get(name)
572+
if subparser is not None:
573+
to_remove = []
574+
for cur_name, cur_parser in self._name_parser_map.items():
575+
if cur_parser is subparser:
576+
to_remove.append(cur_name)
577+
for cur_name in to_remove:
578+
del self._name_parser_map[cur_name]
578579

579580

580581
# noinspection PyProtectedMember
@@ -733,6 +734,7 @@ def _format_action_invocation(self, action) -> str:
733734
return ', '.join(action.option_strings) + ' ' + args_string
734735
# End cmd2 customization
735736

737+
# noinspection PyMethodMayBeStatic
736738
def _determine_metavar(self, action, default_metavar) -> Union[str, Tuple]:
737739
"""Custom method to determine what to use as the metavar value of an action"""
738740
if action.metavar is not None:

cmd2/cmd2.py

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -692,6 +692,14 @@ def find_subcommand(action: argparse.ArgumentParser, subcmd_names: List[str]) ->
692692

693693
for action in target_parser._actions:
694694
if isinstance(action, argparse._SubParsersAction):
695+
# Temporary workaround for avoiding subcommand help text repeatedly getting added to
696+
# action._choices_actions. Until we have instance-specific parser objects, we will remove
697+
# any existing subcommand which has the same name before replacing it. This problem is
698+
# exercised when more than one cmd2.Cmd-based object is created and the same subcommands
699+
# get added each time. Argparse overwrites the previous subcommand but keeps growing the help
700+
# text which is shown by running something like 'alias -h'.
701+
action.remove_parser(subcommand_name)
702+
695703
# Get the kwargs for add_parser()
696704
add_parser_kwargs = getattr(method, constants.SUBCMD_ATTR_ADD_PARSER_KWARGS, {})
697705

0 commit comments

Comments
 (0)