summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--cmd2/argparse_custom.py31
-rw-r--r--examples/modular_commands/commandset_basic.py31
-rw-r--r--examples/modular_commands/commandset_complex.py53
-rw-r--r--examples/modular_commands/commandset_custominit.py14
-rw-r--r--examples/modular_commands_main.py1
-rw-r--r--isolated_tests/test_commandset/test_commandset.py90
6 files changed, 154 insertions, 66 deletions
diff --git a/cmd2/argparse_custom.py b/cmd2/argparse_custom.py
index 485f65c2..74bddfc7 100644
--- a/cmd2/argparse_custom.py
+++ b/cmd2/argparse_custom.py
@@ -728,11 +728,32 @@ class Cmd2HelpFormatter(argparse.RawTextHelpFormatter):
class Cmd2ArgumentParser(argparse.ArgumentParser):
"""Custom ArgumentParser class that improves error and help output"""
- def __init__(self, *args, **kwargs) -> None:
- if 'formatter_class' not in kwargs:
- kwargs['formatter_class'] = Cmd2HelpFormatter
-
- super().__init__(*args, **kwargs)
+ def __init__(self,
+ prog=None,
+ usage=None,
+ description=None,
+ epilog=None,
+ parents=None,
+ formatter_class=Cmd2HelpFormatter,
+ prefix_chars='-',
+ fromfile_prefix_chars=None,
+ argument_default=None,
+ conflict_handler='error',
+ add_help=True,
+ allow_abbrev=True) -> None:
+ super(Cmd2ArgumentParser, self).__init__(
+ prog=prog,
+ usage=usage,
+ description=description,
+ epilog=epilog,
+ parents=parents if parents else [],
+ formatter_class=formatter_class,
+ prefix_chars=prefix_chars,
+ fromfile_prefix_chars=fromfile_prefix_chars,
+ argument_default=argument_default,
+ conflict_handler=conflict_handler,
+ add_help=add_help,
+ allow_abbrev=allow_abbrev)
def add_subparsers(self, **kwargs):
"""Custom override. Sets a default title if one was not given."""
diff --git a/examples/modular_commands/commandset_basic.py b/examples/modular_commands/commandset_basic.py
index 25ba976d..105530e8 100644
--- a/examples/modular_commands/commandset_basic.py
+++ b/examples/modular_commands/commandset_basic.py
@@ -4,39 +4,10 @@ A simple example demonstrating a loadable command set
"""
from typing import List
-from cmd2 import Cmd, CommandSet, Statement, register_command, with_category, with_default_category
+from cmd2 import Cmd, CommandSet, Statement, with_category, with_default_category
from cmd2.utils import CompletionError
-@register_command
-@with_category("AAA")
-def do_unbound(cmd: Cmd, statement: Statement):
- """This is an example of registering an unbound function
-
- :param cmd:
- :param statement:
- :return:
- """
- cmd.poutput('Unbound Command: {}'.format(statement.args))
-
-
-@register_command
-@with_category("AAA")
-def do_func_with_help(cmd: Cmd, statement: Statement):
- """
- This is an example of registering an unbound function
-
- :param cmd:
- :param statement:
- :return:
- """
- cmd.poutput('Unbound Command: {}'.format(statement.args))
-
-
-def help_func_with_help(cmd: Cmd):
- cmd.poutput('Help for func_with_help')
-
-
@with_default_category('Basic Completion')
class BasicCompletionCommandSet(CommandSet):
# List of strings used with completion functions
diff --git a/examples/modular_commands/commandset_complex.py b/examples/modular_commands/commandset_complex.py
new file mode 100644
index 00000000..5a031bd0
--- /dev/null
+++ b/examples/modular_commands/commandset_complex.py
@@ -0,0 +1,53 @@
+# coding=utf-8
+# flake8: noqa E302
+"""
+Test CommandSet
+"""
+
+import argparse
+from typing import List
+
+import cmd2
+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_banana(self, cmd: cmd2.Cmd, statement: cmd2.Statement):
+ """Banana Command"""
+ cmd.poutput('Banana!!')
+
+ cranberry_parser = cmd2.Cmd2ArgumentParser('cranberry')
+ cranberry_parser.add_argument('arg1', choices=['lemonade', 'juice', 'sauce'])
+
+ @cmd2.with_argparser_and_unknown_args(cranberry_parser)
+ def do_cranberry(self, cmd: cmd2.Cmd, ns: argparse.Namespace, unknown: List[str]):
+ 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,
+ 'unknown': unknown}
+
+ def help_cranberry(self, cmd: cmd2.Cmd):
+ 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]):
+ """Durian Command"""
+ cmd.poutput('{} Arguments: '.format(len(args)))
+ cmd.poutput(', '.join(['{}']*len(args)).format(*args))
+
+ def complete_durian(self, cmd: cmd2.Cmd, 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')
+ elderberry_parser.add_argument('arg1')
+
+ @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))
diff --git a/examples/modular_commands/commandset_custominit.py b/examples/modular_commands/commandset_custominit.py
index d96c5f1c..fa26644b 100644
--- a/examples/modular_commands/commandset_custominit.py
+++ b/examples/modular_commands/commandset_custominit.py
@@ -2,19 +2,7 @@
"""
A simple example demonstrating a loadable command set
"""
-from cmd2 import Cmd, CommandSet, Statement, register_command, with_category, with_default_category
-
-
-@register_command
-@with_category("AAA")
-def do_another_command(cmd: Cmd, statement: Statement):
- """
- This is an example of registering an unbound function
- :param cmd:
- :param statement:
- :return:
- """
- cmd.poutput('Another Unbound Command: {}'.format(statement.args))
+from cmd2 import Cmd, CommandSet, Statement, with_category, with_default_category
@with_default_category('Custom Init')
diff --git a/examples/modular_commands_main.py b/examples/modular_commands_main.py
index 9e7f79cc..fd10d8d3 100644
--- a/examples/modular_commands_main.py
+++ b/examples/modular_commands_main.py
@@ -10,6 +10,7 @@ from cmd2 import Cmd, Cmd2ArgumentParser, CommandSet, CompletionItem, with_argpa
from cmd2.utils import CompletionError, basic_complete
from modular_commands.commandset_basic import BasicCompletionCommandSet # noqa: F401
from modular_commands.commandset_custominit import CustomInitCommandSet # noqa: F401
+from modular_commands.commandset_complex import CommandSetA # noqa: F401
# Data source for argparse.choices
food_item_strs = ['Pizza', 'Ham', 'Ham Sandwich', 'Potato']
diff --git a/isolated_tests/test_commandset/test_commandset.py b/isolated_tests/test_commandset/test_commandset.py
index 8de2d3b0..023ea30d 100644
--- a/isolated_tests/test_commandset/test_commandset.py
+++ b/isolated_tests/test_commandset/test_commandset.py
@@ -4,17 +4,17 @@
Test CommandSet
"""
+import argparse
from typing import List
import pytest
import cmd2
from cmd2 import utils
+from cmd2_ext_test import ExternalTestMixin
-from .conftest import complete_tester, normalize, run_cmd
-
-@cmd2.with_default_category('Command Set')
+@cmd2.with_default_category('Fruits')
class CommandSetA(cmd2.CommandSet):
def do_apple(self, cmd: cmd2.Cmd, statement: cmd2.Statement):
cmd.poutput('Apple!')
@@ -23,28 +23,45 @@ class CommandSetA(cmd2.CommandSet):
"""Banana Command"""
cmd.poutput('Banana!!')
- def do_cranberry(self, cmd: cmd2.Cmd, statement: cmd2.Statement):
- cmd.poutput('Cranberry!!')
+ cranberry_parser = cmd2.Cmd2ArgumentParser('cranberry')
+ cranberry_parser.add_argument('arg1', choices=['lemonade', 'juice', 'sauce'])
+
+ @cmd2.with_argparser_and_unknown_args(cranberry_parser)
+ def do_cranberry(self, cmd: cmd2.Cmd, ns: argparse.Namespace, unknown: List[str]):
+ 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,
+ 'unknown': unknown}
def help_cranberry(self, cmd: cmd2.Cmd):
cmd.stdout.write('This command does diddly squat...\n')
- def do_durian(self, cmd: cmd2.Cmd, statement: cmd2.Statement):
+ @cmd2.with_argument_list
+ @cmd2.with_category('Also Alone')
+ def do_durian(self, cmd: cmd2.Cmd, args: List[str]):
"""Durian Command"""
- cmd.poutput('Durian!!')
+ cmd.poutput('{} Arguments: '.format(len(args)))
+ cmd.poutput(', '.join(['{}']*len(args)).format(*args))
+ cmd.last_result = {'args': args}
def complete_durian(self, cmd: cmd2.Cmd, 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')
+ elderberry_parser.add_argument('arg1')
+
@cmd2.with_category('Alone')
- def do_elderberry(self, cmd: cmd2.Cmd, statement: cmd2.Statement):
- cmd.poutput('Elderberry!!')
+ @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}
-class WithCommandSets(cmd2.Cmd):
+class WithCommandSets(ExternalTestMixin, cmd2.Cmd):
"""Class for testing custom help_* methods which override docstring help."""
def __init__(self, *args, **kwargs):
- super().__init__(*args, **kwargs)
+ super(WithCommandSets, self).__init__(*args, **kwargs)
@cmd2.with_default_category('Command Set B')
@@ -84,8 +101,11 @@ def test_autoload_commands(command_sets_app):
assert 'Alone' in cmds_cats
assert 'elderberry' in cmds_cats['Alone']
- assert 'Command Set' in cmds_cats
- assert 'cranberry' in cmds_cats['Command Set']
+ assert 'Also Alone' in cmds_cats
+ assert 'durian' in cmds_cats['Also Alone']
+
+ assert 'Fruits' in cmds_cats
+ assert 'cranberry' in cmds_cats['Fruits']
def test_custom_construct_commandsets():
@@ -96,6 +116,7 @@ def test_custom_construct_commandsets():
cmds_cats, cmds_doc, cmds_undoc, help_topics = app._build_command_info()
assert 'Command Set B' in cmds_cats
+ # Verifies that the same CommandSet can not be loaded twice
command_set_2 = CommandSetB('bar')
with pytest.raises(ValueError):
assert app.install_command_set(command_set_2)
@@ -112,8 +133,8 @@ def test_load_commands(command_sets_manual):
assert 'Alone' in cmds_cats
assert 'elderberry' in cmds_cats['Alone']
- assert 'Command Set' in cmds_cats
- assert 'cranberry' in cmds_cats['Command Set']
+ assert 'Fruits' in cmds_cats
+ 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)
@@ -121,7 +142,7 @@ def test_load_commands(command_sets_manual):
cmds_cats, cmds_doc, cmds_undoc, help_topics = command_sets_manual._build_command_info()
assert 'Alone' not in cmds_cats
- assert 'Command Set' not in cmds_cats
+ assert 'Fruits' not in cmds_cats
# reinstall the command set and verify it is accessible
command_sets_manual.install_command_set(cmd_set)
@@ -131,8 +152,8 @@ def test_load_commands(command_sets_manual):
assert 'Alone' in cmds_cats
assert 'elderberry' in cmds_cats['Alone']
- assert 'Command Set' in cmds_cats
- assert 'cranberry' in cmds_cats['Command Set']
+ assert 'Fruits' in cmds_cats
+ assert 'cranberry' in cmds_cats['Fruits']
def test_partial_with_passthru():
@@ -158,3 +179,36 @@ def test_partial_with_passthru():
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 len(result.data['unknown']) == 2
+ assert 'extra1' in result.data['unknown']
+ assert 'extra2' in result.data['unknown']
+ assert result.data['arg1'] == 'juice'
+ assert result.stderr is None
+
+ result = command_sets_app.app_cmd('durian juice extra1 extra2')
+ assert len(result.data['args']) == 3
+ assert 'juice' in result.data['args']
+ assert 'extra1' in result.data['args']
+ assert 'extra2' in result.data['args']
+ assert result.stderr is None
+
+ result = command_sets_app.app_cmd('durian')
+ assert len(result.data['args']) == 0
+ assert result.stderr is None
+
+ result = command_sets_app.app_cmd('elderberry')
+ assert result.stderr is not None
+ assert len(result.stderr) > 0
+ assert 'arguments are required' in result.stderr
+ assert result.data is None
+
+ result = command_sets_app.app_cmd('elderberry a b')
+ assert result.stderr is not None
+ assert len(result.stderr) > 0
+ assert 'unrecognized arguments' in result.stderr
+ assert result.data is None
+