Repository: python-cmd2/cmd2
Pull request #646 (2019-03-14 04:05:06)

Disabling tweaks


Patch:
diff --git a/CHANGELOG.md b/CHANGELOG.md
index b2e8b5e1..8bde2d33 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -1,3 +1,8 @@
+## 0.9.12 (TBD, 2019)
+* Enhancements
+    * Added ability to include command name placeholders in the message printed when trying to run a disabled command.
+        * See docstring for ``disable_command()`` or ``disable_category()`` for more details.
+
 ## 0.9.11 (March 13, 2019)
 * Bug Fixes
     * Fixed bug in how **history** command deals with multiline commands when output to a script
diff --git a/cmd2/cmd2.py b/cmd2/cmd2.py
index e32b3180..6b085a98 100644
--- a/cmd2/cmd2.py
+++ b/cmd2/cmd2.py
@@ -134,6 +134,9 @@ HELP_FUNC_PREFIX = 'help_'
 ALPHABETICAL_SORT_KEY = utils.norm_fold
 NATURAL_SORT_KEY = utils.natural_keys
 
+# Used as the command name placeholder in disabled command messages.
+COMMAND_NAME = "<COMMAND_NAME>"
+
 
 def categorize(func: Union[Callable, Iterable], category: str) -> None:
     """Categorize a function.
@@ -2054,7 +2057,8 @@ class Cmd(cmd.Cmd):
 
             return self.do_shell(statement.command_and_args)
         else:
-            self.poutput('*** {} is not a recognized command, alias, or macro\n'.format(statement.command))
+            self.perror('*** {} is not a recognized command, alias, or macro'.format(statement.command),
+                        err_color=Fore.RESET, traceback_war=False)
 
     def pseudo_raw_input(self, prompt: str) -> str:
         """Began life as a copy of cmd's cmdloop; like raw_input but
@@ -3661,6 +3665,10 @@ class Cmd(cmd.Cmd):
         Disable a command and overwrite its functions
         :param command: the command being disabled
         :param message_to_print: what to print when this command is run or help is called on it while disabled
+
+                                 The variable COMMAND_NAME can be used as a placeholder for the name of the
+                                 command being disabled.
+                                 ex: message_to_print = "{} is currently disabled".format(COMMAND_NAME)
         """
         import functools
 
@@ -3680,7 +3688,8 @@ class Cmd(cmd.Cmd):
                                                           help_function=getattr(self, help_func_name, None))
 
         # Overwrite the command and help functions to print the message
-        new_func = functools.partial(self._report_disabled_command_usage, message_to_print=message_to_print)
+        new_func = functools.partial(self._report_disabled_command_usage,
+                                     message_to_print=message_to_print.replace(COMMAND_NAME, command))
         setattr(self, self.cmd_func_name(command), new_func)
         setattr(self, help_func_name, new_func)
 
@@ -3690,6 +3699,10 @@ class Cmd(cmd.Cmd):
         :param category: the category to disable
         :param message_to_print: what to print when anything in this category is run or help is called on it
                                  while disabled
+
+                                 The variable COMMAND_NAME can be used as a placeholder for the name of the
+                                 command being disabled.
+                                 ex: message_to_print = "{} is currently disabled".format(COMMAND_NAME)
         """
         all_commands = self.get_all_commands()
 
@@ -3706,7 +3719,7 @@ class Cmd(cmd.Cmd):
         :param message_to_print: the message reporting that the command is disabled
         :param kwargs: not used
         """
-        self.poutput(message_to_print)
+        self.perror(message_to_print, err_color=Fore.RESET, traceback_war=False)
 
     def cmdloop(self, intro: Optional[str] = None) -> None:
         """This is an outer wrapper around _cmdloop() which deals with extra features provided by cmd2.
diff --git a/examples/help_categories.py b/examples/help_categories.py
index e58bac02..62351e81 100755
--- a/examples/help_categories.py
+++ b/examples/help_categories.py
@@ -7,6 +7,7 @@ A sample application for tagging categories on commands.
 import argparse
 
 import cmd2
