summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--CHANGELOG.md5
-rw-r--r--cmd2/argparse_completer.py3
-rw-r--r--cmd2/argparse_custom.py11
-rw-r--r--cmd2/cmd2.py31
-rw-r--r--cmd2/command_definition.py35
-rw-r--r--cmd2/decorators.py14
-rw-r--r--docs/features/modular_commands.rst69
-rw-r--r--examples/modular_commands/commandset_basic.py10
-rw-r--r--examples/modular_commands/commandset_complex.py32
-rw-r--r--examples/modular_commands/commandset_custominit.py4
-rw-r--r--examples/modular_commands_basic.py8
-rw-r--r--examples/modular_commands_dynamic.py24
-rw-r--r--examples/modular_subcommands.py24
-rw-r--r--tests_isolated/test_commandset/test_argparse_subcommands.py16
-rw-r--r--tests_isolated/test_commandset/test_commandset.py231
15 files changed, 229 insertions, 288 deletions
diff --git a/CHANGELOG.md b/CHANGELOG.md
index ef2745d3..6c835259 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -1,4 +1,9 @@
## 1.3.3 (TBD)
+* Breaking changes
+ * CommandSet command functions (do_, complete_, help_) will no longer have the cmd2 app
+ passed in as the first parameter after `self` since this is already a class member.
+ * Renamed `install_command_set()` and `uninstall_command_set()` to `register_command_set()` and
+ `unregister_command_set()` for better name consistency.
* Bug Fixes
* Added explicit testing against python 3.5.2 for Ubuntu 16.04, and 3.5.3 for Debian 9
* Added fallback definition of typing.Deque (taken from 3.5.4)
diff --git a/cmd2/argparse_completer.py b/cmd2/argparse_completer.py
index f14e83fd..77fa41b8 100644
--- a/cmd2/argparse_completer.py
+++ b/cmd2/argparse_completer.py
@@ -606,7 +606,8 @@ class ArgparseCompleter:
# No cases matched, raise an error
raise CompletionError('Could not find CommandSet instance matching defining type for completer')
args.append(cmd_set)
- args.append(self._cmd2_app)
+ else:
+ args.append(self._cmd2_app)
# Check if arg_choices.to_call expects arg_tokens
to_call_params = inspect.signature(arg_choices.to_call).parameters
diff --git a/cmd2/argparse_custom.py b/cmd2/argparse_custom.py
index 5dbb9f66..d724cb88 100644
--- a/cmd2/argparse_custom.py
+++ b/cmd2/argparse_custom.py
@@ -68,9 +68,9 @@ If bound to a cmd2.Cmd subclass, it will pass the app instance as the `self`
argument. This is good in cases where the list of choices being generated
relies on state data of the cmd2-based app.
If bound to a cmd2.CommandSet subclass, it will pass the CommandSet instance
-as the `self` argument, and the app instance as the positional argument.
+as the `self` argument.
- Example bound to cmd2.Cmd::
+ Example::
def my_choices_method(self):
...
@@ -78,13 +78,6 @@ as the `self` argument, and the app instance as the positional argument.
parser.add_argument("arg", choices_method=my_choices_method)
- Example bound to cmd2.CommandSEt::
-
- def my_choices_method(self, app: cmd2.Cmd):
- ...
- return my_generated_list
-
- parser.add_argument("arg", choices_method=my_choices_method)
``completer_function`` - pass a tab completion function that does custom
completion. Since custom tab completion operations commonly need to modify
diff --git a/cmd2/cmd2.py b/cmd2/cmd2.py
index 621228db..30dcb6e8 100644
--- a/cmd2/cmd2.py
+++ b/cmd2/cmd2.py
@@ -45,7 +45,7 @@ from typing import Any, Callable, Dict, Iterable, List, Mapping, Optional, Tuple
from . import ansi, constants, plugin, utils
from .argparse_custom import DEFAULT_ARGUMENT_PARSER, CompletionItem
from .clipboard import can_clip, get_paste_buffer, write_to_paste_buffer
-from .command_definition import CommandSet, _partial_passthru
+from .command_definition import CommandSet
from .constants import COMMAND_FUNC_PREFIX, COMPLETER_FUNC_PREFIX, HELP_FUNC_PREFIX
from .decorators import with_argparser, as_subcommand_to
from .exceptions import (
@@ -186,7 +186,7 @@ class Cmd(cmd.Cmd):
:param auto_load_commands: If True, cmd2 will check for all subclasses of `CommandSet`
that are currently loaded by Python and automatically
instantiate and register all commands. If False, CommandSets
- must be manually installed with `install_command_set`.
+ must be manually installed with `register_command_set`.
"""
# If use_ipython is False, make sure the ipy command isn't available in this instance
if not use_ipython:
@@ -264,7 +264,7 @@ class Cmd(cmd.Cmd):
self._cmd_to_command_sets = {} # type: Dict[str, CommandSet]
if command_sets:
for command_set in command_sets:
- self.install_command_set(command_set)
+ self.register_command_set(command_set)
if auto_load_commands:
self._autoload_commands()
@@ -452,11 +452,11 @@ class Cmd(cmd.Cmd):
or len(init_sig.parameters) != 1
or 'self' not in init_sig.parameters):
cmdset = cmdset_type()
- self.install_command_set(cmdset)
+ self.register_command_set(cmdset)
load_commandset_by_type(all_commandset_defs)
- def install_command_set(self, cmdset: CommandSet) -> None:
+ def register_command_set(self, cmdset: CommandSet) -> None:
"""
Installs a CommandSet, loading all commands defined in the CommandSet
@@ -476,23 +476,20 @@ class Cmd(cmd.Cmd):
try:
for method_name, method in methods:
command = method_name[len(COMMAND_FUNC_PREFIX):]
- command_wrapper = _partial_passthru(method, self)
- self._install_command_function(command, command_wrapper, type(cmdset).__name__)
+ self._install_command_function(command, method, type(cmdset).__name__)
installed_attributes.append(method_name)
completer_func_name = COMPLETER_FUNC_PREFIX + command
cmd_completer = getattr(cmdset, completer_func_name, None)
if cmd_completer is not None:
- completer_wrapper = _partial_passthru(cmd_completer, self)
- self._install_completer_function(command, completer_wrapper)
+ self._install_completer_function(command, cmd_completer)
installed_attributes.append(completer_func_name)
help_func_name = HELP_FUNC_PREFIX + command
cmd_help = getattr(cmdset, help_func_name, None)
if cmd_help is not None:
- help_wrapper = _partial_passthru(cmd_help, self)
- self._install_help_function(command, help_wrapper)
+ self._install_help_function(command, cmd_help)
installed_attributes.append(help_func_name)
self._cmd_to_command_sets[command] = cmdset
@@ -508,7 +505,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)
+ cmdset.on_unregister()
raise
def _install_command_function(self, command: str, command_wrapper: Callable, context=''):
@@ -549,7 +546,7 @@ class Cmd(cmd.Cmd):
raise CommandSetRegistrationError('Attribute already exists: {}'.format(help_func_name))
setattr(self, help_func_name, cmd_help)
- def uninstall_command_set(self, cmdset: CommandSet):
+ def unregister_command_set(self, cmdset: CommandSet):
"""
Uninstalls a CommandSet and unloads all associated commands
:param cmdset: CommandSet to uninstall
@@ -581,7 +578,7 @@ class Cmd(cmd.Cmd):
if hasattr(self, HELP_FUNC_PREFIX + cmd_name):
delattr(self, HELP_FUNC_PREFIX + cmd_name)
- cmdset.on_unregister(self)
+ cmdset.on_unregister()
self._installed_command_sets.remove(cmdset)
def _check_uninstallable(self, cmdset: CommandSet):
@@ -656,11 +653,7 @@ class Cmd(cmd.Cmd):
raise CommandSetRegistrationError('Could not find argparser for command "{}" needed by subcommand: {}'
.format(command_name, str(method)))
- if isinstance(cmdset, CommandSet):
- command_handler = _partial_passthru(method, self)
- else:
- command_handler = method
- subcmd_parser.set_defaults(cmd2_handler=command_handler)
+ subcmd_parser.set_defaults(cmd2_handler=method)
def find_subcommand(action: argparse.ArgumentParser, subcmd_names: List[str]) -> argparse.ArgumentParser:
if not subcmd_names:
diff --git a/cmd2/command_definition.py b/cmd2/command_definition.py
index 22d8915e..86f1151a 100644
--- a/cmd2/command_definition.py
+++ b/cmd2/command_definition.py
@@ -18,36 +18,6 @@ except ImportError: # pragma: no cover
pass
-def _partial_passthru(func: Callable, *args, **kwargs) -> functools.partial:
- """
- Constructs a partial function that passes arguments through to the wrapped function.
- Must construct a new type every time so that each wrapped function's __doc__ can be copied correctly.
-
- :param func: wrapped function
- :param args: positional arguments
- :param kwargs: keyword arguments
- :return: partial function that exposes attributes of wrapped function
- """
- def __getattr__(self, item):
- return getattr(self.func, item)
-
- def __setattr__(self, key, value):
- return setattr(self.func, key, value)
-
- def __dir__(self) -> Iterable[str]:
- return dir(self.func)
-
- passthru_type = type('PassthruPartial' + func.__name__,
- (functools.partial,),
- {
- '__getattr__': __getattr__,
- '__setattr__': __setattr__,
- '__dir__': __dir__,
- })
- passthru_type.__doc__ = func.__doc__
- return passthru_type(func, *args, **kwargs)
-
-
def with_default_category(category: str):
"""
Decorator that applies a category to all ``do_*`` command methods in a class that do not already
@@ -78,8 +48,7 @@ class CommandSet(object):
``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 they're now required to accept
- a reference to ``cmd2.Cmd`` as the first argument after self.
+ ``do_``, ``help_``, and ``complete_`` functions differ only in that self is the CommandSet instead of the cmd2 app
"""
def __init__(self):
@@ -98,7 +67,7 @@ class CommandSet(object):
else:
raise CommandSetRegistrationError('This CommandSet has already been registered')
- def on_unregister(self, cmd):
+ def on_unregister(self):
"""
Called by ``cmd2.Cmd`` when a CommandSet is unregistered and removed.
diff --git a/cmd2/decorators.py b/cmd2/decorators.py
index 0dda3485..7c20af68 100644
--- a/cmd2/decorators.py
+++ b/cmd2/decorators.py
@@ -41,7 +41,7 @@ def with_category(category: str) -> Callable:
##########################
-def _parse_positionals(args: Tuple) -> Tuple['cmd2.Cmd', Union[Statement, str]]:
+def _parse_positionals(args: Tuple) -> Tuple[Union['cmd2.Cmd', 'cmd2.CommandSet'], Union[Statement, str]]:
"""
Helper function for cmd2 decorators to inspect the positional arguments until the cmd2.Cmd argument is found
Assumes that we will find cmd2.Cmd followed by the command statement object or string.
@@ -49,8 +49,10 @@ def _parse_positionals(args: Tuple) -> Tuple['cmd2.Cmd', Union[Statement, str]]:
:return: The cmd2.Cmd reference and the command line statement
"""
for pos, arg in enumerate(args):
- from cmd2 import Cmd
- if isinstance(arg, Cmd) and len(args) > pos:
+ from cmd2 import Cmd, CommandSet
+ if (isinstance(arg, Cmd) or isinstance(arg, CommandSet)) and len(args) > pos:
+ if isinstance(arg, CommandSet):
+ arg = arg._cmd
next_arg = args[pos + 1]
if isinstance(next_arg, (Statement, str)):
return arg, args[pos + 1]
@@ -92,7 +94,7 @@ def with_argument_list(*args: List[Callable], preserve_quotes: bool = False) ->
>>> def do_echo(self, arglist):
>>> self.poutput(' '.join(arglist)
"""
- import functools
+ import functools, cmd2
def arg_decorator(func: Callable):
@functools.wraps(func)
@@ -293,8 +295,8 @@ def with_argparser(parser: argparse.ArgumentParser, *,
else:
setattr(ns, '__statement__', statement)
- def get_handler(self: argparse.Namespace) -> Optional[Callable]:
- return getattr(self, constants.SUBCMD_HANDLER, None)
+ def get_handler(ns_self: argparse.Namespace) -> Optional[Callable]:
+ return getattr(ns_self, constants.SUBCMD_HANDLER, None)
setattr(ns, 'get_handler', types.MethodType(get_handler, ns))
diff --git a/docs/features/modular_commands.rst b/docs/features/modular_commands.rst
index d19c3b45..dddd996e 100644
--- a/docs/features/modular_commands.rst
+++ b/docs/features/modular_commands.rst
@@ -42,8 +42,9 @@ A new decorator ``with_default_category`` is provided to categorize all commands
same command category. Individual commands in a CommandSet may be override the default category by specifying a
specific category with ``cmd.with_category``.
-CommandSet methods will always expect ``self``, and ``cmd2.Cmd`` as the first two parameters. The parameters that
-follow will depend on the specific command decorator being used.
+CommandSet command methods will always expect the same parameters as when defined in a ``cmd2.Cmd`` sub-class,
+except that ``self`` will now refer to the ``CommandSet`` instead of the cmd2 instance. The cmd2 instance can
+be accessed through ``self._cmd`` that is populated when the ``CommandSet`` is registered.
CommandSets will only be auto-loaded if the constructor takes no arguments.
If you need to provide constructor arguments, see :ref:`features/modular_commands:Manual CommandSet Construction`
@@ -58,11 +59,11 @@ If you need to provide constructor arguments, see :ref:`features/modular_command
def __init__(self):
super().__init__()
- def do_hello(self, cmd: cmd2.Cmd, _: cmd2.Statement):
- cmd.poutput('Hello')
+ def do_hello(self, _: cmd2.Statement):
+ self._cmd.poutput('Hello')
- def do_world(self, cmd: cmd2.Cmd, _: cmd2.Statement):
- cmd.poutput('World')
+ def do_world(self, _: cmd2.Statement):
+ self._cmd.poutput('World')
class ExampleApp(cmd2.Cmd):
"""
@@ -94,11 +95,11 @@ CommandSets and pass in the constructor to Cmd2.
self._arg1 = arg1
self._arg2 = arg2
- def do_show_arg1(self, cmd: cmd2.Cmd, _: cmd2.Statement):
- cmd.poutput('Arg1: ' + self._arg1)
+ def do_show_arg1(self, _: cmd2.Statement):
+ self._cmd.poutput('Arg1: ' + self._arg1)
- def do_show_arg2(self, cmd: cmd2.Cmd, _: cmd2.Statement):
- cmd.poutput('Arg2: ' + self._arg2)
+ def do_show_arg2(self, _: cmd2.Statement):
+ self._cmd.poutput('Arg2: ' + self._arg2)
class ExampleApp(cmd2.Cmd):
"""
@@ -139,11 +140,11 @@ You may need to disable command auto-loading if you need dynamically load comman
def __init__(self):
super().__init__()
- def do_apple(self, cmd: cmd2.Cmd, _: cmd2.Statement):
- cmd.poutput('Apple')
+ def do_apple(self, _: cmd2.Statement):
+ self._cmd.poutput('Apple')
- def do_banana(self, cmd: cmd2.Cmd, _: cmd2.Statement):
- cmd.poutput('Banana')
+ def do_banana(self, _: cmd2.Statement):
+ self._cmd.poutput('Banana')
@with_default_category('Vegetables')
@@ -151,11 +152,11 @@ You may need to disable command auto-loading if you need dynamically load comman
def __init__(self):
super().__init__()
- def do_arugula(self, cmd: cmd2.Cmd, _: cmd2.Statement):
- cmd.poutput('Arugula')
+ def do_arugula(self, _: cmd2.Statement):
+ self._cmd.poutput('Arugula')
- def do_bokchoy(self, cmd: cmd2.Cmd, _: cmd2.Statement):
- cmd.poutput('Bok Choy')
+ def do_bokchoy(self, _: cmd2.Statement):
+ self._cmd.poutput('Bok Choy')
class ExampleApp(cmd2.Cmd):
@@ -178,14 +179,14 @@ You may need to disable command auto-loading if you need dynamically load comman
def do_load(self, ns: argparse.Namespace):
if ns.cmds == 'fruits':
try:
- self.install_command_set(self._fruits)
+ self.register_command_set(self._fruits)
self.poutput('Fruits loaded')
except ValueError:
self.poutput('Fruits already loaded')
if ns.cmds == 'vegetables':
try:
- self.install_command_set(self._vegetables)
+ self.register_command_set(self._vegetables)
self.poutput('Vegetables loaded')
except ValueError:
self.poutput('Vegetables already loaded')
@@ -193,11 +194,11 @@ You may need to disable command auto-loading if you need dynamically load comman
@with_argparser(load_parser)
def do_unload(self, ns: argparse.Namespace):
if ns.cmds == 'fruits':
- self.uninstall_command_set(self._fruits)
+ self.unregister_command_set(self._fruits)
self.poutput('Fruits unloaded')
if ns.cmds == 'vegetables':
- self.uninstall_command_set(self._vegetables)
+ self.unregister_command_set(self._vegetables)
self.poutput('Vegetables unloaded')
@@ -240,16 +241,16 @@ command and each CommandSet
def __init__(self):
super().__init__()
- def do_apple(self, cmd: cmd2.Cmd, _: cmd2.Statement):
- cmd.poutput('Apple')
+ def do_apple(self, _: cmd2.Statement):
+ self._cmd.poutput('Apple')
banana_parser = cmd2.Cmd2ArgumentParser(add_help=False)
banana_parser.add_argument('direction', choices=['discs', 'lengthwise'])
@cmd2.as_subcommand_to('cut', 'banana', banana_parser)
- def cut_banana(self, cmd: cmd2.Cmd, ns: argparse.Namespace):
+ def cut_banana(self, ns: argparse.Namespace):
"""Cut banana"""
- cmd.poutput('cutting banana: ' + ns.direction)
+ self._cmd.poutput('cutting banana: ' + ns.direction)
@with_default_category('Vegetables')
@@ -257,15 +258,15 @@ command and each CommandSet
def __init__(self):
super().__init__()
- def do_arugula(self, cmd: cmd2.Cmd, _: cmd2.Statement):
- cmd.poutput('Arugula')
+ def do_arugula(self, _: cmd2.Statement):
+ self._cmd.poutput('Arugula')
bokchoy_parser = cmd2.Cmd2ArgumentParser(add_help=False)
bokchoy_parser.add_argument('style', choices=['quartered', 'diced'])
@cmd2.as_subcommand_to('cut', 'bokchoy', bokchoy_parser)
- def cut_bokchoy(self, cmd: cmd2.Cmd, _: cmd2.Statement):
- cmd.poutput('Bok Choy')
+ def cut_bokchoy(self, _: cmd2.Statement):
+ self._cmd.poutput('Bok Choy')
class ExampleApp(cmd2.Cmd):
@@ -288,14 +289,14 @@ command and each CommandSet
def do_load(self, ns: argparse.Namespace):
if ns.cmds == 'fruits':
try:
- self.install_command_set(self._fruits)
+ self.register_command_set(self._fruits)
self.poutput('Fruits loaded')
except ValueError:
self.poutput('Fruits already loaded')
if ns.cmds == 'vegetables':
try:
- self.install_command_set(self._vegetables)
+ self.register_command_set(self._vegetables)
self.poutput('Vegetables loaded')
except ValueError:
self.poutput('Vegetables already loaded')
@@ -303,11 +304,11 @@ command and each CommandSet
@with_argparser(load_parser)
def do_unload(self, ns: argparse.Namespace):
if ns.cmds == 'fruits':
- self.uninstall_command_set(self._fruits)
+ self.unregister_command_set(self._fruits)
self.poutput('Fruits unloaded')
if ns.cmds == 'vegetables':
- self.uninstall_command_set(self._vegetables)
+ self.unregister_command_set(self._vegetables)
self.poutput('Vegetables unloaded')
cut_parser = cmd2.Cmd2ArgumentParser('cut')
diff --git a/examples/modular_commands/commandset_basic.py b/examples/modular_commands/commandset_basic.py
index 105530e8..2ceda439 100644
--- a/examples/modular_commands/commandset_basic.py
+++ b/examples/modular_commands/commandset_basic.py
@@ -30,7 +30,7 @@ class BasicCompletionCommandSet(CommandSet):
-s, --sport [completes sports]
-p, --path [completes local file system paths]
"""
- cmd.poutput("Args: {}".format(statement.args))
+ self._cmd.poutput("Args: {}".format(statement.args))
def complete_flag_based(self, cmd: Cmd, text: str, line: str, begidx: int, endidx: int) -> List[str]:
"""Completion function for do_flag_based"""
@@ -53,7 +53,7 @@ class BasicCompletionCommandSet(CommandSet):
def do_index_based(self, cmd: Cmd, statement: Statement):
"""Tab completes first 3 arguments using index_based_complete"""
- cmd.poutput("Args: {}".format(statement.args))
+ self._cmd.poutput("Args: {}".format(statement.args))
def complete_index_based(self, cmd: Cmd, text: str, line: str, begidx: int, endidx: int) -> List[str]:
"""Completion function for do_index_based"""
@@ -68,14 +68,14 @@ class BasicCompletionCommandSet(CommandSet):
def do_delimiter_complete(self, cmd: Cmd, statement: Statement):
"""Tab completes files from a list using delimiter_complete"""
- cmd.poutput("Args: {}".format(statement.args))
+ self._cmd.poutput("Args: {}".format(statement.args))
def complete_delimiter_complete(self, cmd: Cmd, text: str, line: str, begidx: int, endidx: int) -> List[str]:
return cmd.delimiter_complete(text, line, begidx, endidx, match_against=self.file_strs, delimiter='/')
def do_raise_error(self, cmd: Cmd, statement: Statement):
"""Demonstrates effect of raising CompletionError"""
- cmd.poutput("Args: {}".format(statement.args))
+ self._cmd.poutput("Args: {}".format(statement.args))
def complete_raise_error(self, cmd: Cmd, text: str, line: str, begidx: int, endidx: int) -> List[str]:
"""
@@ -89,4 +89,4 @@ class BasicCompletionCommandSet(CommandSet):
@with_category('Not Basic Completion')
def do_custom_category(self, cmd: Cmd, statement: Statement):
- cmd.poutput('Demonstrates a command that bypasses the default category')
+ self._cmd.poutput('Demonstrates a command that bypasses the default category')
diff --git a/examples/modular_commands/commandset_complex.py b/examples/modular_commands/commandset_complex.py
index ec5a9e13..7c6b1300 100644
--- a/examples/modular_commands/commandset_complex.py
+++ b/examples/modular_commands/commandset_complex.py
@@ -13,35 +13,35 @@ from cmd2 import utils
@cmd2.with_default_category('Fruits')
class CommandSetA(cmd2.CommandSet):
- def do_apple(self, cmd: cmd2.Cmd, statement: cmd2.Statement):
- cmd.poutput('Apple!')
+ def do_apple(self, statement: cmd2.Statement):
+ self._cmd.poutput('Apple!')
- def do_banana(self, cmd: cmd2.Cmd, statement: cmd2.Statement):
+ def do_banana(self, statement: cmd2.Statement):
"""Banana Command"""
- cmd.poutput('Banana!!')
+ self._cmd.poutput('Banana!!')
cranberry_parser = cmd2.Cmd2ArgumentParser('cranberry')
cranberry_parser.add_argument('arg1', choices=['lemonade', 'juice', 'sauce'])
@cmd2.with_argparser(cranberry_parser, with_unknown_args=True)
- def do_cranberry(self, cmd: cmd2.Cmd, ns: argparse.Namespace, unknown: List[str]):
- cmd.poutput('Cranberry {}!!'.format(ns.arg1))
+ def do_cranberry(self, ns: argparse.Namespace, unknown: List[str]):
+ self._cmd.poutput('Cranberry {}!!'.format(ns.arg1))
if unknown and len(unknown):
- cmd.poutput('Unknown: ' + ', '.join(['{}']*len(unknown)).format(*unknown))
- cmd.last_result = {'arg1': ns.arg1,
+ self._cmd.poutput('Unknown: ' + ', '.join(['{}']*len(unknown)).format(*unknown))
+ self._cmd.last_result = {'arg1': ns.arg1,
'unknown': unknown}
- def help_cranberry(self, cmd: cmd2.Cmd):
- cmd.stdout.write('This command does diddly squat...\n')
+ def help_cranberry(self):
+ self._cmd.stdout.write('This command does diddly squat...\n')
@cmd2.with_argument_list
@cmd2.with_category('Also Alone')
- def do_durian(self, cmd: cmd2.Cmd, args: List[str]):
+ def do_durian(self, args: List[str]):
"""Durian Command"""
- cmd.poutput('{} Arguments: '.format(len(args)))
- cmd.poutput(', '.join(['{}']*len(args)).format(*args))
+ self._cmd.poutput('{} Arguments: '.format(len(args)))
+ self._cmd.poutput(', '.join(['{}']*len(args)).format(*args))
- def complete_durian(self, cmd: cmd2.Cmd, text: str, line: str, begidx: int, endidx: int) -> List[str]:
+ def complete_durian(self, text: str, line: str, begidx: int, endidx: int) -> List[str]:
return utils.basic_complete(text, line, begidx, endidx, ['stinks', 'smells', 'disgusting'])
elderberry_parser = cmd2.Cmd2ArgumentParser('elderberry')
@@ -49,5 +49,5 @@ class CommandSetA(cmd2.CommandSet):
@cmd2.with_category('Alone')
@cmd2.with_argparser(elderberry_parser)
- def do_elderberry(self, cmd: cmd2.Cmd, ns: argparse.Namespace):
- cmd.poutput('Elderberry {}!!'.format(ns.arg1))
+ def do_elderberry(self, ns: argparse.Namespace):
+ self._cmd.poutput('Elderberry {}!!'.format(ns.arg1))
diff --git a/examples/modular_commands/commandset_custominit.py b/examples/modular_commands/commandset_custominit.py
index 5a574a59..2ef94a75 100644
--- a/examples/modular_commands/commandset_custominit.py
+++ b/examples/modular_commands/commandset_custominit.py
@@ -14,7 +14,7 @@ class CustomInitCommandSet(CommandSet):
self._arg2 = arg2
def do_show_arg1(self, cmd: Cmd, _: Statement):
- cmd.poutput('Arg1: ' + self._arg1)
+ self._cmd.poutput('Arg1: ' + self._arg1)
def do_show_arg2(self, cmd: Cmd, _: Statement):
- cmd.poutput('Arg2: ' + self._arg2)
+ self._cmd.poutput('Arg2: ' + self._arg2)
diff --git a/examples/modular_commands_basic.py b/examples/modular_commands_basic.py
index 9f4a0bd2..b9d4c4a2 100644
--- a/examples/modular_commands_basic.py
+++ b/examples/modular_commands_basic.py
@@ -13,11 +13,11 @@ class AutoLoadCommandSet(CommandSet):
def __init__(self):
super().__init__()
- def do_hello(self, cmd: cmd2.Cmd, _: cmd2.Statement):
- cmd.poutput('Hello')
+ def do_hello(self, _: cmd2.Statement):
+ self._cmd.poutput('Hello')
- def do_world(self, cmd: cmd2.Cmd, _: cmd2.Statement):
- cmd.poutput('World')
+ def do_world(self, _: cmd2.Statement):
+ self._cmd.poutput('World')
class ExampleApp(cmd2.Cmd):
diff --git a/examples/modular_commands_dynamic.py b/examples/modular_commands_dynamic.py
index 81dbad82..eb6283a7 100644
--- a/examples/modular_commands_dynamic.py
+++ b/examples/modular_commands_dynamic.py
@@ -19,11 +19,11 @@ class LoadableFruits(CommandSet):
def __init__(self):
super().__init__()
- def do_apple(self, cmd: cmd2.Cmd, _: cmd2.Statement):
- cmd.poutput('Apple')
+ def do_apple(self, _: cmd2.Statement):
+ self._cmd.poutput('Apple')
- def do_banana(self, cmd: cmd2.Cmd, _: cmd2.Statement):
- cmd.poutput('Banana')
+ def do_banana(self, _: cmd2.Statement):
+ self._cmd.poutput('Banana')
@with_default_category('Vegetables')
@@ -31,11 +31,11 @@ class LoadableVegetables(CommandSet):
def __init__(self):
super().__init__()
- def do_arugula(self, cmd: cmd2.Cmd, _: cmd2.Statement):
- cmd.poutput('Arugula')
+ def do_arugula(self, _: cmd2.Statement):
+ self._cmd.poutput('Arugula')
- def do_bokchoy(self, cmd: cmd2.Cmd, _: cmd2.Statement):
- cmd.poutput('Bok Choy')
+ def do_bokchoy(self, _: cmd2.Statement):
+ self._cmd.poutput('Bok Choy')
class ExampleApp(cmd2.Cmd):
@@ -58,14 +58,14 @@ class ExampleApp(cmd2.Cmd):
def do_load(self, ns: argparse.Namespace):
if ns.cmds == 'fruits':
try:
- self.install_command_set(self._fruits)
+ self.register_command_set(self._fruits)
self.poutput('Fruits loaded')
except ValueError:
self.poutput('Fruits already loaded')
if ns.cmds == 'vegetables':
try:
- self.install_command_set(self._vegetables)
+ self.register_command_set(self._vegetables)
self.poutput('Vegetables loaded')
except ValueError:
self.poutput('Vegetables already loaded')
@@ -73,11 +73,11 @@ class ExampleApp(cmd2.Cmd):
@with_argparser(load_parser)
def do_unload(self, ns: argparse.Namespace):
if ns.cmds == 'fruits':
- self.uninstall_command_set(self._fruits)
+ self.unregister_command_set(self._fruits)
self.poutput('Fruits unloaded')
if ns.cmds == 'vegetables':
- self.uninstall_command_set(self._vegetables)
+ self.unregister_command_set(self._vegetables)
self.poutput('Vegetables unloaded')
diff --git a/examples/modular_subcommands.py b/examples/modular_subcommands.py
index 945fd54d..44d4edd8 100644
--- a/examples/modular_subcommands.py
+++ b/examples/modular_subcommands.py
@@ -20,17 +20,17 @@ class LoadableFruits(CommandSet):
def __init__(self):
super().__init__()
- def do_apple(self, cmd: cmd2.Cmd, _: cmd2.Statement):
- cmd.poutput('Apple')
+ def do_apple(self, _: cmd2.Statement):
+ self._cmd.poutput('Apple')
banana_description = "Cut a banana"
banana_parser = cmd2.Cmd2ArgumentParser(add_help=False, description=banana_description)
banana_parser.add_argument('direction', choices=['discs', 'lengthwise'])
@cmd2.as_subcommand_to('cut', 'banana', banana_parser, help=banana_description.lower())
- def cut_banana(self, cmd: cmd2.Cmd, ns: argparse.Namespace):
+ def cut_banana(self, ns: argparse.Namespace):
"""Cut banana"""
- cmd.poutput('cutting banana: ' + ns.direction)
+ self._cmd.poutput('cutting banana: ' + ns.direction)
@with_default_category('Vegetables')
@@ -38,16 +38,16 @@ class LoadableVegetables(CommandSet):
def __init__(self):
super().__init__()
- def do_arugula(self, cmd: cmd2.Cmd, _: cmd2.Statement):
- cmd.poutput('Arugula')
+ def do_arugula(self, _: cmd2.Statement):
+ self._cmd.poutput('Arugula')
bokchoy_description = "Cut some bokchoy"
bokchoy_parser = cmd2.Cmd2ArgumentParser(add_help=False, description=bokchoy_description)
bokchoy_parser.add_argument('style', choices=['quartered', 'diced'])
@cmd2.as_subcommand_to('cut', 'bokchoy', bokchoy_parser, help=bokchoy_description.lower())
- def cut_bokchoy(self, cmd: cmd2.Cmd, _: cmd2.Statement):
- cmd.poutput('Bok Choy')
+ def cut_bokchoy(self, _: cmd2.Statement):
+ self._cmd.poutput('Bok Choy')
class ExampleApp(cmd2.Cmd):
@@ -70,14 +70,14 @@ class ExampleApp(cmd2.Cmd):
def do_load(self, ns: argparse.Namespace):
if ns.cmds == 'fruits':
try:
- self.install_command_set(self._fruits)
+ self.register_command_set(self._fruits)
self.poutput('Fruits loaded')
except ValueError:
self.poutput('Fruits already loaded')
if ns.cmds == 'vegetables':
try:
- self.install_command_set(self._vegetables)
+ self.register_command_set(self._vegetables)
self.poutput('Vegetables loaded')
except ValueError:
self.poutput('Vegetables already loaded')
@@ -85,11 +85,11 @@ class ExampleApp(cmd2.Cmd):
@with_argparser(load_parser)
def do_unload(self, ns: argparse.Namespace):
if ns.cmds == 'fruits':
- self.uninstall_command_set(self._fruits)
+ self.unregister_command_set(self._fruits)
self.poutput('Fruits unloaded')
if ns.cmds == 'vegetables':
- self.uninstall_command_set(self._vegetables)
+ self.unregister_command_set(self._vegetables)
self.poutput('Vegetables unloaded')
cut_parser = cmd2.Cmd2ArgumentParser('cut')
diff --git a/tests_isolated/test_commandset/test_argparse_subcommands.py b/tests_isolated/test_commandset/test_argparse_subcommands.py
index 69a53447..bd2bed42 100644
--- a/tests_isolated/test_commandset/test_argparse_subcommands.py
+++ b/tests_isolated/test_commandset/test_argparse_subcommands.py
@@ -19,17 +19,17 @@ class SubcommandSet(cmd2.CommandSet):
super(SubcommandSet, self).__init__()
# subcommand functions for the base command
- def base_foo(self, cmd: cmd2.Cmd, args):
+ def base_foo(self, args):
"""foo subcommand of base command"""
- cmd.poutput(args.x * args.y)
+ self._cmd.poutput(args.x * args.y)
- def base_bar(self, cmd: cmd2.Cmd, args):
+ def base_bar(self, args):
"""bar subcommand of base command"""
- cmd.poutput('((%s))' % args.z)
+ self._cmd.poutput('((%s))' % args.z)
- def base_helpless(self, cmd: cmd2.Cmd, args):
+ def base_helpless(self, args):
"""helpless subcommand of base command"""
- cmd.poutput('((%s))' % args.z)
+ self._cmd.poutput('((%s))' % args.z)
# create the top-level parser for the base command
base_parser = argparse.ArgumentParser()
@@ -56,11 +56,11 @@ class SubcommandSet(cmd2.CommandSet):
parser_bar.set_defaults(func=base_bar)
@cmd2.with_argparser(base_parser)
- def do_base(self, cmd: cmd2.Cmd, args):
+ def do_base(self, args):
"""Base command help"""
# Call whatever subcommand function was selected
func = getattr(args, 'func')
- func(self, cmd, args)
+ func(self, args)
@pytest.fixture
diff --git a/tests_isolated/test_commandset/test_commandset.py b/tests_isolated/test_commandset/test_commandset.py
index 813f9183..e1441fe4 100644
--- a/tests_isolated/test_commandset/test_commandset.py
+++ b/tests_isolated/test_commandset/test_commandset.py
@@ -21,36 +21,36 @@ class CommandSetBase(cmd2.CommandSet):
@cmd2.with_default_category('Fruits')
class CommandSetA(CommandSetBase):
- def do_apple(self, cmd: cmd2.Cmd, statement: cmd2.Statement):
- cmd.poutput('Apple!')
+ def do_apple(self, statement: cmd2.Statement):
+ self._cmd.poutput('Apple!')
- def do_banana(self, cmd: cmd2.Cmd, statement: cmd2.Statement):
+ def do_banana(self, statement: cmd2.Statement):
"""Banana Command"""
- cmd.poutput('Banana!!')
+ self._cmd.poutput('Banana!!')
cranberry_parser = cmd2.Cmd2ArgumentParser('cranberry')
cranberry_parser.add_argument('arg1', choices=['lemonade', 'juice', 'sauce'])
@cmd2.with_argparser(cranberry_parser, with_unknown_args=True)
- def do_cranberry(self, cmd: cmd2.Cmd, ns: argparse.Namespace, unknown: List[str]):
- cmd.poutput('Cranberry {}!!'.format(ns.arg1))
+ def do_cranberry(self, ns: argparse.Namespace, unknown: List[str]):
+ self._cmd.poutput('Cranberry {}!!'.format(ns.arg1))
if unknown and len(unknown):
- cmd.poutput('Unknown: ' + ', '.join(['{}']*len(unknown)).format(*unknown))
- cmd.last_result = {'arg1': ns.arg1,
+ self._cmd.poutput('Unknown: ' + ', '.join(['{}']*len(unknown)).format(*unknown))
+ self._cmd.last_result = {'arg1': ns.arg1,
'unknown': unknown}
- def help_cranberry(self, cmd: cmd2.Cmd):
- cmd.stdout.write('This command does diddly squat...\n')
+ def help_cranberry(self):
+ self._cmd.stdout.write('This command does diddly squat...\n')
@cmd2.with_argument_list
@cmd2.with_category('Also Alone')
- def do_durian(self, cmd: cmd2.Cmd, args: List[str]):
+ def do_durian(self, args: List[str]):
"""Durian Command"""
- cmd.poutput('{} Arguments: '.format(len(args)))
- cmd.poutput(', '.join(['{}']*len(args)).format(*args))
- cmd.last_result = {'args': args}
+ self._cmd.poutput('{} Arguments: '.format(len(args)))
+ self._cmd.poutput(', '.join(['{}']*len(args)).format(*args))
+ self._cmd.last_result = {'args': args}
- def complete_durian(self, cmd: cmd2.Cmd, text: str, line: str, begidx: int, endidx: int) -> List[str]:
+ def complete_durian(self, text: str, line: str, begidx: int, endidx: int) -> List[str]:
return utils.basic_complete(text, line, begidx, endidx, ['stinks', 'smells', 'disgusting'])
elderberry_parser = cmd2.Cmd2ArgumentParser('elderberry')
@@ -58,9 +58,9 @@ class CommandSetA(CommandSetBase):
@cmd2.with_category('Alone')
@cmd2.with_argparser(elderberry_parser)
- def do_elderberry(self, cmd: cmd2.Cmd, ns: argparse.Namespace):
- cmd.poutput('Elderberry {}!!'.format(ns.arg1))
- cmd.last_result = {'arg1': ns.arg1}
+ def do_elderberry(self, ns: argparse.Namespace):
+ self._cmd.poutput('Elderberry {}!!'.format(ns.arg1))
+ self._cmd.last_result = {'arg1': ns.arg1}
@cmd2.with_default_category('Command Set B')
@@ -69,15 +69,15 @@ class CommandSetB(CommandSetBase):
super().__init__()
self._arg1 = arg1
- def do_aardvark(self, cmd: cmd2.Cmd, statement: cmd2.Statement):
- cmd.poutput('Aardvark!')
+ def do_aardvark(self, statement: cmd2.Statement):
+ self._cmd.poutput('Aardvark!')
- def do_bat(self, cmd: cmd2.Cmd, statement: cmd2.Statement):
+ def do_bat(self, statement: cmd2.Statement):
"""Banana Command"""
- cmd.poutput('Bat!!')
+ self._cmd.poutput('Bat!!')
- def do_crocodile(self, cmd: cmd2.Cmd, statement: cmd2.Statement):
- cmd.poutput('Crocodile!!')
+ def do_crocodile(self, statement: cmd2.Statement):
+ self._cmd.poutput('Crocodile!!')
def test_autoload_commands(command_sets_app):
@@ -108,18 +108,18 @@ def test_custom_construct_commandsets():
# Verifies that the same CommandSet can not be loaded twice
command_set_2 = CommandSetB('bar')
with pytest.raises(CommandSetRegistrationError):
- assert app.install_command_set(command_set_2)
+ assert app.register_command_set(command_set_2)
# Verify that autoload doesn't conflict with a manually loaded CommandSet that could be autoloaded.
command_set_a = CommandSetA()
app2 = WithCommandSets(command_sets=[command_set_a])
with pytest.raises(CommandSetRegistrationError):
- app2.install_command_set(command_set_b)
+ app2.register_command_set(command_set_b)
- app.uninstall_command_set(command_set_b)
+ app.unregister_command_set(command_set_b)
- app2.install_command_set(command_set_b)
+ app2.register_command_set(command_set_b)
assert hasattr(app2, 'do_apple')
assert hasattr(app2, 'do_aardvark')
@@ -141,7 +141,7 @@ def test_load_commands(command_sets_manual):
assert command_sets_manual.find_commandset_for_command('elderberry') is None
assert not command_sets_manual.find_commandsets(CommandSetA)
- command_sets_manual.install_command_set(cmd_set)
+ command_sets_manual.register_command_set(cmd_set)
assert command_sets_manual.find_commandsets(CommandSetA)[0] is cmd_set
assert command_sets_manual.find_commandset_for_command('elderberry') is cmd_set
@@ -155,7 +155,7 @@ def test_load_commands(command_sets_manual):
assert 'cranberry' in cmds_cats['Fruits']
# uninstall the command set and verify it is now also no longer accessible
- command_sets_manual.uninstall_command_set(cmd_set)
+ command_sets_manual.unregister_command_set(cmd_set)
cmds_cats, cmds_doc, cmds_undoc, help_topics = command_sets_manual._build_command_info()
@@ -163,10 +163,10 @@ def test_load_commands(command_sets_manual):
assert 'Fruits' not in cmds_cats
# uninstall a second time and verify no errors happen
- command_sets_manual.uninstall_command_set(cmd_set)
+ command_sets_manual.unregister_command_set(cmd_set)
# reinstall the command set and verify it is accessible
- command_sets_manual.install_command_set(cmd_set)
+ command_sets_manual.register_command_set(cmd_set)
cmds_cats, cmds_doc, cmds_undoc, help_topics = command_sets_manual._build_command_info()
@@ -177,33 +177,10 @@ def test_load_commands(command_sets_manual):
assert 'cranberry' in cmds_cats['Fruits']
-def test_partial_with_passthru():
-
- def test_func(arg1, arg2):
- """Documentation Comment"""
- print('Do stuff {} - {}'.format(arg1, arg2))
-
- my_partial = cmd2.command_definition._partial_passthru(test_func, 1)
-
- setattr(test_func, 'Foo', 5)
-
- assert hasattr(my_partial, 'Foo')
-
- assert getattr(my_partial, 'Foo', None) == 5
-
- a = dir(test_func)
- b = dir(my_partial)
- assert a == b
-
- assert not hasattr(test_func, 'Bar')
- setattr(my_partial, 'Bar', 6)
- assert hasattr(test_func, 'Bar')
-
- assert getattr(test_func, 'Bar', None) == 6
-
-
def test_commandset_decorators(command_sets_app):
result = command_sets_app.app_cmd('cranberry juice extra1 extra2')
+ assert result is not None
+ assert result.data is not None
assert len(result.data['unknown']) == 2
assert 'extra1' in result.data['unknown']
assert 'extra2' in result.data['unknown']
@@ -240,7 +217,7 @@ def test_load_commandset_errors(command_sets_manual, capsys):
# create a conflicting command before installing CommandSet to verify rollback behavior
command_sets_manual._install_command_function('durian', cmd_set.do_durian)
with pytest.raises(CommandSetRegistrationError):
- command_sets_manual.install_command_set(cmd_set)
+ command_sets_manual.register_command_set(cmd_set)
# verify that the commands weren't installed
cmds_cats, cmds_doc, cmds_undoc, help_topics = command_sets_manual._build_command_info()
@@ -256,7 +233,7 @@ def test_load_commandset_errors(command_sets_manual, capsys):
command_sets_manual.app_cmd('alias create banana run_pyscript')
# now install a command set and verify the commands are now present
- command_sets_manual.install_command_set(cmd_set)
+ command_sets_manual.register_command_set(cmd_set)
out, err = capsys.readouterr()
# verify aliases and macros are deleted with warning if they conflict with a command
@@ -289,7 +266,7 @@ class LoadableBase(cmd2.CommandSet):
cut_subparsers = cut_parser.add_subparsers(title='item', help='item to cut')
@cmd2.with_argparser(cut_parser)
- def do_cut(self, cmd: cmd2.Cmd, ns: argparse.Namespace):
+ def do_cut(self, ns: argparse.Namespace):
"""Cut something"""
handler = ns.get_handler()
if handler is not None:
@@ -297,15 +274,15 @@ class LoadableBase(cmd2.CommandSet):
handler(ns)
else:
# No subcommand was provided, so call help
- cmd.pwarning('This command does nothing without sub-parsers registered')
- cmd.do_help('cut')
+ self._cmd.pwarning('This command does nothing without sub-parsers registered')
+ self._cmd.do_help('cut')
stir_parser = cmd2.Cmd2ArgumentParser('stir')
stir_subparsers = stir_parser.add_subparsers(title='item', help='what to stir')
@cmd2.with_argparser(stir_parser)
- def do_stir(self, cmd: cmd2.Cmd, ns: argparse.Namespace):
+ def do_stir(self, ns: argparse.Namespace):
"""Stir something"""
handler = ns.get_handler()
if handler is not None:
@@ -313,21 +290,21 @@ class LoadableBase(cmd2.CommandSet):
handler(ns)
else:
# No subcommand was provided, so call help
- cmd.pwarning('This command does nothing without sub-parsers registered')
- cmd.do_help('stir')
+ self._cmd.pwarning('This command does nothing without sub-parsers registered')
+ self._cmd.do_help('stir')
stir_pasta_parser = cmd2.Cmd2ArgumentParser('pasta', add_help=False)
stir_pasta_parser.add_argument('--option', '-o')
stir_pasta_parser.add_subparsers(title='style', help='Stir style')
@cmd2.as_subcommand_to('stir', 'pasta', stir_pasta_parser)
- def stir_pasta(self, cmd: cmd2.Cmd, ns: argparse.Namespace):
+ def stir_pasta(self, ns: argparse.Namespace):
handler = ns.get_handler()
if handler is not None:
# Call whatever subcommand function was selected
handler(ns)
else:
- cmd.poutput('Stir pasta haphazardly')
+ self._cmd.poutput('Stir pasta haphazardly')
class LoadableBadBase(cmd2.CommandSet):
@@ -335,7 +312,7 @@ class LoadableBadBase(cmd2.CommandSet):
super(LoadableBadBase, self).__init__()
self._dummy = dummy # prevents autoload
- def do_cut(self, cmd: cmd2.Cmd, ns: argparse.Namespace):
+ def do_cut(self, ns: argparse.Namespace):
"""Cut something"""
handler = ns.get_handler()
if handler is not None:
@@ -343,8 +320,8 @@ class LoadableBadBase(cmd2.CommandSet):
handler(ns)
else:
# No subcommand was provided, so call help
- cmd.poutput('This command does nothing without sub-parsers registered')
- cmd.do_help('cut')
+ self._cmd.poutput('This command does nothing without sub-parsers registered')
+ self._cmd.do_help('cut')
@cmd2.with_default_category('Fruits')
@@ -353,16 +330,16 @@ class LoadableFruits(cmd2.CommandSet):
super(LoadableFruits, self).__init__()
self._dummy = dummy # prevents autoload
- def do_apple(self, cmd: cmd2.Cmd, _: cmd2.Statement):
- cmd.poutput('Apple')
+ def do_apple(self, _: cmd2.Statement):
+ self._cmd.poutput('Apple')
banana_parser = cmd2.Cmd2ArgumentParser(add_help=False)
banana_parser.add_argument('direction', choices=['discs', 'lengthwise'])
@cmd2.as_subcommand_to('cut', 'banana', banana_parser, help='Cut banana', aliases=['bananer'])
- def cut_banana(self, cmd: cmd2.Cmd, ns: argparse.Namespace):
+ def cut_banana(self, ns: argparse.Namespace):
"""Cut banana"""
- cmd.poutput('cutting banana: ' + ns.direction)
+ self._cmd.poutput('cutting banana: ' + ns.direction)
class LoadablePastaStir(cmd2.CommandSet):
@@ -374,8 +351,8 @@ class LoadablePastaStir(cmd2.CommandSet):
stir_pasta_vigor_parser.add_argument('frequency')
@cmd2.as_subcommand_to('stir pasta', 'vigorously', stir_pasta_vigor_parser)
- def stir_pasta_vigorously(self, cmd: cmd2.Cmd, ns: argparse.Namespace):
- cmd.poutput('stir the pasta vigorously')
+ def stir_pasta_vigorously(self, ns: argparse.Namespace):
+ self._cmd.poutput('stir the pasta vigorously')
@cmd2.with_default_category('Vegetables')
@@ -384,18 +361,18 @@ class LoadableVegetables(cmd2.CommandSet):
super(LoadableVegetables, self).__init__()
self._dummy = dummy # prevents autoload
- def do_arugula(self, cmd: cmd2.Cmd, _: cmd2.Statement):
- cmd.poutput('Arugula')
+ def do_arugula(self, _: cmd2.Statement):
+ self._cmd.poutput('Arugula')
- def complete_style_arg(self, cmd: cmd2.Cmd, text: str, line: str, begidx: int, endidx: int) -> List[str]:
+ def complete_style_arg(self, text: str, line: str, begidx: int, endidx: int) -> List[str]:
return ['quartered', 'diced']
bokchoy_parser = cmd2.Cmd2ArgumentParser(add_help=False)
bokchoy_parser.add_argument('style', completer_method=complete_style_arg)
@cmd2.as_subcommand_to('cut', 'bokchoy', bokchoy_parser)
- def cut_bokchoy(self, cmd: cmd2.Cmd, _: cmd2.Statement):
- cmd.poutput('Bok Choy')
+ def cut_bokchoy(self, _: cmd2.Statement):
+ self._cmd.poutput('Bok Choy')
def test_subcommands(command_sets_manual):
@@ -407,12 +384,12 @@ def test_subcommands(command_sets_manual):
# installing subcommands without base command present raises exception
with pytest.raises(CommandSetRegistrationError):
- command_sets_manual.install_command_set(fruit_cmds)
+ command_sets_manual.register_command_set(fruit_cmds)
# if the base command is present but isn't an argparse command, expect exception
- command_sets_manual.install_command_set(badbase_cmds)
+ command_sets_manual.register_command_set(badbase_cmds)
with pytest.raises(CommandSetRegistrationError):
- command_sets_manual.install_command_set(fruit_cmds)
+ command_sets_manual.register_command_set(fruit_cmds)
# verify that the commands weren't installed
cmds_cats, cmds_doc, cmds_undoc, help_topics = command_sets_manual._build_command_info()
@@ -420,8 +397,8 @@ def test_subcommands(command_sets_manual):
assert 'Fruits' not in cmds_cats
# Now install the good base commands
- command_sets_manual.uninstall_command_set(badbase_cmds)
- command_sets_manual.install_command_set(base_cmds)
+ command_sets_manual.unregister_command_set(badbase_cmds)
+ command_sets_manual.register_command_set(base_cmds)
# verify that we catch an attempt to register subcommands when the commandset isn't installed
with pytest.raises(CommandSetRegistrationError):
@@ -431,8 +408,8 @@ def test_subcommands(command_sets_manual):
assert 'This command does nothing without sub-parsers registered' in cmd_result.stderr
# verify that command set install without problems
- command_sets_manual.install_command_set(fruit_cmds)
- command_sets_manual.install_command_set(veg_cmds)
+ command_sets_manual.register_command_set(fruit_cmds)
+ command_sets_manual.register_command_set(veg_cmds)
cmds_cats, cmds_doc, cmds_undoc, help_topics = command_sets_manual._build_command_info()
assert 'Fruits' in cmds_cats
@@ -460,21 +437,21 @@ def test_subcommands(command_sets_manual):
assert ['diced', 'quartered'] == command_sets_manual.completion_matches
# verify that command set uninstalls without problems
- command_sets_manual.uninstall_command_set(fruit_cmds)
+ command_sets_manual.unregister_command_set(fruit_cmds)
cmds_cats, cmds_doc, cmds_undoc, help_topics = command_sets_manual._build_command_info()
assert 'Fruits' not in cmds_cats
# verify a double-unregister raises exception
with pytest.raises(CommandSetRegistrationError):
command_sets_manual._unregister_subcommands(fruit_cmds)
- command_sets_manual.uninstall_command_set(veg_cmds)
+ command_sets_manual.unregister_command_set(veg_cmds)
# Disable command and verify subcommands still load and unload
command_sets_manual.disable_command('cut', 'disabled for test')
# verify that command set install without problems
- command_sets_manual.install_command_set(fruit_cmds)
- command_sets_manual.install_command_set(veg_cmds)
+ command_sets_manual.register_command_set(fruit_cmds)
+ command_sets_manual.register_command_set(veg_cmds)
command_sets_manual.enable_command('cut')
@@ -505,7 +482,7 @@ def test_subcommands(command_sets_manual):
command_sets_manual.disable_command('cut', 'disabled for test')
# verify that command set uninstalls without problems
- command_sets_manual.uninstall_command_set(fruit_cmds)
+ command_sets_manual.unregister_command_set(fruit_cmds)
cmds_cats, cmds_doc, cmds_undoc, help_topics = command_sets_manual._build_command_info()
assert 'Fruits' not in cmds_cats
@@ -514,10 +491,10 @@ def test_subcommands(command_sets_manual):
command_sets_manual._unregister_subcommands(fruit_cmds)
with pytest.raises(CommandSetRegistrationError):
- command_sets_manual.uninstall_command_set(base_cmds)
+ command_sets_manual.unregister_command_set(base_cmds)
- command_sets_manual.uninstall_command_set(veg_cmds)
- command_sets_manual.uninstall_command_set(base_cmds)
+ command_sets_manual.unregister_command_set(veg_cmds)
+ command_sets_manual.unregister_command_set(base_cmds)
def test_nested_subcommands(command_sets_manual):
base_cmds = LoadableBase(1)
@@ -526,14 +503,14 @@ def test_nested_subcommands(command_sets_manual):
pasta_cmds = LoadablePastaStir(1)
with pytest.raises(CommandSetRegistrationError):
- command_sets_manual.install_command_set(pasta_cmds)
+ command_sets_manual.register_command_set(pasta_cmds)
- command_sets_manual.install_command_set(base_cmds)
+ command_sets_manual.register_command_set(base_cmds)
- command_sets_manual.install_command_set(pasta_cmds)
+ command_sets_manual.register_command_set(pasta_cmds)
with pytest.raises(CommandSetRegistrationError):
- command_sets_manual.uninstall_command_set(base_cmds)
+ command_sets_manual.unregister_command_set(base_cmds)
class BadNestedSubcommands(cmd2.CommandSet):
def __init__(self, dummy):
@@ -544,11 +521,11 @@ def test_nested_subcommands(command_sets_manual):
stir_pasta_vigor_parser.add_argument('frequency')
@cmd2.as_subcommand_to('stir sauce', 'vigorously', stir_pasta_vigor_parser)
- def stir_pasta_vigorously(self, cmd: cmd2.Cmd, ns: argparse.Namespace):
- cmd.poutput('stir the pasta vigorously')
+ def stir_pasta_vigorously(self, ns: argparse.Namespace):
+ self._cmd.poutput('stir the pasta vigorously')
with pytest.raises(CommandSetRegistrationError):
- command_sets_manual.install_command_set(BadNestedSubcommands(1))
+ command_sets_manual.register_command_set(BadNestedSubcommands(1))
class AppWithSubCommands(cmd2.Cmd):
@@ -631,7 +608,7 @@ class WithCompleterCommandSet(cmd2.CommandSet):
"""dummy variable prevents this from being autoloaded in other tests"""
super(WithCompleterCommandSet, self).__init__()
- def complete_states(self, cmd: cmd2.Cmd, text: str, line: str, begidx: int, endidx: int) -> List[str]:
+ def complete_states(self, text: str, line: str, begidx: int, endidx: int) -> List[str]:
assert self is complete_states_expected_self
return utils.basic_complete(text, line, begidx, endidx, self.states)
@@ -641,8 +618,8 @@ class SubclassCommandSetCase1(WithCompleterCommandSet):
parser.add_argument('state', type=str, completer_method=WithCompleterCommandSet.complete_states)
@cmd2.with_argparser(parser)
- def do_case1(self, cmd: cmd2.Cmd, ns: argparse.Namespace):
- cmd.poutput('something {}'.format(ns.state))
+ def do_case1(self, ns: argparse.Namespace):
+ self._cmd.poutput('something {}'.format(ns.state))
class SubclassCommandSetErrorCase2(WithCompleterCommandSet):
@@ -650,8 +627,8 @@ class SubclassCommandSetErrorCase2(WithCompleterCommandSet):
parser.add_argument('state', type=str, completer_method=WithCompleterCommandSet.complete_states)
@cmd2.with_argparser(parser)
- def do_error2(self, cmd: cmd2.Cmd, ns: argparse.Namespace):
- cmd.poutput('something {}'.format(ns.state))
+ def do_error2(self, ns: argparse.Namespace):
+ self._cmd.poutput('something {}'.format(ns.state))
class SubclassCommandSetCase2(cmd2.CommandSet):
@@ -663,8 +640,8 @@ class SubclassCommandSetCase2(cmd2.CommandSet):
parser.add_argument('state', type=str, completer_method=WithCompleterCommandSet.complete_states)
@cmd2.with_argparser(parser)
- def do_case2(self, cmd: cmd2.Cmd, ns: argparse.Namespace):
- cmd.poutput('something {}'.format(ns.state))
+ def do_case2(self, ns: argparse.Namespace):
+ self._cmd.poutput('something {}'.format(ns.state))
def test_cross_commandset_completer(command_sets_manual):
@@ -678,7 +655,7 @@ def test_cross_commandset_completer(command_sets_manual):
# CommandSet instance as self when calling the completer
case1_set = SubclassCommandSetCase1(1)
- command_sets_manual.install_command_set(case1_set)
+ command_sets_manual.register_command_set(case1_set)
text = ''
line = 'case1 {}'.format(text)
@@ -691,7 +668,7 @@ def test_cross_commandset_completer(command_sets_manual):
assert first_match == 'alabama'
assert command_sets_manual.completion_matches == WithCompleterCommandSet.states
- command_sets_manual.uninstall_command_set(case1_set)
+ command_sets_manual.unregister_command_set(case1_set)
####################################################################################################################
# This exercises Case 2
@@ -701,8 +678,8 @@ def test_cross_commandset_completer(command_sets_manual):
# First verify that, without the correct command set
base_set = WithCompleterCommandSet(1)
case2_set = SubclassCommandSetCase2(2)
- command_sets_manual.install_command_set(base_set)
- command_sets_manual.install_command_set(case2_set)
+ command_sets_manual.register_command_set(base_set)
+ command_sets_manual.register_command_set(case2_set)
text = ''
line = 'case2 {}'.format(text)
@@ -715,8 +692,8 @@ def test_cross_commandset_completer(command_sets_manual):
assert first_match == 'alabama'
assert command_sets_manual.completion_matches == WithCompleterCommandSet.states
- command_sets_manual.uninstall_command_set(case2_set)
- command_sets_manual.uninstall_command_set(base_set)
+ command_sets_manual.unregister_command_set(case2_set)
+ command_sets_manual.unregister_command_set(base_set)
####################################################################################################################
# This exercises Case 3
@@ -724,8 +701,8 @@ def test_cross_commandset_completer(command_sets_manual):
# and no exact type match can be found, but sub-class matches can be found and there is only a single
# subclass match, then use the lone subclass match as the parent CommandSet.
- command_sets_manual.install_command_set(case1_set)
- command_sets_manual.install_command_set(case2_set)
+ command_sets_manual.register_command_set(case1_set)
+ command_sets_manual.register_command_set(case2_set)
text = ''
line = 'case2 {}'.format(text)
@@ -738,8 +715,8 @@ def test_cross_commandset_completer(command_sets_manual):
assert first_match == 'alabama'
assert command_sets_manual.completion_matches == WithCompleterCommandSet.states
- command_sets_manual.uninstall_command_set(case2_set)
- command_sets_manual.uninstall_command_set(case1_set)
+ command_sets_manual.unregister_command_set(case2_set)
+ command_sets_manual.unregister_command_set(case1_set)
####################################################################################################################
# Error Case 1
@@ -747,7 +724,7 @@ def test_cross_commandset_completer(command_sets_manual):
# all installed CommandSet instances for one that is an exact type match, none are found
# search for sub-class matches, also none are found.
- command_sets_manual.install_command_set(case2_set)
+ command_sets_manual.register_command_set(case2_set)
text = ''
line = 'case2 {}'.format(text)
@@ -758,7 +735,7 @@ def test_cross_commandset_completer(command_sets_manual):
assert first_match is None
assert command_sets_manual.completion_matches == []
- command_sets_manual.uninstall_command_set(case2_set)
+ command_sets_manual.unregister_command_set(case2_set)
####################################################################################################################
# Error Case 2
@@ -767,9 +744,9 @@ def test_cross_commandset_completer(command_sets_manual):
# search for sub-class matches, more than 1 is found
error_case2_set = SubclassCommandSetErrorCase2(4)
- command_sets_manual.install_command_set(case1_set)
- command_sets_manual.install_command_set(case2_set)
- command_sets_manual.install_command_set(error_case2_set)
+ command_sets_manual.register_command_set(case1_set)
+ command_sets_manual.register_command_set(case2_set)
+ command_sets_manual.register_command_set(error_case2_set)
text = ''
line = 'case2 {}'.format(text)
@@ -780,7 +757,7 @@ def test_cross_commandset_completer(command_sets_manual):
assert first_match is None
assert command_sets_manual.completion_matches == []
- command_sets_manual.uninstall_command_set(case2_set)
+ command_sets_manual.unregister_command_set(case2_set)
class CommandSetWithPathComplete(cmd2.CommandSet):
@@ -799,7 +776,7 @@ class CommandSetWithPathComplete(cmd2.CommandSet):
def test_path_complete(command_sets_manual):
test_set = CommandSetWithPathComplete(1)
- command_sets_manual.install_command_set(test_set)
+ command_sets_manual.register_command_set(test_set)
text = ''
line = 'path {}'.format(text)