summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorTodd Leonhardt <todd.leonhardt@gmail.com>2017-02-10 19:02:33 -0500
committerGitHub <noreply@github.com>2017-02-10 19:02:33 -0500
commit68240f97141b6a0b4c9b64f3bfaa8c603b3963b9 (patch)
tree03d057334066f693f5fef4f99f120bba72d3b699
parentec5539fa8c0d2f0b783869e73cacde1af32465b0 (diff)
parentc879a8e4cc831c6032c297d7d42c5e71583706ba (diff)
downloadcmd2-git-68240f97141b6a0b4c9b64f3bfaa8c603b3963b9.tar.gz
Merge pull request #42 from python-cmd2/perror_improvement
Perror improvement
-rwxr-xr-xcmd2.py44
-rw-r--r--tests/test_cmd2.py4
-rw-r--r--tests/test_transcript.py7
3 files changed, 49 insertions, 6 deletions
diff --git a/cmd2.py b/cmd2.py
index 8aea72c6..d8c8583a 100755
--- a/cmd2.py
+++ b/cmd2.py
@@ -542,19 +542,27 @@ class Cmd(cmd.Cmd):
if msg[-1] != '\n':
self.stdout.write('\n')
- def perror(self, errmsg, exception_type=None):
+ def perror(self, errmsg, exception_type=None, traceback_war=True):
+ """ Print error message to sys.stderr and if debug is true, print an exception Traceback if one exists.
+
+ :param errmsg: str - error message to print out
+ :param exception_type: str - (optional) type of exception which precipitated this error message
+ :param traceback_war: bool - (optional) if True, print a message to let user know they can enable debug
+ :return:
+ """
if self.debug:
traceback.print_exc()
if exception_type is None:
- err = self.colorize("ERROR: {}'\n".format(errmsg), 'red')
+ err = self.colorize("ERROR: {}\n".format(errmsg), 'red')
sys.stderr.write(err)
else:
err = "EXCEPTION of type '{}' occured with message: '{}'\n".format(exception_type, errmsg)
sys.stderr.write(self.colorize(err, 'red'))
- war = "To enable full traceback, run the following command: 'set debug true'\n"
- sys.stderr.write(self.colorize(war, 'yellow'))
+ if traceback_war:
+ war = "To enable full traceback, run the following command: 'set debug true'\n"
+ sys.stderr.write(self.colorize(war, 'yellow'))
def pfeedback(self, msg):
"""For printing nonessential feedback. Can be silenced with `quiet`.
@@ -920,10 +928,28 @@ class Cmd(cmd.Cmd):
return p
def postparsing_precmd(self, statement):
- stop = 0
+ """This runs after parsing the command-line, but before anything else; even before adding cmd to history.
+
+ NOTE: This runs before precmd() and prior to any potential output redirection or piping.
+
+ If you wish to fatally fail this command and exit the application entirely, set stop = True.
+
+ If you wish to just fail this command you can do so by raising an exception:
+ raise EmptyStatement - will silently fail and do nothing
+ raise <AnyOtherException> - will fail and print an error message
+
+ :param statement: - the parsed command-line statement
+ :return: (bool, statement) - (stop, statement) containing a potentially modified version of the statement
+ """
+ stop = False
return stop, statement
def postparsing_postcmd(self, stop):
+ """This runs after everything else, including after postcmd().
+
+ :param stop: bool - True implies the entire application should exit.
+ :return: bool - True implies the entire application should exit.
+ """
return stop
def func_named(self, arg):
@@ -939,6 +965,11 @@ class Cmd(cmd.Cmd):
return result
def onecmd_plus_hooks(self, line):
+ """
+
+ :param line:
+ :return:
+ """
# The outermost level of try/finally nesting can be condensed once
# Python 2.4 support can be dropped.
stop = 0
@@ -963,6 +994,9 @@ class Cmd(cmd.Cmd):
self.restore_output(statement)
except EmptyStatement:
return 0
+ except ValueError as ex:
+ # If shlex.split failed on syntax, let user know whats going on
+ self.perror("Invalid syntax: {}".format(ex), traceback_war=False)
except Exception as ex:
self.perror(ex, type(ex).__name__)
finally:
diff --git a/tests/test_cmd2.py b/tests/test_cmd2.py
index aa9a76f2..b89f96d4 100644
--- a/tests/test_cmd2.py
+++ b/tests/test_cmd2.py
@@ -231,13 +231,15 @@ load {}
def test_base_load_default_file(base_app, capsys):
+ # TODO: Make sure to remove the 'command.txt' file in case it exists
+
# The way the load command works, we can't directly capture its stdout or stderr
run_cmd(base_app, 'load')
out, err = capsys.readouterr()
# The default file 'command.txt' doesn't exist, so we should get an error message
expected = normalize("""ERROR: Problem accessing script from command.txt:
-[Errno 2] No such file or directory: 'command.txt.txt''
+[Errno 2] No such file or directory: 'command.txt.txt'
To enable full traceback, run the following command: 'set debug true'
""")
assert normalize(str(err)) == expected
diff --git a/tests/test_transcript.py b/tests/test_transcript.py
index 7e89180a..6b229862 100644
--- a/tests/test_transcript.py
+++ b/tests/test_transcript.py
@@ -302,3 +302,10 @@ def test_multiline_command_transcript_with_comments_at_beginning(request, capsys
else:
assert err == ''
assert out == ''
+
+
+def test_invalid_syntax(_cmdline_app, capsys):
+ run_cmd(_cmdline_app, 'speak "')
+ out, err = capsys.readouterr()
+ expected = normalize("""ERROR: Invalid syntax: No closing quotation""")
+ assert normalize(str(err)) == expected