Skip to content

# cmd2.command_definition

## `` cmd2.command_definition

Supports the definition of commands in separate classes to be composed into cmd2.Cmd.

### `` CommandFunc `module-attribute`

    CommandFunc = Callable[..., bool | None]

### `` CommandSetType `module-attribute`

    CommandSetType = TypeVar('CommandSetType', bound=type['CommandSet'])

### `` CommandSet

    CommandSet()

Base class for defining sets of commands to load in cmd2.

`with_default_category` can be used to apply a default category to all commands in the CommandSet.

`do_`, `help_`, and `complete_` functions differ only in that self is the CommandSet instead of the cmd2 app

Private reference to the CLI instance in which this CommandSet running.

This will be set when the CommandSet is registered and it should be accessed by child classes using the self._cmd property.

Source code in `cmd2/command_definition.py`

    89
    90
    91
    92
    93
    94
    95
    96
    97
    98

    def __init__(self) -> None:
        """Private reference to the CLI instance in which this CommandSet running.

        This will be set when the CommandSet is registered and it should be
        accessed by child classes using the self._cmd property.
        """
        self.__cmd_internal: cmd2.Cmd | None = None

        self._settables: dict[str, Settable] = {}
        self._settable_prefix = self.__class__.__name__

#### `` settable_prefix `property`

    settable_prefix

Read-only accessor for the underlying private settable_prefix field.

#### `` settables `property`

    settables

Read-only accessor for the underlying private settables field.

#### `` on_register

    on_register(cmd)

First step to registering a CommandSet, called by cmd2.Cmd.

The commands defined in this class have not been added to the CLI object at this point. Subclasses can override this to perform any initialization requiring access to the Cmd object (e.g. configure commands and their parsers based on CLI state data).

PARAMETER | DESCRIPTION
--- | ---
`cmd` | The cmd2 main application TYPE: `Cmd`

RAISES | DESCRIPTION
--- | ---
`CommandSetRegistrationError` | if CommandSet is already registered.

Source code in `cmd2/command_definition.py`

    125
    126
    127
    128
    129
    130
    131
    132
    133
    134
    135
    136
    137
    138

    def on_register(self, cmd: 'cmd2.Cmd') -> None:
        """First step to registering a CommandSet, called by cmd2.Cmd.

        The commands defined in this class have not been added to the CLI object at this point.
        Subclasses can override this to perform any initialization requiring access to the Cmd object
        (e.g. configure commands and their parsers based on CLI state data).

        :param cmd: The cmd2 main application
        :raises CommandSetRegistrationError: if CommandSet is already registered.
        """
        if self.__cmd_internal is None:
            self.__cmd_internal = cmd
        else:
            raise CommandSetRegistrationError('This CommandSet has already been registered')

#### `` on_registered

    on_registered()

2nd step to registering, called by cmd2.Cmd after a CommandSet is registered and all its commands have been added.

Subclasses can override this to perform custom steps related to the newly added commands (e.g. setting them to a disabled state).

Source code in `cmd2/command_definition.py`

    140
    141
    142
    143
    144
    145

    def on_registered(self) -> None:
        """2nd step to registering, called by cmd2.Cmd after a CommandSet is registered and all its commands have been added.

        Subclasses can override this to perform custom steps related to the newly added commands (e.g. setting
        them to a disabled state).
        """

#### `` on_unregister

    on_unregister()

First step to unregistering a CommandSet, called by `cmd2.Cmd`.

Subclasses can override this to perform any cleanup steps which require their commands being registered in the CLI.

Source code in `cmd2/command_definition.py`

    147
    148
    149
    150
    151

    def on_unregister(self) -> None:
        """First step to unregistering a CommandSet, called by ``cmd2.Cmd``.

        Subclasses can override this to perform any cleanup steps which require their commands being registered in the CLI.
        """

#### `` on_unregistered

    on_unregistered()

2nd step to unregistering, called by `cmd2.Cmd` after a CommandSet is unregistered and all its commands removed.

