Skip to content

Commit 15aba14

Browse files
committed
Fixed issue where CommandSet registration did not respect disabled categories
1 parent 8f2f42e commit 15aba14

File tree

3 files changed

+61
-5
lines changed

3 files changed

+61
-5
lines changed

CHANGELOG.md

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,8 @@
1+
## 3.1.3 (TBD)
2+
3+
- Bug Fixes
4+
- Fixed issue where `CommandSet` registration did not respect disabled categories
5+
16
## 3.1.2 (January 26, 2026)
27

38
- Bug Fixes

cmd2/cmd2.py

Lines changed: 26 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -593,11 +593,14 @@ def __init__(
593593
# being printed by a command.
594594
self.terminal_lock = threading.RLock()
595595

596-
# Commands that have been disabled from use. This is to support commands that are only available
597-
# during specific states of the application. This dictionary's keys are the command names and its
598-
# values are DisabledCommand objects.
596+
# Commands disabled during specific application states
597+
# Key: Command name | Value: DisabledCommand object
599598
self.disabled_commands: dict[str, DisabledCommand] = {}
600599

600+
# Categories of commands to be disabled
601+
# Key: Category name | Value: Message to display
602+
self.disabled_categories: dict[str, str] = {}
603+
601604
# The default key for sorting string results. Its default value performs a case-insensitive alphabetical sort.
602605
# If natural sorting is preferred, then set this to NATURAL_SORT_KEY.
603606
# cmd2 uses this key for sorting:
@@ -788,6 +791,12 @@ def register_command_set(self, cmdset: CommandSet) -> None:
788791
if default_category and not hasattr(command_method, constants.CMD_ATTR_HELP_CATEGORY):
789792
utils.categorize(command_method, default_category)
790793

794+
# If this command is in a disabled category, then disable it
795+
command_category = getattr(command_method, constants.CMD_ATTR_HELP_CATEGORY, None)
796+
if command_category in self.disabled_categories:
797+
message_to_print = self.disabled_categories[command_category]
798+
self.disable_command(command, message_to_print)
799+
791800
self._installed_command_sets.add(cmdset)
792801

793802
self._register_subcommands(cmdset)
@@ -5805,7 +5814,7 @@ def enable_command(self, command: str) -> None:
58055814
58065815
:param command: the command being enabled
58075816
"""
5808-
# If the commands is already enabled, then return
5817+
# If the command is already enabled, then return
58095818
if command not in self.disabled_commands:
58105819
return
58115820

@@ -5837,11 +5846,17 @@ def enable_category(self, category: str) -> None:
58375846
58385847
:param category: the category to enable
58395848
"""
5849+
# If the category is already enabled, then return
5850+
if category not in self.disabled_categories:
5851+
return
5852+
58405853
for cmd_name in list(self.disabled_commands):
58415854
func = self.disabled_commands[cmd_name].command_function
58425855
if getattr(func, constants.CMD_ATTR_HELP_CATEGORY, None) == category:
58435856
self.enable_command(cmd_name)
58445857

5858+
del self.disabled_categories[category]
5859+
58455860
def disable_command(self, command: str, message_to_print: str) -> None:
58465861
"""Disable a command and overwrite its functions.
58475862
@@ -5852,7 +5867,7 @@ def disable_command(self, command: str, message_to_print: str) -> None:
58525867
command being disabled.
58535868
ex: message_to_print = f"{cmd2.COMMAND_NAME} is currently disabled"
58545869
"""
5855-
# If the commands is already disabled, then return
5870+
# If the command is already disabled, then return
58565871
if command in self.disabled_commands:
58575872
return
58585873

@@ -5891,13 +5906,19 @@ def disable_category(self, category: str, message_to_print: str) -> None:
58915906
of the command being disabled.
58925907
ex: message_to_print = f"{cmd2.COMMAND_NAME} is currently disabled"
58935908
"""
5909+
# If the category is already disabled, then return
5910+
if category in self.disabled_categories:
5911+
return
5912+
58945913
all_commands = self.get_all_commands()
58955914

58965915
for cmd_name in all_commands:
58975916
func = self.cmd_func(cmd_name)
58985917
if getattr(func, constants.CMD_ATTR_HELP_CATEGORY, None) == category:
58995918
self.disable_command(cmd_name, message_to_print)
59005919

5920+
self.disabled_categories[category] = message_to_print
5921+
59015922
def _report_disabled_command_usage(self, *_args: Any, message_to_print: str, **_kwargs: Any) -> None:
59025923
"""Report when a disabled command has been run or had help called on it.
59035924

tests/test_cmd2.py

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@
2020
COMMAND_NAME,
2121
Cmd2Style,
2222
Color,
23+
CommandSet,
2324
RichPrintKwargs,
2425
clipboard,
2526
constants,
@@ -3106,6 +3107,16 @@ def do_has_no_helper_funcs(self, arg) -> None:
31063107
self.poutput("The real has_no_helper_funcs")
31073108

31083109

3110+
class DisableCommandSet(CommandSet):
3111+
"""Test registering a command which is in a disabled category"""
3112+
3113+
category_name = "CommandSet Test Category"
3114+
3115+
@cmd2.with_category(category_name)
3116+
def do_new_command(self, arg) -> None:
3117+
self._cmd.poutput("CommandSet function is enabled")
3118+
3119+
31093120
@pytest.fixture
31103121
def disable_commands_app():
31113122
return DisableCommandsApp()
@@ -3251,6 +3262,25 @@ def test_disabled_message_command_name(disable_commands_app) -> None:
32513262
assert err[0].startswith('has_helper_funcs is currently disabled')
32523263

32533264

3265+
def test_register_command_in_enabled_category(disable_commands_app) -> None:
3266+
disable_commands_app.enable_category(DisableCommandSet.category_name)
3267+
cs = DisableCommandSet()
3268+
disable_commands_app.register_command_set(cs)
3269+
3270+
out, _err = run_cmd(disable_commands_app, 'new_command')
3271+
assert out[0] == "CommandSet function is enabled"
3272+
3273+
3274+
def test_register_command_in_disabled_category(disable_commands_app) -> None:
3275+
message_to_print = "CommandSet function is disabled"
3276+
disable_commands_app.disable_category(DisableCommandSet.category_name, message_to_print)
3277+
cs = DisableCommandSet()
3278+
disable_commands_app.register_command_set(cs)
3279+
3280+
_out, err = run_cmd(disable_commands_app, 'new_command')
3281+
assert err[0] == message_to_print
3282+
3283+
32543284
@pytest.mark.parametrize('silence_startup_script', [True, False])
32553285
def test_startup_script(request, capsys, silence_startup_script) -> None:
32563286
test_dir = os.path.dirname(request.module.__file__)

0 commit comments

Comments
 (0)