summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorEric Lin <anselor@gmail.com>2018-10-06 18:15:23 +0000
committerEric Lin <anselor@gmail.com>2018-10-06 18:15:23 +0000
commitfb575e41251156a90044055e8a352079e4f75866 (patch)
treec8f013e04d7a9e28164367228fb0249e5b1dbbb2
parent6d79731ae51229d46263dcddfc945946afa6e238 (diff)
parent467be57e647112f536becc8625ffa080cb67a0ce (diff)
downloadcmd2-git-fb575e41251156a90044055e8a352079e4f75866.tar.gz
Merge remote-tracking branch 'origin/master' into argparse_remainder
-rw-r--r--CHANGELOG.md2
-rwxr-xr-xcmd2/argparse_completer.py7
-rw-r--r--cmd2/cmd2.py73
-rw-r--r--cmd2/pyscript_bridge.py15
-rwxr-xr-xexamples/subcommands.py42
-rwxr-xr-xexamples/tab_autocomp_dynamic.py4
-rwxr-xr-xexamples/tab_autocompletion.py8
-rwxr-xr-xexamples/tab_completion.py2
-rw-r--r--tests/test_argparse.py18
-rw-r--r--tests/test_cmd2.py16
-rw-r--r--tests/test_completion.py36
-rw-r--r--tests/test_pyscript.py2
12 files changed, 134 insertions, 91 deletions
diff --git a/CHANGELOG.md b/CHANGELOG.md
index 4c5fd65e..0dc8ecca 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -41,7 +41,7 @@
have been deleted
* The new application lifecycle hook system allows for registration of callbacks to be called at various points
in the lifecycle and is more powerful and flexible than the previous system
- * ``alias`` is now a command with subcommands to create, list, and delete aliases. Therefore its syntax
+ * ``alias`` is now a command with sub-commands to create, list, and delete aliases. Therefore its syntax
has changed. All current alias commands in startup scripts or transcripts will break with this release.
* `unalias` was deleted since ``alias delete`` replaced it
diff --git a/cmd2/argparse_completer.py b/cmd2/argparse_completer.py
index b8d6244b..b8e3502e 100755
--- a/cmd2/argparse_completer.py
+++ b/cmd2/argparse_completer.py
@@ -965,6 +965,13 @@ class ACArgumentParser(argparse.ArgumentParser):
self._custom_error_message = custom_message
# End cmd2 customization
+ def add_subparsers(self, **kwargs):
+ """Custom override. Sets a default title if one was not given."""
+ if 'title' not in kwargs:
+ kwargs['title'] = 'sub-commands'
+
+ return super().add_subparsers(**kwargs)
+
def error(self, message: str) -> None:
"""Custom error override. Allows application to control the error being displayed by argparse"""
if len(self._custom_error_message) > 0:
diff --git a/cmd2/cmd2.py b/cmd2/cmd2.py
index 7aaacdb1..4502c53a 100644
--- a/cmd2/cmd2.py
+++ b/cmd2/cmd2.py
@@ -548,8 +548,8 @@ class Cmd(cmd.Cmd):
self.exit_code = None
# This lock should be acquired before doing any asynchronous changes to the terminal to
- # ensure the updates to the terminal don't interfere with the input being typed. It can be
- # acquired any time there is a readline prompt on screen.
+ # ensure the updates to the terminal don't interfere with the input being typed or output
+ # being printed by a command.
self.terminal_lock = threading.RLock()
# ----- Methods related to presenting output to the user -----
@@ -2204,7 +2204,7 @@ class Cmd(cmd.Cmd):
return stop
- # ----- Alias subcommand functions -----
+ # ----- Alias sub-command functions -----
def alias_create(self, args: argparse.Namespace):
"""Create or overwrite an alias"""
@@ -2267,8 +2267,8 @@ class Cmd(cmd.Cmd):
" macro")
alias_parser = ACArgumentParser(description=alias_description, epilog=alias_epilog, prog='alias')
- # Add subcommands to alias
- alias_subparsers = alias_parser.add_subparsers(title='sub-commands')
+ # Add sub-commands to alias
+ alias_subparsers = alias_parser.add_subparsers()
# alias -> create
alias_create_help = "create or overwrite an alias"
@@ -2326,13 +2326,13 @@ class Cmd(cmd.Cmd):
"""Manage aliases"""
func = getattr(args, 'func', None)
if func is not None:
- # Call whatever subcommand function was selected
+ # Call whatever sub-command function was selected
func(self, args)
else:
- # No subcommand was provided, so call help
+ # No sub-command was provided, so call help
self.do_help('alias')
- # ----- Macro subcommand functions -----
+ # ----- Macro sub-command functions -----
def macro_create(self, args: argparse.Namespace):
"""Create or overwrite a macro"""
@@ -2445,8 +2445,8 @@ class Cmd(cmd.Cmd):
" alias")
macro_parser = ACArgumentParser(description=macro_description, epilog=macro_epilog, prog='macro')
- # Add subcommands to macro
- macro_subparsers = macro_parser.add_subparsers(title='sub-commands')
+ # Add sub-commands to macro
+ macro_subparsers = macro_parser.add_subparsers()
# macro -> create
macro_create_help = "create or overwrite a macro"
@@ -2527,10 +2527,10 @@ class Cmd(cmd.Cmd):
"""Manage macros"""
func = getattr(args, 'func', None)
if func is not None:
- # Call whatever subcommand function was selected
+ # Call whatever sub-command function was selected
func(self, args)
else:
- # No subcommand was provided, so call help
+ # No sub-command was provided, so call help
self.do_help('macro')
def complete_help_command(self, text: str, line: str, begidx: int, endidx: int) -> List[str]:
@@ -2551,7 +2551,7 @@ class Cmd(cmd.Cmd):
if not tokens:
return []
- # Must have at least 3 args for 'help command subcommand'
+ # Must have at least 3 args for 'help command sub-command'
if len(tokens) < 3:
return []
@@ -2580,7 +2580,7 @@ class Cmd(cmd.Cmd):
setattr(help_parser.add_argument('command', help="command to retrieve help for", nargs="?"),
ACTION_ARG_CHOICES, ('complete_help_command',))
- setattr(help_parser.add_argument('subcommand', help="subcommand to retrieve help for",
+ setattr(help_parser.add_argument('subcommand', help="sub-command to retrieve help for",
nargs=argparse.REMAINDER),
ACTION_ARG_CHOICES, ('complete_help_subcommand',))
help_parser.add_argument('-v', '--verbose', action='store_true',
@@ -3481,12 +3481,13 @@ a..b, a:b, a:, ..b items by indices (inclusive)
def async_alert(self, alert_msg: str, new_prompt: Optional[str] = None) -> None: # pragma: no cover
"""
- Used to display an important message to the user while they are at the prompt in between commands.
+ Display an important message to the user while they are at the prompt in between commands.
To the user it appears as if an alert message is printed above the prompt and their current input
text and cursor location is left alone.
- IMPORTANT: Do not call this unless you have acquired self.terminal_lock
- first, which ensures a prompt is onscreen
+ IMPORTANT: This function will not print an alert unless it can acquire self.terminal_lock to ensure
+ a prompt is onscreen. Therefore it is best to acquire the lock before calling this function
+ to guarantee the alert prints.
:param alert_msg: the message to display to the user
:param new_prompt: if you also want to change the prompt that is displayed, then include it here
@@ -3525,34 +3526,48 @@ a..b, a:b, a:, ..b items by indices (inclusive)
def async_update_prompt(self, new_prompt: str) -> None: # pragma: no cover
"""
- Updates the prompt while the user is still typing at it. This is good for alerting the user to system
+ Update the prompt while the user is still typing at it. This is good for alerting the user to system
changes dynamically in between commands. For instance you could alter the color of the prompt to indicate
a system status or increase a counter to report an event. If you do alter the actual text of the prompt,
it is best to keep the prompt the same width as what's on screen. Otherwise the user's input text will
be shifted and the update will not be seamless.
- IMPORTANT: Do not call this unless you have acquired self.terminal_lock
- first, which ensures a prompt is onscreen
+ IMPORTANT: This function will not update the prompt unless it can acquire self.terminal_lock to ensure
+ a prompt is onscreen. Therefore it is best to acquire the lock before calling this function
+ to guarantee the prompt changes.
:param new_prompt: what to change the prompt to
+ :raises RuntimeError if called while another thread holds terminal_lock
"""
self.async_alert('', new_prompt)
- @staticmethod
- def set_window_title(title: str) -> None: # pragma: no cover
+ def set_window_title(self, title: str) -> None: # pragma: no cover
"""
- Sets the terminal window title
+ Set the terminal window title
+
+ IMPORTANT: This function will not set the title unless it can acquire self.terminal_lock to avoid
+ writing to stderr while a command is running. Therefore it is best to acquire the lock
+ before calling this function to guarantee the title changes.
+
:param title: the new window title
+ :raises RuntimeError if called while another thread holds terminal_lock
"""
if not vt100_support:
return
- import colorama.ansi as ansi
- try:
- sys.stderr.write(ansi.set_title(title))
- except AttributeError:
- # Debugging in Pycharm has issues with setting terminal title
- pass
+ # Sanity check that can't fail if self.terminal_lock was acquired before calling this function
+ if self.terminal_lock.acquire(blocking=False):
+ try:
+ import colorama.ansi as ansi
+ sys.stderr.write(ansi.set_title(title))
+ except AttributeError:
+ # Debugging in Pycharm has issues with setting terminal title
+ pass
+
+ self.terminal_lock.release()
+
+ else:
+ raise RuntimeError("another thread holds terminal_lock")
def cmdloop(self, intro: Optional[str]=None) -> None:
"""This is an outer wrapper around _cmdloop() which deals with extra features provided by cmd2.
diff --git a/cmd2/pyscript_bridge.py b/cmd2/pyscript_bridge.py
index 7920e1be..8187d7fd 100644
--- a/cmd2/pyscript_bridge.py
+++ b/cmd2/pyscript_bridge.py
@@ -33,9 +33,16 @@ class CommandResult(namedtuple_with_defaults('CommandResult', ['stdout', 'stderr
NOTE: Named tuples are immutable. So the contents are there for access, not for modification.
"""
- def __bool__(self):
- """If stderr is None and data is not None the command is considered a success"""
- return not self.stderr and self.data is not None
+ def __bool__(self) -> bool:
+ """Returns True if the command succeeded, otherwise False"""
+
+ # If data has a __bool__ method, then call it to determine success of command
+ if self.data is not None and callable(getattr(self.data, '__bool__', None)):
+ return bool(self.data)
+
+ # Otherwise check if stderr was filled out
+ else:
+ return not self.stderr
def _exec_cmd(cmd2_app, func: Callable, echo: bool) -> CommandResult:
@@ -91,7 +98,7 @@ class ArgparseFunctor:
return commands
def __getattr__(self, item: str):
- """Search for a subcommand matching this item and update internal state to track the traversal"""
+ """Search for a sub-command matching this item and update internal state to track the traversal"""
# look for sub-command under the current command/sub-command layer
for action in self.__current_subcommand_parser._actions:
if not action.option_strings and isinstance(action, argparse._SubParsersAction):
diff --git a/examples/subcommands.py b/examples/subcommands.py
index 02b06412..83c29393 100755
--- a/examples/subcommands.py
+++ b/examples/subcommands.py
@@ -1,9 +1,9 @@
#!/usr/bin/env python3
# coding=utf-8
-"""A simple example demonstrating how to use Argparse to support subcommands.
+"""A simple example demonstrating how to use Argparse to support sub-commands.
-This example shows an easy way for a single command to have many subcommands, each of which takes different arguments
+This example shows an easy way for a single command to have many sub-commands, each of which takes different arguments
and provides separate contextual help.
"""
import argparse
@@ -13,15 +13,15 @@ sport_item_strs = ['Bat', 'Basket', 'Basketball', 'Football', 'Space Ball']
# create the top-level parser for the base command
base_parser = argparse.ArgumentParser(prog='base')
-base_subparsers = base_parser.add_subparsers(title='subcommands', help='subcommand help')
+base_subparsers = base_parser.add_subparsers(title='sub-commands', help='sub-command help')
-# create the parser for the "foo" subcommand
+# create the parser for the "foo" sub-command
parser_foo = base_subparsers.add_parser('foo', help='foo help')
parser_foo.add_argument('-x', type=int, default=1, help='integer')
parser_foo.add_argument('y', type=float, help='float')
parser_foo.add_argument('input_file', type=str, help='Input File')
-# create the parser for the "bar" subcommand
+# create the parser for the "bar" sub-command
parser_bar = base_subparsers.add_parser('bar', help='bar help')
bar_subparsers = parser_bar.add_subparsers(title='layer3', help='help for 3rd layer of commands')
@@ -31,7 +31,7 @@ bar_subparsers.add_parser('apple', help='apple help')
bar_subparsers.add_parser('artichoke', help='artichoke help')
bar_subparsers.add_parser('cranberries', help='cranberries help')
-# create the parser for the "sport" subcommand
+# create the parser for the "sport" sub-command
parser_sport = base_subparsers.add_parser('sport', help='sport help')
sport_arg = parser_sport.add_argument('sport', help='Enter name of a sport')
setattr(sport_arg, 'arg_choices', sport_item_strs)
@@ -40,15 +40,15 @@ setattr(sport_arg, 'arg_choices', sport_item_strs)
# create the top-level parser for the alternate command
# The alternate command doesn't provide its own help flag
base2_parser = argparse.ArgumentParser(prog='alternate', add_help=False)
-base2_subparsers = base2_parser.add_subparsers(title='subcommands', help='subcommand help')
+base2_subparsers = base2_parser.add_subparsers(title='sub-commands', help='sub-command help')
-# create the parser for the "foo" subcommand
+# create the parser for the "foo" sub-command
parser_foo2 = base2_subparsers.add_parser('foo', help='foo help')
parser_foo2.add_argument('-x', type=int, default=1, help='integer')
parser_foo2.add_argument('y', type=float, help='float')
parser_foo2.add_argument('input_file', type=str, help='Input File')
-# create the parser for the "bar" subcommand
+# create the parser for the "bar" sub-command
parser_bar2 = base2_subparsers.add_parser('bar', help='bar help')
bar2_subparsers = parser_bar2.add_subparsers(title='layer3', help='help for 3rd layer of commands')
@@ -58,7 +58,7 @@ bar2_subparsers.add_parser('apple', help='apple help')
bar2_subparsers.add_parser('artichoke', help='artichoke help')
bar2_subparsers.add_parser('cranberries', help='cranberries help')
-# create the parser for the "sport" subcommand
+# create the parser for the "sport" sub-command
parser_sport2 = base2_subparsers.add_parser('sport', help='sport help')
sport2_arg = parser_sport2.add_argument('sport', help='Enter name of a sport')
setattr(sport2_arg, 'arg_choices', sport_item_strs)
@@ -66,26 +66,26 @@ setattr(sport2_arg, 'arg_choices', sport_item_strs)
class SubcommandsExample(cmd2.Cmd):
"""
- Example cmd2 application where we a base command which has a couple subcommands
- and the "sport" subcommand has tab completion enabled.
+ Example cmd2 application where we a base command which has a couple sub-commands
+ and the "sport" sub-command has tab completion enabled.
"""
def __init__(self):
super().__init__()
- # subcommand functions for the base command
+ # sub-command functions for the base command
def base_foo(self, args):
- """foo subcommand of base command"""
+ """foo sub-command of base command"""
self.poutput(args.x * args.y)
def base_bar(self, args):
- """bar subcommand of base command"""
+ """bar sub-command of base command"""
self.poutput('((%s))' % args.z)
def base_sport(self, args):
- """sport subcommand of base command"""
+ """sport sub-command of base command"""
self.poutput('Sport is {}'.format(args.sport))
- # Set handler functions for the subcommands
+ # Set handler functions for the sub-commands
parser_foo.set_defaults(func=base_foo)
parser_bar.set_defaults(func=base_bar)
parser_sport.set_defaults(func=base_sport)
@@ -95,10 +95,10 @@ class SubcommandsExample(cmd2.Cmd):
"""Base command help"""
func = getattr(args, 'func', None)
if func is not None:
- # Call whatever subcommand function was selected
+ # Call whatever sub-command function was selected
func(self, args)
else:
- # No subcommand was provided, so call help
+ # No sub-command was provided, so call help
self.do_help('base')
@cmd2.with_argparser(base2_parser)
@@ -106,10 +106,10 @@ class SubcommandsExample(cmd2.Cmd):
"""Alternate command help"""
func = getattr(args, 'func', None)
if func is not None:
- # Call whatever subcommand function was selected
+ # Call whatever sub-command function was selected
func(self, args)
else:
- # No subcommand was provided, so call help
+ # No sub-command was provided, so call help
self.do_help('alternate')
diff --git a/examples/tab_autocomp_dynamic.py b/examples/tab_autocomp_dynamic.py
index 2c90b7a2..af77b204 100755
--- a/examples/tab_autocomp_dynamic.py
+++ b/examples/tab_autocomp_dynamic.py
@@ -25,7 +25,7 @@ def query_actors() -> List[str]:
class TabCompleteExample(cmd2.Cmd):
- """ Example cmd2 application where we a base command which has a couple subcommands."""
+ """ Example cmd2 application where we a base command which has a couple sub-commands."""
CAT_AUTOCOMPLETE = 'AutoComplete Examples'
@@ -225,7 +225,7 @@ class TabCompleteExample(cmd2.Cmd):
@cmd2.with_category(CAT_AUTOCOMPLETE)
@cmd2.with_argparser(video_parser)
def do_video(self, args):
- """Video management command demonstrates multiple layers of subcommands being handled by AutoCompleter"""
+ """Video management command demonstrates multiple layers of sub-commands being handled by AutoCompleter"""
func = getattr(args, 'func', None)
if func is not None:
# Call whatever subcommand function was selected
diff --git a/examples/tab_autocompletion.py b/examples/tab_autocompletion.py
index 7725be95..571b4082 100755
--- a/examples/tab_autocompletion.py
+++ b/examples/tab_autocompletion.py
@@ -25,7 +25,7 @@ def query_actors() -> List[str]:
class TabCompleteExample(cmd2.Cmd):
- """ Example cmd2 application where we a base command which has a couple subcommands."""
+ """ Example cmd2 application where we a base command which has a couple sub-commands."""
CAT_AUTOCOMPLETE = 'AutoComplete Examples'
@@ -275,7 +275,7 @@ class TabCompleteExample(cmd2.Cmd):
@cmd2.with_category(CAT_AUTOCOMPLETE)
@cmd2.with_argparser(video_parser)
def do_video(self, args):
- """Video management command demonstrates multiple layers of subcommands being handled by AutoCompleter"""
+ """Video management command demonstrates multiple layers of sub-commands being handled by AutoCompleter"""
func = getattr(args, 'func', None)
if func is not None:
# Call whatever subcommand function was selected
@@ -358,7 +358,7 @@ class TabCompleteExample(cmd2.Cmd):
@cmd2.with_category(CAT_AUTOCOMPLETE)
@cmd2.with_argparser(media_parser)
def do_media(self, args):
- """Media management command demonstrates multiple layers of subcommands being handled by AutoCompleter"""
+ """Media management command demonstrates multiple layers of sub-commands being handled by AutoCompleter"""
func = getattr(args, 'func', None)
if func is not None:
# Call whatever subcommand function was selected
@@ -459,7 +459,7 @@ class TabCompleteExample(cmd2.Cmd):
@cmd2.with_category(CAT_AUTOCOMPLETE)
@cmd2.with_argparser(library_parser)
def do_library(self, args):
- """Media management command demonstrates multiple layers of subcommands being handled by AutoCompleter"""
+ """Media management command demonstrates multiple layers of sub-commands being handled by AutoCompleter"""
func = getattr(args, 'func', None)
if func is not None:
# Call whatever subcommand function was selected
diff --git a/examples/tab_completion.py b/examples/tab_completion.py
index 2ec7ff70..77d62988 100755
--- a/examples/tab_completion.py
+++ b/examples/tab_completion.py
@@ -12,7 +12,7 @@ sport_item_strs = ['Bat', 'Basket', 'Basketball', 'Football', 'Space Ball']
class TabCompleteExample(cmd2.Cmd):
- """ Example cmd2 application where we a base command which has a couple subcommands."""
+ """ Example cmd2 application where we a base command which has a couple sub-commands."""
def __init__(self):
super().__init__()
diff --git a/tests/test_argparse.py b/tests/test_argparse.py
index fdd16bcc..f1078e73 100644
--- a/tests/test_argparse.py
+++ b/tests/test_argparse.py
@@ -179,31 +179,31 @@ def test_arglist_decorator_twice(argparse_app):
class SubcommandApp(cmd2.Cmd):
- """ Example cmd2 application where we a base command which has a couple subcommands."""
+ """ Example cmd2 application where we a base command which has a couple sub-commands."""
def __init__(self):
cmd2.Cmd.__init__(self)
- # subcommand functions for the base command
+ # sub-command functions for the base command
def base_foo(self, args):
- """foo subcommand of base command"""
+ """foo sub-command of base command"""
self.poutput(args.x * args.y)
def base_bar(self, args):
- """bar subcommand of base command"""
+ """bar sub-command of base command"""
self.poutput('((%s))' % args.z)
# create the top-level parser for the base command
base_parser = argparse.ArgumentParser(prog='base')
- base_subparsers = base_parser.add_subparsers(title='subcommands', help='subcommand help')
+ base_subparsers = base_parser.add_subparsers(title='sub-commands', help='sub-command help')
- # create the parser for the "foo" subcommand
+ # create the parser for the "foo" sub-command
parser_foo = base_subparsers.add_parser('foo', help='foo help')
parser_foo.add_argument('-x', type=int, default=1, help='integer')
parser_foo.add_argument('y', type=float, help='float')
parser_foo.set_defaults(func=base_foo)
- # create the parser for the "bar" subcommand
+ # create the parser for the "bar" sub-command
parser_bar = base_subparsers.add_parser('bar', help='bar help')
parser_bar.add_argument('z', help='string')
parser_bar.set_defaults(func=base_bar)
@@ -213,10 +213,10 @@ class SubcommandApp(cmd2.Cmd):
"""Base command help"""
func = getattr(args, 'func', None)
if func is not None:
- # Call whatever subcommand function was selected
+ # Call whatever sub-command function was selected
func(self, args)
else:
- # No subcommand was provided, so call help
+ # No sub-command was provided, so call help
self.do_help('base')
@pytest.fixture
diff --git a/tests/test_cmd2.py b/tests/test_cmd2.py
index a64f21e4..a2bd6197 100644
--- a/tests/test_cmd2.py
+++ b/tests/test_cmd2.py
@@ -1576,8 +1576,14 @@ class CommandResultApp(cmd2.Cmd):
self._last_result = cmd2.CommandResult(arg, data=True)
def do_negative(self, arg):
+ self._last_result = cmd2.CommandResult(arg, data=False)
+
+ def do_affirmative_no_data(self, arg):
self._last_result = cmd2.CommandResult(arg)
+ def do_negative_no_data(self, arg):
+ self._last_result = cmd2.CommandResult('', arg)
+
@pytest.fixture
def commandresult_app():
app = CommandResultApp()
@@ -1590,11 +1596,19 @@ def test_commandresult_truthy(commandresult_app):
assert commandresult_app._last_result
assert commandresult_app._last_result == cmd2.CommandResult(arg, data=True)
+ run_cmd(commandresult_app, 'affirmative_no_data {}'.format(arg))
+ assert commandresult_app._last_result
+ assert commandresult_app._last_result == cmd2.CommandResult(arg)
+
def test_commandresult_falsy(commandresult_app):
arg = 'bar'
run_cmd(commandresult_app, 'negative {}'.format(arg))
assert not commandresult_app._last_result
- assert commandresult_app._last_result == cmd2.CommandResult(arg)
+ assert commandresult_app._last_result == cmd2.CommandResult(arg, data=False)
+
+ run_cmd(commandresult_app, 'negative_no_data {}'.format(arg))
+ assert not commandresult_app._last_result
+ assert commandresult_app._last_result == cmd2.CommandResult('', arg)
def test_is_text_file_bad_input(base_app):
diff --git a/tests/test_completion.py b/tests/test_completion.py
index 1b7b65d2..d722e534 100644
--- a/tests/test_completion.py
+++ b/tests/test_completion.py
@@ -784,7 +784,7 @@ def test_cmd2_help_subcommand_completion_nomatch(sc_app):
assert first_match is None
def test_subcommand_tab_completion(sc_app):
- # This makes sure the correct completer for the sport subcommand is called
+ # This makes sure the correct completer for the sport sub-command is called
text = 'Foot'
line = 'base sport {}'.format(text)
endidx = len(line)
@@ -797,8 +797,8 @@ def test_subcommand_tab_completion(sc_app):
def test_subcommand_tab_completion_with_no_completer(sc_app):
- # This tests what happens when a subcommand has no completer
- # In this case, the foo subcommand has no completer defined
+ # This tests what happens when a sub-command has no completer
+ # In this case, the foo sub-command has no completer defined
text = 'Foot'
line = 'base foo {}'.format(text)
endidx = len(line)
@@ -825,42 +825,42 @@ def test_subcommand_tab_completion_space_in_text(sc_app):
class SubcommandsWithUnknownExample(cmd2.Cmd):
"""
- Example cmd2 application where we a base command which has a couple subcommands
- and the "sport" subcommand has tab completion enabled.
+ Example cmd2 application where we a base command which has a couple sub-commands
+ and the "sport" sub-command has tab completion enabled.
"""
def __init__(self):
cmd2.Cmd.__init__(self)
- # subcommand functions for the base command
+ # sub-command functions for the base command
def base_foo(self, args):
- """foo subcommand of base command"""
+ """foo sub-command of base command"""
self.poutput(args.x * args.y)
def base_bar(self, args):
- """bar subcommand of base command"""
+ """bar sub-command of base command"""
self.poutput('((%s))' % args.z)
def base_sport(self, args):
- """sport subcommand of base command"""
+ """sport sub-command of base command"""
self.poutput('Sport is {}'.format(args.sport))
# create the top-level parser for the base command
base_parser = argparse.ArgumentParser(prog='base')
- base_subparsers = base_parser.add_subparsers(title='subcommands', help='subcommand help')
+ base_subparsers = base_parser.add_subparsers(title='sub-commands', help='sub-command help')
- # create the parser for the "foo" subcommand
+ # create the parser for the "foo" sub-command
parser_foo = base_subparsers.add_parser('foo', help='foo help')
parser_foo.add_argument('-x', type=int, default=1, help='integer')
parser_foo.add_argument('y', type=float, help='float')
parser_foo.set_defaults(func=base_foo)
- # create the parser for the "bar" subcommand
+ # create the parser for the "bar" sub-command
parser_bar = base_subparsers.add_parser('bar', help='bar help')
parser_bar.add_argument('z', help='string')
parser_bar.set_defaults(func=base_bar)
- # create the parser for the "sport" subcommand
+ # create the parser for the "sport" sub-command
parser_sport = base_subparsers.add_parser('sport', help='sport help')
sport_arg = parser_sport.add_argument('sport', help='Enter name of a sport')
setattr(sport_arg, 'arg_choices', sport_item_strs)
@@ -870,10 +870,10 @@ class SubcommandsWithUnknownExample(cmd2.Cmd):
"""Base command help"""
func = getattr(args, 'func', None)
if func is not None:
- # Call whatever subcommand function was selected
+ # Call whatever sub-command function was selected
func(self, args)
else:
- # No subcommand was provided, so call help
+ # No sub-command was provided, so call help
self.do_help('base')
@@ -977,7 +977,7 @@ def test_cmd2_help_subcommand_completion_nomatch_scu(scu_app):
def test_subcommand_tab_completion_scu(scu_app):
- # This makes sure the correct completer for the sport subcommand is called
+ # This makes sure the correct completer for the sport sub-command is called
text = 'Foot'
line = 'base sport {}'.format(text)
endidx = len(line)
@@ -990,8 +990,8 @@ def test_subcommand_tab_completion_scu(scu_app):
def test_subcommand_tab_completion_with_no_completer_scu(scu_app):
- # This tests what happens when a subcommand has no completer
- # In this case, the foo subcommand has no completer defined
+ # This tests what happens when a sub-command has no completer
+ # In this case, the foo sub-command has no completer defined
text = 'Foot'
line = 'base foo {}'.format(text)
endidx = len(line)
diff --git a/tests/test_pyscript.py b/tests/test_pyscript.py
index 36e48598..6b72e940 100644
--- a/tests/test_pyscript.py
+++ b/tests/test_pyscript.py
@@ -65,7 +65,7 @@ class PyscriptExample(Cmd):
@with_argparser(media_parser)
def do_media(self, args):
- """Media management command demonstrates multiple layers of subcommands being handled by AutoCompleter"""
+ """Media management command demonstrates multiple layers of sub-commands being handled by AutoCompleter"""
func = getattr(args, 'func', None)
if func is not None:
# Call whatever subcommand function was selected