Skip to content

Commit 4b71f09

Browse files
committed
Updated unit test.
1 parent 99ba829 commit 4b71f09

File tree

2 files changed

+33
-32
lines changed

2 files changed

+33
-32
lines changed

Diff for: cmd2/cmd2.py

+20-21
Original file line numberDiff line numberDiff line change
@@ -875,7 +875,8 @@ def unregister_command_set(self, cmdset: CommandSet) -> None:
875875
if command in self._cmd_to_command_sets:
876876
del self._cmd_to_command_sets[command]
877877

878-
# A command synonym does not own the parser.
878+
# Only remove the parser if this is the actual
879+
# command since command synonyms don't own it.
879880
if cmd_func_name == command_method.__name__:
880881
self._command_parsers.remove(command_method)
881882

@@ -890,6 +891,18 @@ def unregister_command_set(self, cmdset: CommandSet) -> None:
890891
self._installed_command_sets.remove(cmdset)
891892

892893
def _check_uninstallable(self, cmdset: CommandSet) -> None:
894+
def check_parser_uninstallable(parser: argparse.ArgumentParser) -> None:
895+
for action in parser._actions:
896+
if isinstance(action, argparse._SubParsersAction):
897+
for subparser in action.choices.values():
898+
attached_cmdset = getattr(subparser, constants.PARSER_ATTR_COMMANDSET, None)
899+
if attached_cmdset is not None and attached_cmdset is not cmdset:
900+
raise CommandSetRegistrationError(
901+
'Cannot uninstall CommandSet when another CommandSet depends on it'
902+
)
903+
check_parser_uninstallable(subparser)
904+
break
905+
893906
methods: List[Tuple[str, Callable[..., Any]]] = inspect.getmembers(
894907
cmdset,
895908
predicate=lambda meth: isinstance(meth, Callable) # type: ignore[arg-type]
@@ -898,26 +911,12 @@ def _check_uninstallable(self, cmdset: CommandSet) -> None:
898911
)
899912

900913
for cmd_func_name, command_method in methods:
901-
# Do nothing if this is a command synonym since it does not own the parser.
902-
if cmd_func_name != command_method.__name__:
903-
continue
904-
905-
command_parser = self._command_parsers.get(command_method)
906-
907-
def check_parser_uninstallable(parser: argparse.ArgumentParser) -> None:
908-
for action in parser._actions:
909-
if isinstance(action, argparse._SubParsersAction):
910-
for subparser in action.choices.values():
911-
attached_cmdset = getattr(subparser, constants.PARSER_ATTR_COMMANDSET, None)
912-
if attached_cmdset is not None and attached_cmdset is not cmdset:
913-
raise CommandSetRegistrationError(
914-
'Cannot uninstall CommandSet when another CommandSet depends on it'
915-
)
916-
check_parser_uninstallable(subparser)
917-
break
918-
919-
if command_parser is not None:
920-
check_parser_uninstallable(command_parser)
914+
# We only need to check if it's safe to remove the parser if this
915+
# is the actual command since command synonyms don't own it.
916+
if cmd_func_name == command_method.__name__:
917+
command_parser = self._command_parsers.get(command_method)
918+
if command_parser is not None:
919+
check_parser_uninstallable(command_parser)
921920

922921
def _register_subcommands(self, cmdset: Union[CommandSet, 'Cmd']) -> None:
923922
"""

Diff for: tests_isolated/test_commandset/test_commandset.py

+13-11
Original file line numberDiff line numberDiff line change
@@ -164,8 +164,10 @@ def do_builtin(self, _):
164164
# Create a synonym to a command inside of this CommandSet
165165
do_builtin_synonym = do_builtin
166166

167-
# Create a synonym to a command outside of this CommandSet
168-
do_help_synonym = cmd2.Cmd.do_help
167+
# Create a synonym to a command outside of this CommandSet with subcommands.
168+
# This will best test the synonym check in cmd2.Cmd._check_uninstallable() when
169+
# we unresgister this CommandSet.
170+
do_alias_synonym = cmd2.Cmd.do_alias
169171

170172
cs = SynonymCommandSet("foo")
171173
app = WithCommandSets(command_sets=[cs])
@@ -176,21 +178,21 @@ def do_builtin(self, _):
176178
assert builtin_parser is not None
177179
assert builtin_parser is builtin_synonym_parser
178180

179-
help_parser = app._command_parsers.get(cmd2.Cmd.do_help)
180-
help_synonym_parser = app._command_parsers.get(app.do_help_synonym)
181-
assert help_parser is not None
182-
assert help_parser is help_synonym_parser
181+
alias_parser = app._command_parsers.get(cmd2.Cmd.do_alias)
182+
alias_synonym_parser = app._command_parsers.get(app.do_alias_synonym)
183+
assert alias_parser is not None
184+
assert alias_parser is alias_synonym_parser
183185

184186
# Unregister the CommandSet and make sure built-in command and synonyms are gone
185187
app.unregister_command_set(cs)
186188
assert not hasattr(app, "do_builtin")
187189
assert not hasattr(app, "do_builtin_synonym")
188-
assert not hasattr(app, "do_help_synonym")
190+
assert not hasattr(app, "do_alias_synonym")
189191

190-
# Make sure the help command still exists, has the same parser, and works.
191-
assert help_parser is app._command_parsers.get(cmd2.Cmd.do_help)
192-
out, err = run_cmd(app, 'help')
193-
assert app.doc_header in out
192+
# Make sure the alias command still exists, has the same parser, and works.
193+
assert alias_parser is app._command_parsers.get(cmd2.Cmd.do_alias)
194+
out, err = run_cmd(app, 'alias --help')
195+
assert normalize(alias_parser.format_help())[0] in out
194196

195197

196198
def test_custom_construct_commandsets():

0 commit comments

Comments
 (0)