@@ -146,6 +146,52 @@ def test_autoload_commands(command_sets_app):
146146 assert 'Command Set B' not in cmds_cats
147147
148148
149+ def test_command_synonyms ():
150+ """Test the use of command synonyms in CommandSets"""
151+
152+ class SynonymCommandSet (cmd2 .CommandSet ):
153+ def __init__ (self , arg1 ):
154+ super ().__init__ ()
155+ self ._arg1 = arg1
156+
157+ @cmd2 .with_argparser (cmd2 .Cmd2ArgumentParser (description = "Native Command" ))
158+ def do_builtin (self , _ ):
159+ pass
160+
161+ # Create a synonym to a command inside of this CommandSet
162+ do_builtin_synonym = do_builtin
163+
164+ # Create a synonym to a command outside of this CommandSet with subcommands.
165+ # This will best test the synonym check in cmd2.Cmd._check_uninstallable() when
166+ # we unresgister this CommandSet.
167+ do_alias_synonym = cmd2 .Cmd .do_alias
168+
169+ cs = SynonymCommandSet ("foo" )
170+ app = WithCommandSets (command_sets = [cs ])
171+
172+ # Make sure the synonyms have the same parser as what they alias
173+ builtin_parser = app ._command_parsers .get (app .do_builtin )
174+ builtin_synonym_parser = app ._command_parsers .get (app .do_builtin_synonym )
175+ assert builtin_parser is not None
176+ assert builtin_parser is builtin_synonym_parser
177+
178+ alias_parser = app ._command_parsers .get (cmd2 .Cmd .do_alias )
179+ alias_synonym_parser = app ._command_parsers .get (app .do_alias_synonym )
180+ assert alias_parser is not None
181+ assert alias_parser is alias_synonym_parser
182+
183+ # Unregister the CommandSet and make sure built-in command and synonyms are gone
184+ app .unregister_command_set (cs )
185+ assert not hasattr (app , "do_builtin" )
186+ assert not hasattr (app , "do_builtin_synonym" )
187+ assert not hasattr (app , "do_alias_synonym" )
188+
189+ # Make sure the alias command still exists, has the same parser, and works.
190+ assert alias_parser is app ._command_parsers .get (cmd2 .Cmd .do_alias )
191+ out , err = run_cmd (app , 'alias --help' )
192+ assert normalize (alias_parser .format_help ())[0 ] in out
193+
194+
149195def test_custom_construct_commandsets ():
150196 command_set_b = CommandSetB ('foo' )
151197
@@ -288,7 +334,7 @@ def test_load_commandset_errors(command_sets_manual, capsys):
288334 cmd_set = CommandSetA ()
289335
290336 # create a conflicting command before installing CommandSet to verify rollback behavior
291- command_sets_manual ._install_command_function ('durian ' , cmd_set .do_durian )
337+ command_sets_manual ._install_command_function ('do_durian ' , cmd_set .do_durian )
292338 with pytest .raises (CommandSetRegistrationError ):
293339 command_sets_manual .register_command_set (cmd_set )
294340
@@ -313,13 +359,21 @@ def test_load_commandset_errors(command_sets_manual, capsys):
313359 assert "Deleting alias 'apple'" in err
314360 assert "Deleting alias 'banana'" in err
315361
362+ # verify command functions which don't start with "do_" raise an exception
363+ with pytest .raises (CommandSetRegistrationError ):
364+ command_sets_manual ._install_command_function ('new_cmd' , cmd_set .do_banana )
365+
366+ # verify methods which don't start with "do_" raise an exception
367+ with pytest .raises (CommandSetRegistrationError ):
368+ command_sets_manual ._install_command_function ('do_new_cmd' , cmd_set .on_register )
369+
316370 # verify duplicate commands are detected
317371 with pytest .raises (CommandSetRegistrationError ):
318- command_sets_manual ._install_command_function ('banana ' , cmd_set .do_banana )
372+ command_sets_manual ._install_command_function ('do_banana ' , cmd_set .do_banana )
319373
320374 # verify bad command names are detected
321375 with pytest .raises (CommandSetRegistrationError ):
322- command_sets_manual ._install_command_function ('bad command' , cmd_set .do_banana )
376+ command_sets_manual ._install_command_function ('do_bad command' , cmd_set .do_banana )
323377
324378 # verify error conflict with existing completer function
325379 with pytest .raises (CommandSetRegistrationError ):
0 commit comments