summaryrefslogtreecommitdiff
path: root/cmd2/command_definition.py
diff options
context:
space:
mode:
Diffstat (limited to 'cmd2/command_definition.py')
-rw-r--r--cmd2/command_definition.py24
1 files changed, 21 insertions, 3 deletions
diff --git a/cmd2/command_definition.py b/cmd2/command_definition.py
index 64adaada..3f05792c 100644
--- a/cmd2/command_definition.py
+++ b/cmd2/command_definition.py
@@ -4,7 +4,7 @@ Supports the definition of commands in separate classes to be composed into cmd2
"""
from typing import Optional, Type
-from .constants import COMMAND_FUNC_PREFIX
+from .constants import CLASS_ATTR_DEFAULT_HELP_CATEGORY, COMMAND_FUNC_PREFIX
from .exceptions import CommandSetRegistrationError
# Allows IDEs to resolve types without impacting imports at runtime, breaking circular dependency issues
@@ -17,22 +17,40 @@ except ImportError: # pragma: no cover
pass
-def with_default_category(category: str):
+def with_default_category(category: str, *, heritable: bool = True):
"""
Decorator that applies a category to all ``do_*`` command methods in a class that do not already
have a category specified.
+ CommandSets that are decorated by this with `heritable` set to True (default) will set a class attribute that is
+ inherited by all subclasses unless overridden. All commands of this CommandSet and all subclasses of this CommandSet
+ that do not declare an explicit category will be placed in this category. Subclasses may use this decorator to
+ override the default category.
+
+ If `heritable` is set to False, then only the commands declared locally to this CommandSet will be placed in the
+ specified category. Dynamically created commands, and commands declared in sub-classes will not receive this
+ category.
+
:param category: category to put all uncategorized commands in
+ :param heritable: Flag whether this default category should apply to sub-classes. Defaults to True
:return: decorator function
"""
def decorate_class(cls: Type[CommandSet]):
+ if heritable:
+ setattr(cls, CLASS_ATTR_DEFAULT_HELP_CATEGORY, category)
+
from .constants import CMD_ATTR_HELP_CATEGORY
import inspect
from .decorators import with_category
+ # get members of the class that meet the following criteria:
+ # 1. Must be a function
+ # 2. Must start with COMMAND_FUNC_PREFIX (do_)
+ # 3. Must be a member of the class being decorated and not one inherited from a parent declaration
methods = inspect.getmembers(
cls,
- predicate=lambda meth: inspect.isfunction(meth) and meth.__name__.startswith(COMMAND_FUNC_PREFIX))
+ predicate=lambda meth: inspect.isfunction(meth) and meth.__name__.startswith(COMMAND_FUNC_PREFIX)
+ and meth in inspect.getmro(cls)[0].__dict__.values())
category_decorator = with_category(category)
for method in methods:
if not hasattr(method[1], CMD_ATTR_HELP_CATEGORY):