summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--cmd2/cmd2.py54
-rw-r--r--tests/conftest.py2
-rw-r--r--tests/test_cmd2.py45
3 files changed, 41 insertions, 60 deletions
diff --git a/cmd2/cmd2.py b/cmd2/cmd2.py
index 2a617a75..012b6f6b 100644
--- a/cmd2/cmd2.py
+++ b/cmd2/cmd2.py
@@ -632,7 +632,7 @@ class Cmd(cmd.Cmd):
err_msg = err_color + err_msg + Fore.RESET
self.decolorized_write(sys.stderr, err_msg)
- if traceback_war:
+ if traceback_war and not self.debug:
war = "To enable full traceback, run the following command: 'set debug true'\n"
war = war_color + war + Fore.RESET
self.decolorized_write(sys.stderr, war)
@@ -1893,6 +1893,8 @@ class Cmd(cmd.Cmd):
try:
self.pipe_proc = subprocess.Popen(statement.pipe_to, stdin=subproc_stdin)
except Exception as ex:
+ self.perror('Not piping because - {}'.format(ex), traceback_war=False)
+
# Restore stdout to what it was and close the pipe
self.stdout.close()
subproc_stdin.close()
@@ -1901,8 +1903,6 @@ class Cmd(cmd.Cmd):
self.kept_state = None
self.redirecting = False
- # Re-raise the exception
- raise ex
elif statement.output:
import tempfile
if (not statement.output_to) and (not self.can_clip):
@@ -1920,7 +1920,7 @@ class Cmd(cmd.Cmd):
try:
sys.stdout = self.stdout = open(statement.output_to, mode)
except OSError as ex:
- self.perror('Not Redirecting because - {}'.format(ex), traceback_war=False)
+ self.perror('Not redirecting because - {}'.format(ex), traceback_war=False)
self.redirecting = False
else:
# going to a paste buffer
@@ -2007,8 +2007,10 @@ class Cmd(cmd.Cmd):
stop = func(statement)
else:
- self.default(statement)
- stop = False
+ stop = self.default(statement)
+
+ if stop is None:
+ stop = False
return stop
@@ -2056,19 +2058,18 @@ class Cmd(cmd.Cmd):
# Run the resolved command
return self.onecmd_plus_hooks(resolved)
- def default(self, statement: Statement) -> None:
+ def default(self, statement: Statement) -> Optional[bool]:
"""Executed when the command given isn't a recognized command implemented by a do_* method.
:param statement: Statement object with parsed input
"""
if self.default_to_shell:
- result = os.system(statement.command_and_args)
- # If os.system() succeeded, then don't print warning about unknown command
- if not result:
- return
+ if 'shell' not in self.exclude_from_history:
+ self.history.append(statement.raw)
- # Print out a message stating this is an unknown command
- self.poutput('*** Unknown syntax: {}\n'.format(statement.command_and_args))
+ return self.do_shell(statement.command_and_args)
+ else:
+ self.poutput('*** {} is not a recognized command, alias, or macro\n'.format(statement.command))
def pseudo_raw_input(self, prompt: str) -> str:
"""Began life as a copy of cmd's cmdloop; like raw_input but
@@ -2803,7 +2804,7 @@ class Cmd(cmd.Cmd):
:param args: argparse parsed arguments from the set command
:param parameter: optional search parameter
"""
- param = parameter.strip().lower()
+ param = utils.norm_fold(parameter.strip())
result = {}
maxlen = 0
@@ -2844,7 +2845,7 @@ class Cmd(cmd.Cmd):
# Check if param was passed in
if not args.param:
return self.show(args)
- param = args.param.strip().lower()
+ param = utils.norm_fold(args.param.strip())
# Check if value was passed in
if not args.value:
@@ -3156,15 +3157,19 @@ class Cmd(cmd.Cmd):
history_parser_group.add_argument('-e', '--edit', action='store_true',
help='edit and then run selected history items')
history_parser_group.add_argument('-s', '--script', action='store_true', help='output commands in script format')
- history_parser_group.add_argument('-o', '--output-file', metavar='FILE', help='output commands to a script file')
- history_parser_group.add_argument('-t', '--transcript', help='output commands and results to a transcript file')
+ setattr(history_parser_group.add_argument('-o', '--output-file', metavar='FILE',
+ help='output commands to a script file'),
+ ACTION_ARG_CHOICES, ('path_complete',))
+ setattr(history_parser_group.add_argument('-t', '--transcript',
+ help='output commands and results to a transcript file'),
+ ACTION_ARG_CHOICES, ('path_complete',))
history_parser_group.add_argument('-c', '--clear', action="store_true", help='clear all history')
- _history_arg_help = """empty all history items
-a one history item by number
-a..b, a:b, a:, ..b items by indices (inclusive)
-[string] items containing string
-/regex/ items matching regular expression"""
- history_parser.add_argument('arg', nargs='?', help=_history_arg_help)
+ history_arg_help = ("empty all history items\n"
+ "a one history item by number\n"
+ "a..b, a:b, a:, ..b items by indices (inclusive)\n"
+ "string items containing string\n"
+ "/regex/ items matching regular expression")
+ history_parser.add_argument('arg', nargs='?', help=history_arg_help)
@with_argparser(history_parser)
def do_history(self, args: argparse.Namespace) -> None:
@@ -3851,7 +3856,6 @@ class History(list):
end = int(end)
return self[start:end]
- # noinspection PyUnresolvedReferences
getme = getme.strip()
if getme.startswith(r'/') and getme.endswith(r'/'):
@@ -3871,7 +3875,7 @@ class History(list):
:param hi: HistoryItem
:return: bool - True if search matches
"""
- return getme.lower() in hi.lowercase
+ return utils.norm_fold(getme) in utils.norm_fold(hi)
return [itm for itm in self if isin(itm)]
diff --git a/tests/conftest.py b/tests/conftest.py
index da7e8b08..ac6a1896 100644
--- a/tests/conftest.py
+++ b/tests/conftest.py
@@ -59,7 +59,7 @@ positional arguments:
arg empty all history items
a one history item by number
a..b, a:b, a:, ..b items by indices (inclusive)
- [string] items containing string
+ string items containing string
/regex/ items matching regular expression
optional arguments:
diff --git a/tests/test_cmd2.py b/tests/test_cmd2.py
index 9bb85ffe..59c6bb60 100644
--- a/tests/test_cmd2.py
+++ b/tests/test_cmd2.py
@@ -298,7 +298,7 @@ def test_pyscript_requires_an_argument(base_app, capsys):
def test_base_error(base_app):
out = run_cmd(base_app, 'meow')
- assert out == ["*** Unknown syntax: meow"]
+ assert "is not a recognized command" in out[0]
@pytest.fixture
@@ -803,8 +803,7 @@ def test_pipe_to_shell_error(base_app, capsys):
run_cmd(base_app, 'help | foobarbaz.this_does_not_exist')
out, err = capsys.readouterr()
assert not out
- expected_error = 'FileNotFoundError'
- assert err.startswith("EXCEPTION of type '{}' occurred with message:".format(expected_error))
+ assert err.startswith("ERROR: Not piping because")
@pytest.mark.skipif(not clipboard.can_clip,
@@ -1042,12 +1041,12 @@ def hook_failure():
def test_precmd_hook_success(base_app):
out = base_app.onecmd_plus_hooks('help')
- assert out is None
+ assert out is False
def test_precmd_hook_failure(hook_failure):
out = hook_failure.onecmd_plus_hooks('help')
- assert out == True
+ assert out is True
class SayApp(cmd2.Cmd):
@@ -1098,40 +1097,18 @@ class ShellApp(cmd2.Cmd):
super().__init__(*args, **kwargs)
self.default_to_shell = True
-@pytest.fixture
-def shell_app():
- app = ShellApp()
- app.stdout = utils.StdSim(app.stdout)
- return app
-
-def test_default_to_shell_unknown(shell_app):
- unknown_command = 'zyxcw23'
- out = run_cmd(shell_app, unknown_command)
- assert out == ["*** Unknown syntax: {}".format(unknown_command)]
-
-def test_default_to_shell_good(capsys):
- app = cmd2.Cmd()
- app.default_to_shell = True
+def test_default_to_shell(base_app, monkeypatch):
if sys.platform.startswith('win'):
line = 'dir'
else:
line = 'ls'
- statement = app.statement_parser.parse(line)
- retval = app.default(statement)
- assert not retval
- out, err = capsys.readouterr()
- assert out == ''
-
-def test_default_to_shell_failure(capsys):
- app = cmd2.Cmd()
- app.default_to_shell = True
- line = 'ls does_not_exist.xyz'
- statement = app.statement_parser.parse(line)
- retval = app.default(statement)
- assert not retval
- out, err = capsys.readouterr()
- assert out == "*** Unknown syntax: {}\n".format(line)
+ base_app.default_to_shell = True
+ m = mock.Mock()
+ monkeypatch.setattr("{}.Popen".format('subprocess'), m)
+ out = run_cmd(base_app, line)
+ assert out == []
+ assert m.called
def test_ansi_prompt_not_esacped(base_app):
from cmd2.rl_utils import rl_make_safe_prompt