Subclasses can override this to perform remaining cleanup steps.

Source code in `cmd2/command_definition.py`

    153
    154
    155
    156
    157
    158

    def on_unregistered(self) -> None:
        """2nd step to unregistering, called by ``cmd2.Cmd`` after a CommandSet is unregistered and all its commands removed.

        Subclasses can override this to perform remaining cleanup steps.
        """
        self.__cmd_internal = None

#### `` add_settable

    add_settable(settable)

Add a settable parameter to the CommandSet.

PARAMETER | DESCRIPTION
--- | ---
`settable` | Settable object being added TYPE: `Settable`

Source code in `cmd2/command_definition.py`

    170
    171
    172
    173
    174
    175
    176
    177
    178
    179
    180
    181
    182
    183

    def add_settable(self, settable: Settable) -> None:
        """Add a settable parameter to the CommandSet.

        :param settable: Settable object being added
        """
        if self.__cmd_internal is not None:
            if not self._cmd.always_prefix_settables:
                if settable.name in self._cmd.settables and settable.name not in self._settables:
                    raise KeyError(f'Duplicate settable: {settable.name}')
            else:
                prefixed_name = f'{self._settable_prefix}.{settable.name}'
                if prefixed_name in self._cmd.settables and settable.name not in self._settables:
                    raise KeyError(f'Duplicate settable: {settable.name}')
        self._settables[settable.name] = settable

#### `` remove_settable

    remove_settable(name)

Remove a settable parameter from the CommandSet.

PARAMETER | DESCRIPTION
--- | ---
`name` | name of the settable being removed TYPE: `str`

RAISES | DESCRIPTION
--- | ---
`KeyError` | if the Settable matches this name

Source code in `cmd2/command_definition.py`

    185
    186
    187
    188
    189
    190
    191
    192
    193
    194

    def remove_settable(self, name: str) -> None:
        """Remove a settable parameter from the CommandSet.

        :param name: name of the settable being removed
        :raises KeyError: if the Settable matches this name
        """
        try:
            del self._settables[name]
        except KeyError as exc:
            raise KeyError(name + " is not a settable parameter") from exc

#### `` sigint_handler

    sigint_handler()

Handle a SIGINT that occurred for a command in this CommandSet.

RETURNS | DESCRIPTION
--- | ---
`bool` | True if this completes the interrupt handling and no KeyboardInterrupt will be raised. False to raise a KeyboardInterrupt.

Source code in `cmd2/command_definition.py`

    196
    197
    198
    199
    200
    201
    202

    def sigint_handler(self) -> bool:
        """Handle a SIGINT that occurred for a command in this CommandSet.

        :return: True if this completes the interrupt handling and no KeyboardInterrupt will be raised.
                 False to raise a KeyboardInterrupt.
        """
        return False

### `` with_default_category

    with_default_category(category, *, heritable=True)

Apply a category to all `do_*` command methods in a class that do not already have a category specified (Decorator).

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.

PARAMETER | DESCRIPTION
--- | ---
`category` | category to put all uncategorized commands in TYPE: `str`
`heritable` | Flag whether this default category should apply to sub-classes. Defaults to True TYPE: `bool` DEFAULT: `True`

RETURNS | DESCRIPTION
--- | ---
`Callable[[CommandSetType], CommandSetType]` | decorator function

Source code in `cmd2/command_definition.py`

    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
    70
    71
    72
    73
    74
    75
    76
    77
    78

    def with_default_category(category: str, *, heritable: bool = True) -> Callable[[CommandSetType], CommandSetType]:
        """Apply a category to all ``do_*`` command methods in a class that do not already have a category specified (Decorator).

        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: CommandSetType) -> CommandSetType:
            if heritable:
                setattr(cls, CLASS_ATTR_DEFAULT_HELP_CATEGORY, category)

            import inspect

            from .constants import (
                CMD_ATTR_HELP_CATEGORY,
            )
            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)
                    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):
                    setattr(cls, method[0], category_decorator(method[1]))
            return cls

        return decorate_class