summaryrefslogtreecommitdiff
path: root/cmd2/cmd2.py
diff options
context:
space:
mode:
authorEric Lin <anselor@gmail.com>2020-08-07 18:17:14 -0400
committeranselor <anselor@gmail.com>2020-08-10 11:28:29 -0400
commit6c939fb0fffd076b4471591fda79f85db2aab460 (patch)
treec511a3d549d4fcbbc3073a395f3e475a8369c208 /cmd2/cmd2.py
parent267434118955c2edfc59042d4a8c9515f63ef719 (diff)
downloadcmd2-git-1.3.2.tar.gz
Will now traverse down CommandSet inheritance tree to find all leaf descendants.1.3.2
CommandSet now has a check to ensure it is only registered with one cmd2.Cmd instance at a time. Adds function to find command set by type and by command name
Diffstat (limited to 'cmd2/cmd2.py')
-rw-r--r--cmd2/cmd2.py46
1 files changed, 38 insertions, 8 deletions
diff --git a/cmd2/cmd2.py b/cmd2/cmd2.py
index 975f4635..39feac68 100644
--- a/cmd2/cmd2.py
+++ b/cmd2/cmd2.py
@@ -406,18 +406,47 @@ class Cmd(cmd.Cmd):
self._register_subcommands(self)
+ def find_commandsets(self, commandset_type: Type[CommandSet], *, subclass_match: bool = False) -> List[CommandSet]:
+ """
+ Find all CommandSets that match the provided CommandSet type.
+ By default, locates a CommandSet that is an exact type match but may optionally return all CommandSets that
+ are sub-classes of the provided type
+ :param commandset_type: CommandSet sub-class type to search for
+ :param subclass_match: If True, return all sub-classes of provided type, otherwise only search for exact match
+ :return: Matching CommandSets
+ """
+ return [cmdset for cmdset in self._installed_command_sets
+ if type(cmdset) == commandset_type or (subclass_match and isinstance(cmdset, commandset_type))]
+
+ def find_commandset_for_command(self, command_name: str) -> Optional[CommandSet]:
+ """
+ Finds the CommandSet that registered the command name
+ :param command_name: command name to search
+ :return: CommandSet that provided the command
+ """
+ return self._cmd_to_command_sets.get(command_name)
+
def _autoload_commands(self) -> None:
"""Load modular command definitions."""
- # Search for all subclasses of CommandSet, instantiate them if they weren't provided in the constructor
+ # Search for all subclasses of CommandSet, instantiate them if they weren't already provided in the constructor
all_commandset_defs = CommandSet.__subclasses__()
existing_commandset_types = [type(command_set) for command_set in self._installed_command_sets]
- for cmdset_type in all_commandset_defs:
- init_sig = inspect.signature(cmdset_type.__init__)
- if not (cmdset_type in existing_commandset_types
- or len(init_sig.parameters) != 1
- or 'self' not in init_sig.parameters):
- cmdset = cmdset_type()
- self.install_command_set(cmdset)
+
+ def load_commandset_by_type(commandset_types: List[Type]) -> None:
+ for cmdset_type in commandset_types:
+ # check if the type has sub-classes. We will only auto-load leaf class types.
+ subclasses = cmdset_type.__subclasses__()
+ if subclasses:
+ load_commandset_by_type(subclasses)
+ else:
+ init_sig = inspect.signature(cmdset_type.__init__)
+ if not (cmdset_type in existing_commandset_types
+ or len(init_sig.parameters) != 1
+ or 'self' not in init_sig.parameters):
+ cmdset = cmdset_type()
+ self.install_command_set(cmdset)
+
+ load_commandset_by_type(all_commandset_defs)
def install_command_set(self, cmdset: CommandSet) -> None:
"""
@@ -471,6 +500,7 @@ class Cmd(cmd.Cmd):
if cmdset in self._cmd_to_command_sets.values():
self._cmd_to_command_sets = \
{key: val for key, val in self._cmd_to_command_sets.items() if val is not cmdset}
+ cmdset.on_unregister(self)
raise
def _install_command_function(self, command: str, command_wrapper: Callable, context=''):