summaryrefslogtreecommitdiff
path: root/cmd2
diff options
context:
space:
mode:
authorEric Lin <anselor@gmail.com>2020-07-29 17:59:47 -0400
committeranselor <anselor@gmail.com>2020-08-04 13:38:08 -0400
commit105369bdd15c2067b3ee6bdd6a737733a34c38ef (patch)
tree6358e7923d35d491998d263a93fdbdd8f1e8c256 /cmd2
parent8d0b162cf5712c26947f1e0bbc2b1021cb71e366 (diff)
downloadcmd2-git-105369bdd15c2067b3ee6bdd6a737733a34c38ef.tar.gz
Suggested PR Fixes.
sub-commande => subcommand Added help/aliases to `as_subcommand_to` decorator.
Diffstat (limited to 'cmd2')
-rw-r--r--cmd2/argparse_custom.py2
-rw-r--r--cmd2/cmd2.py34
-rw-r--r--cmd2/constants.py3
-rw-r--r--cmd2/decorators.py23
4 files changed, 35 insertions, 27 deletions
diff --git a/cmd2/argparse_custom.py b/cmd2/argparse_custom.py
index 689c1db7..9dde5347 100644
--- a/cmd2/argparse_custom.py
+++ b/cmd2/argparse_custom.py
@@ -774,7 +774,7 @@ class Cmd2ArgumentParser(argparse.ArgumentParser):
allow_abbrev=allow_abbrev)
self.register('action', 'unloadable_parsers', _UnloadableSubParsersAction)
- def add_subparsers(self, unloadable=False, **kwargs):
+ def add_subparsers(self, unloadable: bool = False, **kwargs):
"""
Custom override. Sets a default title if one was not given.
diff --git a/cmd2/cmd2.py b/cmd2/cmd2.py
index ea590fac..e15a856e 100644
--- a/cmd2/cmd2.py
+++ b/cmd2/cmd2.py
@@ -527,14 +527,14 @@ class Cmd(cmd.Cmd):
def _register_subcommands(self, cmdset: Union[CommandSet, 'Cmd']) -> None:
"""
- Register sub-commands with their base command
+ Register subcommands with their base command
- :param cmdset: CommandSet containing sub-commands
+ :param cmdset: CommandSet containing subcommands
"""
if not (cmdset is self or cmdset in self._installed_command_sets):
- raise ValueError('Adding sub-commands from an unregistered CommandSet')
+ raise ValueError('Adding subcommands from an unregistered CommandSet')
- # find all methods that start with the sub-command prefix
+ # find all methods that start with the subcommand prefix
methods = inspect.getmembers(
cmdset,
predicate=lambda meth: (inspect.ismethod(meth) or isinstance(meth, Callable))
@@ -548,22 +548,18 @@ class Cmd(cmd.Cmd):
subcommand_name = getattr(method, constants.SUBCMD_ATTR_NAME)
command_name = getattr(method, constants.SUBCMD_ATTR_COMMAND)
subcmd_parser = getattr(method, constants.CMD_ATTR_ARGPARSER)
+ parser_args = getattr(method, constants.SUBCMD_ATTR_PARSER_ARGS, {})
# Search for the base command function and verify it has an argparser defined
command_func = self.cmd_func(command_name)
if command_func is None or not hasattr(command_func, constants.CMD_ATTR_ARGPARSER):
- raise TypeError('Could not find command "{}" needed by sub-command: {}'
+ raise TypeError('Could not find command "{}" needed by subcommand: {}'
.format(command_name, str(method)))
command_parser = getattr(command_func, constants.CMD_ATTR_ARGPARSER)
if command_parser is None:
- raise TypeError('Could not find argparser for command "{}" needed by sub-command: {}'
+ raise TypeError('Could not find argparser for command "{}" needed by subcommand: {}'
.format(command_name, str(method)))
- if hasattr(method, '__doc__') and method.__doc__ is not None:
- help_text = method.__doc__.splitlines()[0]
- else:
- help_text = subcommand_name
-
if isinstance(cmdset, CommandSet):
command_handler = _partial_passthru(method, self)
else:
@@ -572,18 +568,18 @@ class Cmd(cmd.Cmd):
for action in command_parser._actions:
if isinstance(action, _UnloadableSubParsersAction):
- action.add_parser(subcommand_name, parents=[subcmd_parser], help=help_text)
+ action.add_parser(subcommand_name, parents=[subcmd_parser], **parser_args)
def _unregister_subcommands(self, cmdset: Union[CommandSet, 'Cmd']) -> None:
"""
- Unregister sub-commands from their base command
+ Unregister subcommands from their base command
- :param cmdset: CommandSet containing sub-commands
+ :param cmdset: CommandSet containing subcommands
"""
if not (cmdset is self or cmdset in self._installed_command_sets):
- raise ValueError('Removing sub-commands from an unregistered CommandSet')
+ raise ValueError('Removing subcommands from an unregistered CommandSet')
- # find all methods that start with the sub-command prefix
+ # find all methods that start with the subcommand prefix
methods = inspect.getmembers(
cmdset,
predicate=lambda meth: (inspect.ismethod(meth) or isinstance(meth, Callable))
@@ -600,11 +596,11 @@ class Cmd(cmd.Cmd):
# Search for the base command function and verify it has an argparser defined
command_func = self.cmd_func(command_name)
if command_func is None or not hasattr(command_func, constants.CMD_ATTR_ARGPARSER):
- raise TypeError('Could not find command "{}" needed by sub-command: {}'
+ raise TypeError('Could not find command "{}" needed by subcommand: {}'
.format(command_name, str(method)))
command_parser = getattr(command_func, constants.CMD_ATTR_ARGPARSER)
if command_parser is None:
- raise TypeError('Could not find argparser for command "{}" needed by sub-command: {}'
+ raise TypeError('Could not find argparser for command "{}" needed by subcommand: {}'
.format(command_name, str(method)))
for action in command_parser._actions:
@@ -3387,7 +3383,7 @@ class Cmd(cmd.Cmd):
if 'gnureadline' in sys.modules:
# Restore what the readline module pointed to
if cmd2_env.readline_module is None:
- del (sys.modules['readline'])
+ del sys.modules['readline']
else:
sys.modules['readline'] = cmd2_env.readline_module
diff --git a/cmd2/constants.py b/cmd2/constants.py
index 0135e328..88a1bb82 100644
--- a/cmd2/constants.py
+++ b/cmd2/constants.py
@@ -50,6 +50,7 @@ CMD_ATTR_ARGPARSER = 'argparser'
# Whether or not tokens are unquoted before sending to argparse
CMD_ATTR_PRESERVE_QUOTES = 'preserve_quotes'
-# sub-command attributes for the base command name and the sub-command name
+# subcommand attributes for the base command name and the subcommand name
SUBCMD_ATTR_COMMAND = 'parent_command'
SUBCMD_ATTR_NAME = 'subcommand_name'
+SUBCMD_ATTR_PARSER_ARGS = 'subcommand_parser_args'
diff --git a/cmd2/decorators.py b/cmd2/decorators.py
index 6e3b7acf..82ad8cd7 100644
--- a/cmd2/decorators.py
+++ b/cmd2/decorators.py
@@ -1,7 +1,7 @@
# coding=utf-8
"""Decorators for ``cmd2`` commands"""
import argparse
-from typing import TYPE_CHECKING, Any, Callable, Dict, List, Optional, Tuple, Union
+from typing import TYPE_CHECKING, Any, Callable, Dict, Iterable, List, Optional, Tuple, Union
from . import constants
from .exceptions import Cmd2ArgparseError
@@ -339,13 +339,18 @@ def with_argparser(parser: argparse.ArgumentParser, *,
def as_subcommand_to(command: str,
subcommand: str,
- parser: argparse.ArgumentParser) -> Callable[[argparse.Namespace], Optional[bool]]:
+ parser: argparse.ArgumentParser,
+ *,
+ help_text: Optional[str] = None,
+ aliases: Iterable[str] = None) -> Callable[[argparse.Namespace], Optional[bool]]:
"""
- Tag this method as a sub-command to an existing argparse decorated command.
+ Tag this method as a subcommand to an existing argparse decorated command.
:param command: Command Name
- :param subcommand: Sub-command name
- :param parser: argparse Parser to for this sub-command
+ :param subcommand: Subcommand name
+ :param parser: argparse Parser for this subcommand
+ :param help_text: Help message for this subcommand
+ :param aliases: Alternative names for this subcommand
:return: Wrapper function that can receive an argparse.Namespace
"""
def arg_decorator(func: Callable):
@@ -357,10 +362,16 @@ def as_subcommand_to(command: str,
parser.set_defaults(func=func)
- # # Set some custom attributes for this command
+ # Set some custom attributes for this command
setattr(func, constants.SUBCMD_ATTR_COMMAND, command)
setattr(func, constants.CMD_ATTR_ARGPARSER, parser)
setattr(func, constants.SUBCMD_ATTR_NAME, subcommand)
+ parser_args = {}
+ if help_text is not None:
+ parser_args['help'] = help_text
+ if aliases is not None:
+ parser_args['aliases'] = aliases[:]
+ setattr(func, constants.SUBCMD_ATTR_PARSER_ARGS, parser_args)
return func