diff options
author | Todd Leonhardt <todd.leonhardt@gmail.com> | 2017-02-10 19:02:33 -0500 |
---|---|---|
committer | GitHub <noreply@github.com> | 2017-02-10 19:02:33 -0500 |
commit | 68240f97141b6a0b4c9b64f3bfaa8c603b3963b9 (patch) | |
tree | 03d057334066f693f5fef4f99f120bba72d3b699 | |
parent | ec5539fa8c0d2f0b783869e73cacde1af32465b0 (diff) | |
parent | c879a8e4cc831c6032c297d7d42c5e71583706ba (diff) | |
download | cmd2-git-68240f97141b6a0b4c9b64f3bfaa8c603b3963b9.tar.gz |
Merge pull request #42 from python-cmd2/perror_improvement
Perror improvement
-rwxr-xr-x | cmd2.py | 44 | ||||
-rw-r--r-- | tests/test_cmd2.py | 4 | ||||
-rw-r--r-- | tests/test_transcript.py | 7 |
3 files changed, 49 insertions, 6 deletions
@@ -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 |