+from cmd2.cmd2 import COMMAND_NAME
 
 
 class HelpCategories(cmd2.Cmd):
@@ -143,7 +144,9 @@ class HelpCategories(cmd2.Cmd):
     @cmd2.with_category("Command Management")
     def do_disable_commands(self, _):
         """Disable the Application Management commands"""
-        self.disable_category(self.CMD_CAT_APP_MGMT, "Application Management is currently disabled")
+        message_to_print = "{} is not available while {} commands are disabled".format(COMMAND_NAME,
+                                                                                       self.CMD_CAT_APP_MGMT)
+        self.disable_category(self.CMD_CAT_APP_MGMT, message_to_print)
         self.poutput("The Application Management commands have been disabled")
 
     @cmd2.with_category("Command Management")


Test patch:
diff --git a/tests/test_cmd2.py b/tests/test_cmd2.py
index b3942203..44ca89e0 100644
--- a/tests/test_cmd2.py
+++ b/tests/test_cmd2.py
@@ -292,9 +292,10 @@ def test_pyscript_requires_an_argument(base_app, capsys):
     assert "the following arguments are required: script_path" in err
 
 
-def test_base_error(base_app):
-    out = run_cmd(base_app, 'meow')
-    assert "is not a recognized command" in out[0]
+def test_base_error(base_app, capsys):
+    run_cmd(base_app, 'meow')
+    out, err = capsys.readouterr()
+    assert "is not a recognized command" in err
 
 
 def test_base_load(base_app, request):
@@ -2199,23 +2200,27 @@ def disable_commands_app():
     return app
 
 
-def test_disable_and_enable_category(disable_commands_app):
+def test_disable_and_enable_category(disable_commands_app, capsys):
     # Disable the category
     message_to_print = 'These commands are currently disabled'
     disable_commands_app.disable_category(disable_commands_app.category_name, message_to_print)
 
     # Make sure all the commands and help on those commands displays the message
-    out = run_cmd(disable_commands_app, 'has_help_func')
-    assert out == [message_to_print]
+    run_cmd(disable_commands_app, 'has_help_func')
+    out, err = capsys.readouterr()
+    assert err.startswith(message_to_print)
 
-    out = run_cmd(disable_commands_app, 'help has_help_func')
-    assert out == [message_to_print]
+    run_cmd(disable_commands_app, 'help has_help_func')
+    out, err = capsys.readouterr()
+    assert err.startswith(message_to_print)
 
-    out = run_cmd(disable_commands_app, 'has_no_help_func')
-    assert out == [message_to_print]
+    run_cmd(disable_commands_app, 'has_no_help_func')
+    out, err = capsys.readouterr()
+    assert err.startswith(message_to_print)
 
-    out = run_cmd(disable_commands_app, 'help has_no_help_func')
-    assert out == [message_to_print]
+    run_cmd(disable_commands_app, 'help has_no_help_func')
+    out, err = capsys.readouterr()
+    assert err.startswith(message_to_print)
 
     visible_commands = disable_commands_app.get_visible_commands()
     assert 'has_help_func' not in visible_commands
@@ -2275,3 +2280,11 @@ def test_disabled_command_not_in_history(disable_commands_app):
     saved_len = len(disable_commands_app.history)
     run_cmd(disable_commands_app, 'has_help_func')
     assert saved_len == len(disable_commands_app.history)
+
+def test_disabled_message_command_name(disable_commands_app, capsys):
+    message_to_print = '{} is currently disabled'.format(cmd2.cmd2.COMMAND_NAME)
+    disable_commands_app.disable_command('has_help_func', message_to_print)
+
+    run_cmd(disable_commands_app, 'has_help_func')
+    out, err = capsys.readouterr()
+    assert err.startswith('has_help_func is currently disabled')