From 4f7d0f18509ab4f50c88e942e7ba33a7824b58ac Mon Sep 17 00:00:00 2001 From: kotfu Date: Sun, 22 Apr 2018 20:48:27 -0600 Subject: remove old pyparsing unit tests, they have all been duplicated in shlex --- tests/test_parsing.py | 239 -------------------------------------------------- 1 file changed, 239 deletions(-) (limited to 'tests/test_parsing.py') diff --git a/tests/test_parsing.py b/tests/test_parsing.py index 2682ec68..5825e735 100644 --- a/tests/test_parsing.py +++ b/tests/test_parsing.py @@ -20,39 +20,6 @@ def hist(): h = cmd2.cmd2.History([HistoryItem('first'), HistoryItem('second'), HistoryItem('third'), HistoryItem('fourth')]) return h -# Case-sensitive parser -@pytest.fixture -def parser(): - c = cmd2.Cmd() - c.multilineCommands = ['multiline'] - c.parser_manager = cmd2.cmd2.ParserManager(redirector=c.redirector, terminators=c.terminators, - multilineCommands=c.multilineCommands, legalChars=c.legalChars, - commentGrammars=c.commentGrammars, commentInProgress=c.commentInProgress, - blankLinesAllowed=c.blankLinesAllowed, prefixParser=c.prefixParser, - preparse=c.preparse, postparse=c.postparse, aliases=c.aliases, - shortcuts=c.shortcuts) - return c.parser_manager.main_parser - -# Case-sensitive ParserManager -@pytest.fixture -def cs_pm(): - c = cmd2.Cmd() - c.multilineCommands = ['multiline'] - c.parser_manager = cmd2.cmd2.ParserManager(redirector=c.redirector, terminators=c.terminators, - multilineCommands=c.multilineCommands, legalChars=c.legalChars, - commentGrammars=c.commentGrammars, commentInProgress=c.commentInProgress, - blankLinesAllowed=c.blankLinesAllowed, prefixParser=c.prefixParser, - preparse=c.preparse, postparse=c.postparse, aliases=c.aliases, - shortcuts=c.shortcuts) - return c.parser_manager - - -@pytest.fixture -def input_parser(): - c = cmd2.Cmd() - return c.parser_manager.input_source_parser - - def test_history_span(hist): h = hist assert h == ['first', 'second', 'third', 'fourth'] @@ -119,212 +86,6 @@ def test_cast_problems(capsys): out, err = capsys.readouterr() assert out == expected.format(current, new) - -def test_parse_empty_string(parser): - assert parser.parseString('').dump() == '[]' - -def test_parse_only_comment(parser): - assert parser.parseString('/* empty command */').dump() == '[]' - -def test_parse_single_word(parser): - line = 'plainword' - results = parser.parseString(line) - assert results.command == line - -def test_parse_word_plus_terminator(parser): - line = 'termbare;' - results = parser.parseString(line) - assert results.command == 'termbare' - assert results.terminator == ';' - -def test_parse_suffix_after_terminator(parser): - line = 'termbare; suffx' - results = parser.parseString(line) - assert results.command == 'termbare' - assert results.terminator == ';' - assert results.suffix == 'suffx' - -def test_parse_command_with_args(parser): - line = 'command with args' - results = parser.parseString(line) - assert results.command == 'command' - assert results.args == 'with args' - -def test_parse_command_with_args_terminator_and_suffix(parser): - line = 'command with args and terminator; and suffix' - results = parser.parseString(line) - assert results.command == 'command' - assert results.args == "with args and terminator" - assert results.terminator == ';' - assert results.suffix == 'and suffix' - -def test_parse_simple_piped(parser): - line = 'simple | piped' - results = parser.parseString(line) - assert results.command == 'simple' - assert results.pipeTo == " piped" - -def test_parse_double_pipe_is_not_a_pipe(parser): - line = 'double-pipe || is not a pipe' - results = parser.parseString(line) - assert results.command == 'double-pipe' - assert results.args == '|| is not a pipe' - assert not 'pipeTo' in results - -def test_parse_complex_pipe(parser): - line = 'command with args, terminator;sufx | piped' - results = parser.parseString(line) - assert results.command == 'command' - assert results.args == "with args, terminator" - assert results.terminator == ';' - assert results.suffix == 'sufx' - assert results.pipeTo == ' piped' - -def test_parse_output_redirect(parser): - line = 'output into > afile.txt' - results = parser.parseString(line) - assert results.command == 'output' - assert results.args == 'into' - assert results.output == '>' - assert results.outputTo == 'afile.txt' - -def test_parse_output_redirect_with_dash_in_path(parser): - line = 'output into > python-cmd2/afile.txt' - results = parser.parseString(line) - assert results.command == 'output' - assert results.args == 'into' - assert results.output == '>' - assert results.outputTo == 'python-cmd2/afile.txt' - - -def test_case_sensitive_parsed_single_word(cs_pm): - line = 'HeLp' - statement = cs_pm.parsed(line) - assert statement.parsed.command == line - - -def test_parse_input_redirect(input_parser): - line = '< afile.txt' - results = input_parser.parseString(line) - assert results.inputFrom == line - -def test_parse_input_redirect_with_dash_in_path(input_parser): - line = "< python-cmd2/afile.txt" - results = input_parser.parseString(line) - assert results.inputFrom == line - -def test_parse_pipe_and_redirect(parser): - line = 'output into;sufx | pipethrume plz > afile.txt' - results = parser.parseString(line) - assert results.command == 'output' - assert results.args == 'into' - assert results.terminator == ';' - assert results.suffix == 'sufx' - assert results.pipeTo == ' pipethrume plz' - assert results.output == '>' - assert results.outputTo == 'afile.txt' - -def test_parse_output_to_paste_buffer(parser): - line = 'output to paste buffer >> ' - results = parser.parseString(line) - assert results.command == 'output' - assert results.args == 'to paste buffer' - assert results.output == '>>' - -def test_parse_ignore_commented_redirectors(parser): - line = 'ignore the /* commented | > */ stuff;' - results = parser.parseString(line) - assert results.command == 'ignore' - assert results.args == 'the /* commented | > */ stuff' - assert results.terminator == ';' - -def test_parse_has_redirect_inside_terminator(parser): - """The terminator designates the end of the commmand/arguments portion. If a redirector - occurs before a terminator, then it will be treated as part of the arguments and not as a redirector.""" - line = 'has > inside;' - results = parser.parseString(line) - assert results.command == 'has' - assert results.args == '> inside' - assert results.terminator == ';' - -def test_parse_what_if_quoted_strings_seem_to_start_comments(parser): - line = 'what if "quoted strings /* seem to " start comments?' - results = parser.parseString(line) - assert results.command == 'what' - assert results.args == 'if "quoted strings /* seem to " start comments?' - -def test_parse_unfinished_multiliine_command(parser): - line = 'multiline has > inside an unfinished command' - results = parser.parseString(line) - assert results.multilineCommand == 'multiline' - assert not 'args' in results - -def test_parse_multiline_command_ignores_redirectors_within_it(parser): - line = 'multiline has > inside;' - results = parser.parseString(line) - assert results.multilineCommand == 'multiline' - assert results.args == 'has > inside' - assert results.terminator == ';' - -def test_parse_multiline_with_incomplete_comment(parser): - """A terminator within a comment will be ignored and won't terminate a multiline command. - Un-closed comments effectively comment out everything after the start.""" - line = 'multiline command /* with comment in progress;' - results = parser.parseString(line) - assert results.multilineCommand == 'multiline' - assert not 'args' in results - -def test_parse_multiline_with_complete_comment(parser): - line = 'multiline command /* with comment complete */ is done;' - results = parser.parseString(line) - assert results.multilineCommand == 'multiline' - assert results.args == 'command /* with comment complete */ is done' - assert results.terminator == ';' - -def test_parse_multiline_termninated_by_empty_line(parser): - line = 'multiline command ends\n\n' - results = parser.parseString(line) - assert results.multilineCommand == 'multiline' - assert results.args == 'command ends' - assert len(results.terminator) == 2 - assert results.terminator[0] == '\n' - assert results.terminator[1] == '\n' - -def test_parse_multiline_ignores_terminators_in_comments(parser): - line = 'multiline command "with term; ends" now\n\n' - results = parser.parseString(line) - assert results.multilineCommand == 'multiline' - assert results.args == 'command "with term; ends" now' - assert len(results.terminator) == 2 - assert results.terminator[0] == '\n' - assert results.terminator[1] == '\n' - -def test_parse_command_with_unicode_args(parser): - line = 'drink café' - results = parser.parseString(line) - assert results.command == 'drink' - assert results.args == 'café' - -def test_parse_unicode_command(parser): - line = 'café au lait' - results = parser.parseString(line) - assert results.command == 'café' - assert results.args == 'au lait' - -def test_parse_redirect_to_unicode_filename(parser): - line = 'dir home > café' - results = parser.parseString(line) - assert results.command == 'dir' - assert results.args == 'home' - assert results.output == '>' - assert results.outputTo == 'café' - -def test_parse_input_redirect_from_unicode_filename(input_parser): - line = '< café' - results = input_parser.parseString(line) - assert results.inputFrom == line - - def test_empty_statement_raises_exception(): app = cmd2.Cmd() with pytest.raises(cmd2.cmd2.EmptyStatement): -- cgit v1.2.1 From 8297d4d1c0a4f56c6c952059fb7fc2b43b1050ed Mon Sep 17 00:00:00 2001 From: kotfu Date: Tue, 24 Apr 2018 21:15:54 -0600 Subject: Refactoring and code cleanup - rename CommandParser to StatementParser - move tests from test_shlexparsing.py to test_parsing.py - standardize the output of the parse() method into a variable called statement. --- tests/test_parsing.py | 346 +++++++++++++++++++++++++++++++++++++++----------- 1 file changed, 270 insertions(+), 76 deletions(-) (limited to 'tests/test_parsing.py') diff --git a/tests/test_parsing.py b/tests/test_parsing.py index 5825e735..6fa7d629 100644 --- a/tests/test_parsing.py +++ b/tests/test_parsing.py @@ -1,90 +1,284 @@ # coding=utf-8 """ -Unit/functional testing for helper functions/classes in the cmd2.py module. - -These are primarily tests related to parsing. Moreover, they are mostly a port of the old doctest tests which were -problematic because they worked properly for some versions of pyparsing but not for others. +Test the parsing logic in parsing.py Copyright 2017 Todd Leonhardt Released under MIT license, see LICENSE file """ -import sys - import cmd2 +from cmd2.parsing import StatementParser + import pytest @pytest.fixture -def hist(): - from cmd2.cmd2 import HistoryItem - h = cmd2.cmd2.History([HistoryItem('first'), HistoryItem('second'), HistoryItem('third'), HistoryItem('fourth')]) - return h - -def test_history_span(hist): - h = hist - assert h == ['first', 'second', 'third', 'fourth'] - assert h.span('-2..') == ['third', 'fourth'] - assert h.span('2..3') == ['second', 'third'] # Inclusive of end - assert h.span('3') == ['third'] - assert h.span(':') == h - assert h.span('2..') == ['second', 'third', 'fourth'] - assert h.span('-1') == ['fourth'] - assert h.span('-2..-3') == ['third', 'second'] - assert h.span('*') == h - -def test_history_get(hist): - h = hist - assert h == ['first', 'second', 'third', 'fourth'] - assert h.get('') == h - assert h.get('-2') == h[:-2] - assert h.get('5') == [] - assert h.get('2-3') == ['second'] # Exclusive of end - assert h.get('ir') == ['first', 'third'] # Normal string search for all elements containing "ir" - assert h.get('/i.*d/') == ['third'] # Regex string search "i", then anything, then "d" - - -def test_cast(): - cast = cmd2.cmd2.cast - - # Boolean - assert cast(True, True) == True - assert cast(True, False) == False - assert cast(True, 0) == False - assert cast(True, 1) == True - assert cast(True, 'on') == True - assert cast(True, 'off') == False - assert cast(True, 'ON') == True - assert cast(True, 'OFF') == False - assert cast(True, 'y') == True - assert cast(True, 'n') == False - assert cast(True, 't') == True - assert cast(True, 'f') == False - - # Non-boolean same type - assert cast(1, 5) == 5 - assert cast(3.4, 2.7) == 2.7 - assert cast('foo', 'bar') == 'bar' - assert cast([1,2], [3,4]) == [3,4] - - -def test_cast_problems(capsys): - cast = cmd2.cmd2.cast - - expected = 'Problem setting parameter (now {}) to {}; incorrect type?\n' - - # Boolean current, with new value not convertible to bool - current = True - new = [True, True] - assert cast(current, new) == current - out, err = capsys.readouterr() - assert out == expected.format(current, new) - - # Non-boolean current, with new value not convertible to current type - current = 1 - new = 'octopus' - assert cast(current, new) == current - out, err = capsys.readouterr() - assert out == expected.format(current, new) +def parser(): + parser = StatementParser( + quotes=['"', "'"], + allow_redirection=True, + redirection_chars=['|', '<', '>'], + terminators = [';'], + multilineCommands = ['multiline'], + aliases = {'helpalias': 'help', '42': 'theanswer'}, + shortcuts = [('?', 'help'), ('!', 'shell')] + ) + return parser + +def test_parse_empty_string(parser): + statement = parser.parse('') + assert not statement.command + +@pytest.mark.parametrize('tokens,command,args', [ + ( [], None, ''), + ( ['command'], 'command', '' ), + ( ['command', 'arg1', 'arg2'], 'command', 'arg1 arg2') +]) +def test_command_and_args(parser, tokens, command, args): + (parsed_command, parsed_args) = parser._command_and_args(tokens) + assert command == parsed_command + assert args == parsed_args + +@pytest.mark.parametrize('line', [ + 'plainword', + '"one word"', + "'one word'", +]) +def test_single_word(parser, line): + statement = parser.parse(line) + assert statement.command == line + +def test_word_plus_terminator(parser): + line = 'termbare;' + statement = parser.parse(line) + assert statement.command == 'termbare' + assert statement.terminator == ';' + +def test_suffix_after_terminator(parser): + line = 'termbare; suffx' + statement = parser.parse(line) + assert statement.command == 'termbare' + assert statement.terminator == ';' + assert statement.suffix == 'suffx' + +def test_command_with_args(parser): + line = 'command with args' + statement = parser.parse(line) + assert statement.command == 'command' + assert statement.args == 'with args' + assert not statement.pipeTo + +def test_parse_command_with_args_terminator_and_suffix(parser): + line = 'command with args and terminator; and suffix' + statement = parser.parse(line) + assert statement.command == 'command' + assert statement.args == "with args and terminator" + assert statement.terminator == ';' + assert statement.suffix == 'and suffix' + +def test_hashcomment(parser): + statement = parser.parse('hi # this is all a comment') + assert statement.command == 'hi' + assert not statement.args + assert not statement.pipeTo + +def test_c_comment(parser): + statement = parser.parse('hi /* this is | all a comment */') + assert statement.command == 'hi' + assert not statement.args + assert not statement.pipeTo + +def test_c_comment_empty(parser): + statement = parser.parse('/* this is | all a comment */') + assert not statement.command + assert not statement.args + assert not statement.pipeTo + +def test_parse_what_if_quoted_strings_seem_to_start_comments(parser): + statement = parser.parse('what if "quoted strings /* seem to " start comments?') + assert statement.command == 'what' + assert statement.args == 'if "quoted strings /* seem to " start comments?' + assert not statement.pipeTo + +def test_simple_piped(parser): + statement = parser.parse('simple | piped') + assert statement.command == 'simple' + assert not statement.args + assert statement.pipeTo == 'piped' + +def test_double_pipe_is_not_a_pipe(parser): + line = 'double-pipe || is not a pipe' + statement = parser.parse(line) + assert statement.command == 'double-pipe' + assert statement.args == '|| is not a pipe' + assert not statement.pipeTo + +def test_complex_pipe(parser): + line = 'command with args, terminator;sufx | piped' + statement = parser.parse(line) + assert statement.command == 'command' + assert statement.args == "with args, terminator" + assert statement.terminator == ';' + assert statement.suffix == 'sufx' + assert statement.pipeTo == 'piped' + +def test_output_redirect(parser): + line = 'output into > afile.txt' + statement = parser.parse(line) + assert statement.command == 'output' + assert statement.args == 'into' + assert statement.output == '>' + assert statement.outputTo == 'afile.txt' + +def test_output_redirect_with_dash_in_path(parser): + line = 'output into > python-cmd2/afile.txt' + statement = parser.parse(line) + assert statement.command == 'output' + assert statement.args == 'into' + assert statement.output == '>' + assert statement.outputTo == 'python-cmd2/afile.txt' + +def test_output_redirect_append(parser): + line = 'output appended to >> /tmp/afile.txt' + statement = parser.parse(line) + assert statement.command == 'output' + assert statement.args == 'appended to' + assert statement.output == '>>' + assert statement.outputTo == '/tmp/afile.txt' + +def test_parse_input_redirect(parser): + line = '< afile.txt' + statement = parser.parse(line) + assert statement.inputFrom == 'afile.txt' + +def test_parse_input_redirect_after_command(parser): + line = 'help < afile.txt' + statement = parser.parse(line) + assert statement.command == 'help' + assert statement.args == '' + assert statement.inputFrom == 'afile.txt' + +def test_parse_input_redirect_with_dash_in_path(parser): + line = '< python-cmd2/afile.txt' + statement = parser.parse(line) + assert statement.inputFrom == 'python-cmd2/afile.txt' + +def test_pipe_and_redirect(parser): + line = 'output into;sufx | pipethrume plz > afile.txt' + statement = parser.parse(line) + assert statement.command == 'output' + assert statement.args == 'into' + assert statement.terminator == ';' + assert statement.suffix == 'sufx' + assert statement.pipeTo == 'pipethrume plz' + assert statement.output == '>' + assert statement.outputTo == 'afile.txt' + +def test_parse_output_to_paste_buffer(parser): + line = 'output to paste buffer >> ' + statement = parser.parse(line) + assert statement.command == 'output' + assert statement.args == 'to paste buffer' + assert statement.output == '>>' + +def test_has_redirect_inside_terminator(parser): + """The terminator designates the end of the commmand/arguments portion. If a redirector + occurs before a terminator, then it will be treated as part of the arguments and not as a redirector.""" + line = 'has > inside;' + statement = parser.parse(line) + assert statement.command == 'has' + assert statement.args == '> inside' + assert statement.terminator == ';' + +def test_parse_unfinished_multiliine_command(parser): + line = 'multiline has > inside an unfinished command' + statement = parser.parse(line) + assert statement.multilineCommand == 'multiline' + assert not statement.args + assert not statement.terminator + + +def test_parse_multiline_command_ignores_redirectors_within_it(parser): + line = 'multiline has > inside;' + statement = parser.parse(line) + assert statement.multilineCommand == 'multiline' + assert statement.args == 'has > inside' + assert statement.terminator == ';' + +# def test_parse_multiline_with_incomplete_comment(parser): +# """A terminator within a comment will be ignored and won't terminate a multiline command. +# Un-closed comments effectively comment out everything after the start.""" +# line = 'multiline command /* with comment in progress;' +# statement = parser.parse(line) +# assert statement.multilineCommand == 'multiline' +# assert statement.args == 'command' +# assert not statement.terminator + +def test_parse_multiline_with_complete_comment(parser): + line = 'multiline command /* with comment complete */ is done;' + statement = parser.parse(line) + assert statement.multilineCommand == 'multiline' + assert statement.args == 'command is done' + assert statement.terminator == ';' + +def test_parse_multiline_termninated_by_empty_line(parser): + line = 'multiline command ends\n\n' + statement = parser.parse(line) + assert statement.multilineCommand == 'multiline' + assert statement.args == 'command ends' + assert statement.terminator == '\n' + +def test_parse_multiline_ignores_terminators_in_comments(parser): + line = 'multiline command "with term; ends" now\n\n' + statement = parser.parse(line) + assert statement.multilineCommand == 'multiline' + assert statement.args == 'command "with term; ends" now' + assert statement.terminator == '\n' + +def test_parse_command_with_unicode_args(parser): + line = 'drink café' + statement = parser.parse(line) + assert statement.command == 'drink' + assert statement.args == 'café' + +def test_parse_unicode_command(parser): + line = 'café au lait' + statement = parser.parse(line) + assert statement.command == 'café' + assert statement.args == 'au lait' + +def test_parse_redirect_to_unicode_filename(parser): + line = 'dir home > café' + statement = parser.parse(line) + assert statement.command == 'dir' + assert statement.args == 'home' + assert statement.output == '>' + assert statement.outputTo == 'café' + +def test_parse_input_redirect_from_unicode_filename(parser): + line = '< café' + statement = parser.parse(line) + assert statement.inputFrom == 'café' + +def test_empty_statement_raises_exception(): + app = cmd2.Cmd() + with pytest.raises(cmd2.cmd2.EmptyStatement): + app._complete_statement('') + + with pytest.raises(cmd2.cmd2.EmptyStatement): + app._complete_statement(' ') + +@pytest.mark.parametrize('line,command,args', [ + ('helpalias', 'help', ''), + ('helpalias mycommand', 'help', 'mycommand'), + ('42', 'theanswer', ''), + ('42 arg1 arg2', 'theanswer', 'arg1 arg2'), + ('!ls', 'shell', 'ls'), + ('!ls -al /tmp', 'shell', 'ls -al /tmp'), +]) +def test_alias_and_shortcut_expansion(parser, line, command, args): + statement = parser.parse(line) + assert statement.command == command + assert statement.args == args def test_empty_statement_raises_exception(): app = cmd2.Cmd() -- cgit v1.2.1 From 9170550b2a32a763dafc1d7b14b43d97c542a0db Mon Sep 17 00:00:00 2001 From: kotfu Date: Tue, 24 Apr 2018 22:40:29 -0600 Subject: Add test for alias expansion on incomplete multiline commands --- tests/test_parsing.py | 36 ++++++++++++++++++------------------ 1 file changed, 18 insertions(+), 18 deletions(-) (limited to 'tests/test_parsing.py') diff --git a/tests/test_parsing.py b/tests/test_parsing.py index 6fa7d629..1913938e 100644 --- a/tests/test_parsing.py +++ b/tests/test_parsing.py @@ -19,7 +19,7 @@ def parser(): redirection_chars=['|', '<', '>'], terminators = [';'], multilineCommands = ['multiline'], - aliases = {'helpalias': 'help', '42': 'theanswer'}, + aliases = {'helpalias': 'help', '42': 'theanswer', 'anothermultiline': 'multiline'}, shortcuts = [('?', 'help'), ('!', 'shell')] ) return parser @@ -193,9 +193,9 @@ def test_parse_unfinished_multiliine_command(parser): line = 'multiline has > inside an unfinished command' statement = parser.parse(line) assert statement.multilineCommand == 'multiline' - assert not statement.args + assert statement.command == 'multiline' + assert statement.args == 'has > inside an unfinished command' assert not statement.terminator - def test_parse_multiline_command_ignores_redirectors_within_it(parser): line = 'multiline has > inside;' @@ -204,14 +204,14 @@ def test_parse_multiline_command_ignores_redirectors_within_it(parser): assert statement.args == 'has > inside' assert statement.terminator == ';' -# def test_parse_multiline_with_incomplete_comment(parser): -# """A terminator within a comment will be ignored and won't terminate a multiline command. -# Un-closed comments effectively comment out everything after the start.""" -# line = 'multiline command /* with comment in progress;' -# statement = parser.parse(line) -# assert statement.multilineCommand == 'multiline' -# assert statement.args == 'command' -# assert not statement.terminator +def test_parse_multiline_with_incomplete_comment(parser): + """A terminator within a comment will be ignored and won't terminate a multiline command. + Un-closed comments effectively comment out everything after the start.""" + line = 'multiline command /* with comment in progress;' + statement = parser.parse(line) + assert statement.multilineCommand == 'multiline' + assert statement.args == 'command' + assert not statement.terminator def test_parse_multiline_with_complete_comment(parser): line = 'multiline command /* with comment complete */ is done;' @@ -280,10 +280,10 @@ def test_alias_and_shortcut_expansion(parser, line, command, args): assert statement.command == command assert statement.args == args -def test_empty_statement_raises_exception(): - app = cmd2.Cmd() - with pytest.raises(cmd2.cmd2.EmptyStatement): - app._complete_statement('') - - with pytest.raises(cmd2.cmd2.EmptyStatement): - app._complete_statement(' ') +def test_alias_on_multiline_command(parser): + line = 'anothermultiline has > inside an unfinished command' + statement = parser.parse(line) + assert statement.multilineCommand == 'multiline' + assert statement.command == 'multiline' + assert statement.args == 'has > inside an unfinished command' + assert not statement.terminator -- cgit v1.2.1 From 739d3f42715e59b61432cd7fbedacae4a4f80a16 Mon Sep 17 00:00:00 2001 From: kotfu Date: Thu, 26 Apr 2018 20:21:52 -0600 Subject: First stage of refactoring cmd2.parseline() for tab completion --- tests/test_parsing.py | 38 +++++++++++++++++++++++++++++++++++++- 1 file changed, 37 insertions(+), 1 deletion(-) (limited to 'tests/test_parsing.py') diff --git a/tests/test_parsing.py b/tests/test_parsing.py index 1913938e..d7a872b3 100644 --- a/tests/test_parsing.py +++ b/tests/test_parsing.py @@ -19,7 +19,7 @@ def parser(): redirection_chars=['|', '<', '>'], terminators = [';'], multilineCommands = ['multiline'], - aliases = {'helpalias': 'help', '42': 'theanswer', 'anothermultiline': 'multiline'}, + aliases = {'helpalias': 'help', '42': 'theanswer', 'anothermultiline': 'multiline', 'fake': 'pyscript'}, shortcuts = [('?', 'help'), ('!', 'shell')] ) return parser @@ -27,6 +27,8 @@ def parser(): def test_parse_empty_string(parser): statement = parser.parse('') assert not statement.command + assert not statement.args + assert statement.raw == '' @pytest.mark.parametrize('tokens,command,args', [ ( [], None, ''), @@ -287,3 +289,37 @@ def test_alias_on_multiline_command(parser): assert statement.command == 'multiline' assert statement.args == 'has > inside an unfinished command' assert not statement.terminator + +def test_parse_command_only_command_and_args(parser): + line = 'help history' + statement = parser.parse_command_only(line) + assert statement.command == 'help' + assert statement.args == 'history' + assert statement.command_and_args == line + +def test_parse_command_only_emptyline(parser): + line = '' + statement = parser.parse_command_only(line) + assert statement.command is None + assert statement.args is '' + assert statement.command_and_args is line + +def test_parse_command_only_strips_line(parser): + line = ' help history ' + statement = parser.parse_command_only(line) + assert statement.command == 'help' + assert statement.args == 'history' + assert statement.command_and_args == line.strip() + +def test_parse_command_only_expands_alias(parser): + line = 'fake foobar.py' + statement = parser.parse_command_only(line) + assert statement.command == 'pyscript' + assert statement.args == 'foobar.py' + +def test_parse_command_only_expands_shortcuts(parser): + line = '!cat foobar.txt' + statement = parser.parse_command_only(line) + assert statement.command == 'shell' + assert statement.args == 'cat foobar.txt' + assert statement.command_and_args == line.replace('!', 'shell ') -- cgit v1.2.1 From fd3512a80600a3262030d55ed03f4930757395f6 Mon Sep 17 00:00:00 2001 From: kotfu Date: Sun, 29 Apr 2018 09:52:10 -0600 Subject: Move quotes and redirection_chars from arguments to constants Since the tab completion code relies on these same constants, if we allow them to be passed to the statement parser, we could have a situation where the statement parser and tab completion return different results. --- tests/test_parsing.py | 2 -- 1 file changed, 2 deletions(-) (limited to 'tests/test_parsing.py') diff --git a/tests/test_parsing.py b/tests/test_parsing.py index d7a872b3..b920b440 100644 --- a/tests/test_parsing.py +++ b/tests/test_parsing.py @@ -14,9 +14,7 @@ import pytest @pytest.fixture def parser(): parser = StatementParser( - quotes=['"', "'"], allow_redirection=True, - redirection_chars=['|', '<', '>'], terminators = [';'], multilineCommands = ['multiline'], aliases = {'helpalias': 'help', '42': 'theanswer', 'anothermultiline': 'multiline', 'fake': 'pyscript'}, -- cgit v1.2.1 From 85c63d41286e62460b3b80c465349a5a0476266c Mon Sep 17 00:00:00 2001 From: kotfu Date: Sun, 29 Apr 2018 09:59:13 -0600 Subject: multilineCommand -> multiline_command --- tests/test_parsing.py | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) (limited to 'tests/test_parsing.py') diff --git a/tests/test_parsing.py b/tests/test_parsing.py index b920b440..3fc7c171 100644 --- a/tests/test_parsing.py +++ b/tests/test_parsing.py @@ -16,7 +16,7 @@ def parser(): parser = StatementParser( allow_redirection=True, terminators = [';'], - multilineCommands = ['multiline'], + multiline_commands = ['multiline'], aliases = {'helpalias': 'help', '42': 'theanswer', 'anothermultiline': 'multiline', 'fake': 'pyscript'}, shortcuts = [('?', 'help'), ('!', 'shell')] ) @@ -192,7 +192,7 @@ def test_has_redirect_inside_terminator(parser): def test_parse_unfinished_multiliine_command(parser): line = 'multiline has > inside an unfinished command' statement = parser.parse(line) - assert statement.multilineCommand == 'multiline' + assert statement.multiline_command == 'multiline' assert statement.command == 'multiline' assert statement.args == 'has > inside an unfinished command' assert not statement.terminator @@ -200,7 +200,7 @@ def test_parse_unfinished_multiliine_command(parser): def test_parse_multiline_command_ignores_redirectors_within_it(parser): line = 'multiline has > inside;' statement = parser.parse(line) - assert statement.multilineCommand == 'multiline' + assert statement.multiline_command == 'multiline' assert statement.args == 'has > inside' assert statement.terminator == ';' @@ -209,28 +209,28 @@ def test_parse_multiline_with_incomplete_comment(parser): Un-closed comments effectively comment out everything after the start.""" line = 'multiline command /* with comment in progress;' statement = parser.parse(line) - assert statement.multilineCommand == 'multiline' + assert statement.multiline_command == 'multiline' assert statement.args == 'command' assert not statement.terminator def test_parse_multiline_with_complete_comment(parser): line = 'multiline command /* with comment complete */ is done;' statement = parser.parse(line) - assert statement.multilineCommand == 'multiline' + assert statement.multiline_command == 'multiline' assert statement.args == 'command is done' assert statement.terminator == ';' def test_parse_multiline_termninated_by_empty_line(parser): line = 'multiline command ends\n\n' statement = parser.parse(line) - assert statement.multilineCommand == 'multiline' + assert statement.multiline_command == 'multiline' assert statement.args == 'command ends' assert statement.terminator == '\n' def test_parse_multiline_ignores_terminators_in_comments(parser): line = 'multiline command "with term; ends" now\n\n' statement = parser.parse(line) - assert statement.multilineCommand == 'multiline' + assert statement.multiline_command == 'multiline' assert statement.args == 'command "with term; ends" now' assert statement.terminator == '\n' @@ -283,7 +283,7 @@ def test_alias_and_shortcut_expansion(parser, line, command, args): def test_alias_on_multiline_command(parser): line = 'anothermultiline has > inside an unfinished command' statement = parser.parse(line) - assert statement.multilineCommand == 'multiline' + assert statement.multiline_command == 'multiline' assert statement.command == 'multiline' assert statement.args == 'has > inside an unfinished command' assert not statement.terminator -- cgit v1.2.1 From fbc6d0b39fa1e84ea3de3b38b700c45189146429 Mon Sep 17 00:00:00 2001 From: kotfu Date: Sun, 29 Apr 2018 12:43:11 -0600 Subject: pipeTo -> pipe_to --- tests/test_parsing.py | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) (limited to 'tests/test_parsing.py') diff --git a/tests/test_parsing.py b/tests/test_parsing.py index 3fc7c171..01674136 100644 --- a/tests/test_parsing.py +++ b/tests/test_parsing.py @@ -65,7 +65,7 @@ def test_command_with_args(parser): statement = parser.parse(line) assert statement.command == 'command' assert statement.args == 'with args' - assert not statement.pipeTo + assert not statement.pipe_to def test_parse_command_with_args_terminator_and_suffix(parser): line = 'command with args and terminator; and suffix' @@ -79,38 +79,38 @@ def test_hashcomment(parser): statement = parser.parse('hi # this is all a comment') assert statement.command == 'hi' assert not statement.args - assert not statement.pipeTo + assert not statement.pipe_to def test_c_comment(parser): statement = parser.parse('hi /* this is | all a comment */') assert statement.command == 'hi' assert not statement.args - assert not statement.pipeTo + assert not statement.pipe_to def test_c_comment_empty(parser): statement = parser.parse('/* this is | all a comment */') assert not statement.command assert not statement.args - assert not statement.pipeTo + assert not statement.pipe_to def test_parse_what_if_quoted_strings_seem_to_start_comments(parser): statement = parser.parse('what if "quoted strings /* seem to " start comments?') assert statement.command == 'what' assert statement.args == 'if "quoted strings /* seem to " start comments?' - assert not statement.pipeTo + assert not statement.pipe_to def test_simple_piped(parser): statement = parser.parse('simple | piped') assert statement.command == 'simple' assert not statement.args - assert statement.pipeTo == 'piped' + assert statement.pipe_to == 'piped' def test_double_pipe_is_not_a_pipe(parser): line = 'double-pipe || is not a pipe' statement = parser.parse(line) assert statement.command == 'double-pipe' assert statement.args == '|| is not a pipe' - assert not statement.pipeTo + assert not statement.pipe_to def test_complex_pipe(parser): line = 'command with args, terminator;sufx | piped' @@ -119,7 +119,7 @@ def test_complex_pipe(parser): assert statement.args == "with args, terminator" assert statement.terminator == ';' assert statement.suffix == 'sufx' - assert statement.pipeTo == 'piped' + assert statement.pipe_to == 'piped' def test_output_redirect(parser): line = 'output into > afile.txt' @@ -169,7 +169,7 @@ def test_pipe_and_redirect(parser): assert statement.args == 'into' assert statement.terminator == ';' assert statement.suffix == 'sufx' - assert statement.pipeTo == 'pipethrume plz' + assert statement.pipe_to == 'pipethrume plz' assert statement.output == '>' assert statement.outputTo == 'afile.txt' -- cgit v1.2.1 From 83fd707dcf9916c9f483e4417a2c3b2b083c8da2 Mon Sep 17 00:00:00 2001 From: kotfu Date: Sun, 29 Apr 2018 12:44:38 -0600 Subject: outputTo -> output_to --- tests/test_parsing.py | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) (limited to 'tests/test_parsing.py') diff --git a/tests/test_parsing.py b/tests/test_parsing.py index 01674136..cfc5aa76 100644 --- a/tests/test_parsing.py +++ b/tests/test_parsing.py @@ -127,7 +127,7 @@ def test_output_redirect(parser): assert statement.command == 'output' assert statement.args == 'into' assert statement.output == '>' - assert statement.outputTo == 'afile.txt' + assert statement.output_to == 'afile.txt' def test_output_redirect_with_dash_in_path(parser): line = 'output into > python-cmd2/afile.txt' @@ -135,7 +135,7 @@ def test_output_redirect_with_dash_in_path(parser): assert statement.command == 'output' assert statement.args == 'into' assert statement.output == '>' - assert statement.outputTo == 'python-cmd2/afile.txt' + assert statement.output_to == 'python-cmd2/afile.txt' def test_output_redirect_append(parser): line = 'output appended to >> /tmp/afile.txt' @@ -143,7 +143,7 @@ def test_output_redirect_append(parser): assert statement.command == 'output' assert statement.args == 'appended to' assert statement.output == '>>' - assert statement.outputTo == '/tmp/afile.txt' + assert statement.output_to == '/tmp/afile.txt' def test_parse_input_redirect(parser): line = '< afile.txt' @@ -171,7 +171,7 @@ def test_pipe_and_redirect(parser): assert statement.suffix == 'sufx' assert statement.pipe_to == 'pipethrume plz' assert statement.output == '>' - assert statement.outputTo == 'afile.txt' + assert statement.output_to == 'afile.txt' def test_parse_output_to_paste_buffer(parser): line = 'output to paste buffer >> ' @@ -252,7 +252,7 @@ def test_parse_redirect_to_unicode_filename(parser): assert statement.command == 'dir' assert statement.args == 'home' assert statement.output == '>' - assert statement.outputTo == 'café' + assert statement.output_to == 'café' def test_parse_input_redirect_from_unicode_filename(parser): line = '< café' -- cgit v1.2.1 From 39e74f6b60b8701b14da29693f909ab407242f73 Mon Sep 17 00:00:00 2001 From: kotfu Date: Sun, 29 Apr 2018 15:33:18 -0600 Subject: pylint cleanups --- tests/test_parsing.py | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) (limited to 'tests/test_parsing.py') diff --git a/tests/test_parsing.py b/tests/test_parsing.py index cfc5aa76..eb26c47d 100644 --- a/tests/test_parsing.py +++ b/tests/test_parsing.py @@ -5,20 +5,20 @@ Test the parsing logic in parsing.py Copyright 2017 Todd Leonhardt Released under MIT license, see LICENSE file """ +import pytest + import cmd2 from cmd2.parsing import StatementParser -import pytest - @pytest.fixture def parser(): parser = StatementParser( allow_redirection=True, - terminators = [';'], - multiline_commands = ['multiline'], - aliases = {'helpalias': 'help', '42': 'theanswer', 'anothermultiline': 'multiline', 'fake': 'pyscript'}, - shortcuts = [('?', 'help'), ('!', 'shell')] + terminators=[';'], + multiline_commands=['multiline'], + aliases={'helpalias': 'help', '42': 'theanswer', 'anothermultiline': 'multiline', 'fake': 'pyscript'}, + shortcuts=[('?', 'help'), ('!', 'shell')] ) return parser @@ -29,9 +29,9 @@ def test_parse_empty_string(parser): assert statement.raw == '' @pytest.mark.parametrize('tokens,command,args', [ - ( [], None, ''), - ( ['command'], 'command', '' ), - ( ['command', 'arg1', 'arg2'], 'command', 'arg1 arg2') + ([], None, ''), + (['command'], 'command', ''), + (['command', 'arg1', 'arg2'], 'command', 'arg1 arg2') ]) def test_command_and_args(parser, tokens, command, args): (parsed_command, parsed_args) = parser._command_and_args(tokens) -- cgit v1.2.1 From 1297be25d68b0c8e511b819c906f0d5e0a942606 Mon Sep 17 00:00:00 2001 From: kotfu Date: Sun, 29 Apr 2018 16:09:54 -0600 Subject: Really get rid of the inputFrom stuff, including documentation --- tests/test_parsing.py | 22 ---------------------- 1 file changed, 22 deletions(-) (limited to 'tests/test_parsing.py') diff --git a/tests/test_parsing.py b/tests/test_parsing.py index eb26c47d..4ca6838e 100644 --- a/tests/test_parsing.py +++ b/tests/test_parsing.py @@ -145,23 +145,6 @@ def test_output_redirect_append(parser): assert statement.output == '>>' assert statement.output_to == '/tmp/afile.txt' -def test_parse_input_redirect(parser): - line = '< afile.txt' - statement = parser.parse(line) - assert statement.inputFrom == 'afile.txt' - -def test_parse_input_redirect_after_command(parser): - line = 'help < afile.txt' - statement = parser.parse(line) - assert statement.command == 'help' - assert statement.args == '' - assert statement.inputFrom == 'afile.txt' - -def test_parse_input_redirect_with_dash_in_path(parser): - line = '< python-cmd2/afile.txt' - statement = parser.parse(line) - assert statement.inputFrom == 'python-cmd2/afile.txt' - def test_pipe_and_redirect(parser): line = 'output into;sufx | pipethrume plz > afile.txt' statement = parser.parse(line) @@ -254,11 +237,6 @@ def test_parse_redirect_to_unicode_filename(parser): assert statement.output == '>' assert statement.output_to == 'café' -def test_parse_input_redirect_from_unicode_filename(parser): - line = '< café' - statement = parser.parse(line) - assert statement.inputFrom == 'café' - def test_empty_statement_raises_exception(): app = cmd2.Cmd() with pytest.raises(cmd2.cmd2.EmptyStatement): -- cgit v1.2.1 From 3a7e713ad191bf9763d04c907d4fb27a0d52208b Mon Sep 17 00:00:00 2001 From: kotfu Date: Sun, 29 Apr 2018 16:34:52 -0600 Subject: Add new unit test --- tests/test_parsing.py | 7 +++++++ 1 file changed, 7 insertions(+) (limited to 'tests/test_parsing.py') diff --git a/tests/test_parsing.py b/tests/test_parsing.py index 4ca6838e..8c026631 100644 --- a/tests/test_parsing.py +++ b/tests/test_parsing.py @@ -299,3 +299,10 @@ def test_parse_command_only_expands_shortcuts(parser): assert statement.command == 'shell' assert statement.args == 'cat foobar.txt' assert statement.command_and_args == line.replace('!', 'shell ') + +def test_parse_command_only_quoted_args(parser): + line = 'shell "/tmp/directory with spaces/doit.sh"' + statement = parser.parse_command_only(line) + assert statement.command == 'shell' + assert statement.args == '"/tmp/directory with spaces/doit.sh"' + assert statement.command_and_args == line -- cgit v1.2.1 From efce15990f2485666f38178ca444c786ac05901d Mon Sep 17 00:00:00 2001 From: kotfu Date: Sun, 29 Apr 2018 16:54:36 -0600 Subject: Add test_command_with_quoted_args() --- tests/test_parsing.py | 6 ++++++ 1 file changed, 6 insertions(+) (limited to 'tests/test_parsing.py') diff --git a/tests/test_parsing.py b/tests/test_parsing.py index 8c026631..53c941d2 100644 --- a/tests/test_parsing.py +++ b/tests/test_parsing.py @@ -67,6 +67,12 @@ def test_command_with_args(parser): assert statement.args == 'with args' assert not statement.pipe_to +def test_command_with_quoted_args(parser): + line = 'command with "quoted args" and "some not"' + statement = parser.parse(line) + assert statement.command == 'command' + assert statement.args == 'with "quoted args" and "some not"' + def test_parse_command_with_args_terminator_and_suffix(parser): line = 'command with args and terminator; and suffix' statement = parser.parse(line) -- cgit v1.2.1 From 119a6e49f1c37ea43059c74f7a2441a275731554 Mon Sep 17 00:00:00 2001 From: kotfu Date: Mon, 30 Apr 2018 00:01:47 -0600 Subject: Fix nested alias and shortcut expansion --- tests/test_parsing.py | 24 ++++++++++++++++++++---- 1 file changed, 20 insertions(+), 4 deletions(-) (limited to 'tests/test_parsing.py') diff --git a/tests/test_parsing.py b/tests/test_parsing.py index 53c941d2..1e745bda 100644 --- a/tests/test_parsing.py +++ b/tests/test_parsing.py @@ -17,7 +17,11 @@ def parser(): allow_redirection=True, terminators=[';'], multiline_commands=['multiline'], - aliases={'helpalias': 'help', '42': 'theanswer', 'anothermultiline': 'multiline', 'fake': 'pyscript'}, + aliases={'helpalias': 'help', + '42': 'theanswer', + 'l': '!ls -al', + 'anothermultiline': 'multiline', + 'fake': 'pyscript'}, shortcuts=[('?', 'help'), ('!', 'shell')] ) return parser @@ -28,6 +32,17 @@ def test_parse_empty_string(parser): assert not statement.args assert statement.raw == '' +@pytest.mark.parametrize('line,tokens', [ + ('command', ['command']), + ('command /* with some comment */ arg', ['command', 'arg']), + ('command arg1 arg2 # comment at the end', ['command', 'arg1', 'arg2']), + ('42 arg1 arg2', ['theanswer', 'arg1', 'arg2']), + ('l', ['shell', 'ls', '-al']) +]) +def test_tokenize(parser, line, tokens): + tokens_to_test = parser.tokenize(line) + assert tokens_to_test == tokens + @pytest.mark.parametrize('tokens,command,args', [ ([], None, ''), (['command'], 'command', ''), @@ -258,6 +273,7 @@ def test_empty_statement_raises_exception(): ('42 arg1 arg2', 'theanswer', 'arg1 arg2'), ('!ls', 'shell', 'ls'), ('!ls -al /tmp', 'shell', 'ls -al /tmp'), + ('l', 'shell', 'ls -al') ]) def test_alias_and_shortcut_expansion(parser, line, command, args): statement = parser.parse(line) @@ -307,8 +323,8 @@ def test_parse_command_only_expands_shortcuts(parser): assert statement.command_and_args == line.replace('!', 'shell ') def test_parse_command_only_quoted_args(parser): - line = 'shell "/tmp/directory with spaces/doit.sh"' + line = 'l "/tmp/directory with spaces/doit.sh"' statement = parser.parse_command_only(line) assert statement.command == 'shell' - assert statement.args == '"/tmp/directory with spaces/doit.sh"' - assert statement.command_and_args == line + assert statement.args == 'ls -al "/tmp/directory with spaces/doit.sh"' + assert statement.command_and_args == line.replace('l', 'shell ls -al') -- cgit v1.2.1 From ad634b2e7f68392727246f796647b92d67172011 Mon Sep 17 00:00:00 2001 From: kotfu Date: Wed, 2 May 2018 19:09:30 -0700 Subject: Add argv to Statement object --- tests/test_parsing.py | 59 +++++++++++++++++++++++++++++++++++++++++++-------- 1 file changed, 50 insertions(+), 9 deletions(-) (limited to 'tests/test_parsing.py') diff --git a/tests/test_parsing.py b/tests/test_parsing.py index 1e745bda..3f8fc07c 100644 --- a/tests/test_parsing.py +++ b/tests/test_parsing.py @@ -10,6 +10,7 @@ import pytest import cmd2 from cmd2.parsing import StatementParser +from cmd2 import utils @pytest.fixture def parser(): @@ -44,8 +45,8 @@ def test_tokenize(parser, line, tokens): assert tokens_to_test == tokens @pytest.mark.parametrize('tokens,command,args', [ - ([], None, ''), - (['command'], 'command', ''), + ([], None, None), + (['command'], 'command', None), (['command', 'arg1', 'arg2'], 'command', 'arg1 arg2') ]) def test_command_and_args(parser, tokens, command, args): @@ -61,12 +62,15 @@ def test_command_and_args(parser, tokens, command, args): def test_single_word(parser, line): statement = parser.parse(line) assert statement.command == line + assert not statement.args + assert statement.argv == [utils.strip_quotes(line)] def test_word_plus_terminator(parser): line = 'termbare;' statement = parser.parse(line) assert statement.command == 'termbare' assert statement.terminator == ';' + assert statement.argv == ['termbare'] def test_suffix_after_terminator(parser): line = 'termbare; suffx' @@ -74,19 +78,21 @@ def test_suffix_after_terminator(parser): assert statement.command == 'termbare' assert statement.terminator == ';' assert statement.suffix == 'suffx' + assert statement.argv == ['termbare'] def test_command_with_args(parser): line = 'command with args' statement = parser.parse(line) assert statement.command == 'command' assert statement.args == 'with args' - assert not statement.pipe_to + assert statement.argv == ['command', 'with', 'args'] def test_command_with_quoted_args(parser): line = 'command with "quoted args" and "some not"' statement = parser.parse(line) assert statement.command == 'command' assert statement.args == 'with "quoted args" and "some not"' + assert statement.argv == ['command', 'with', 'quoted args', 'and', 'some not'] def test_parse_command_with_args_terminator_and_suffix(parser): line = 'command with args and terminator; and suffix' @@ -95,35 +101,40 @@ def test_parse_command_with_args_terminator_and_suffix(parser): assert statement.args == "with args and terminator" assert statement.terminator == ';' assert statement.suffix == 'and suffix' + assert statement.argv == ['command', 'with', 'args', 'and', 'terminator'] def test_hashcomment(parser): statement = parser.parse('hi # this is all a comment') assert statement.command == 'hi' assert not statement.args - assert not statement.pipe_to + assert statement.argv == ['hi'] def test_c_comment(parser): statement = parser.parse('hi /* this is | all a comment */') assert statement.command == 'hi' assert not statement.args assert not statement.pipe_to + assert statement.argv == ['hi'] def test_c_comment_empty(parser): statement = parser.parse('/* this is | all a comment */') assert not statement.command assert not statement.args assert not statement.pipe_to + assert not statement.argv def test_parse_what_if_quoted_strings_seem_to_start_comments(parser): statement = parser.parse('what if "quoted strings /* seem to " start comments?') assert statement.command == 'what' assert statement.args == 'if "quoted strings /* seem to " start comments?' assert not statement.pipe_to + assert statement.argv == ['what', 'if', 'quoted strings /* seem to ', 'start', 'comments?'] def test_simple_piped(parser): statement = parser.parse('simple | piped') assert statement.command == 'simple' assert not statement.args + assert statement.argv == ['simple'] assert statement.pipe_to == 'piped' def test_double_pipe_is_not_a_pipe(parser): @@ -131,6 +142,7 @@ def test_double_pipe_is_not_a_pipe(parser): statement = parser.parse(line) assert statement.command == 'double-pipe' assert statement.args == '|| is not a pipe' + assert statement.argv == ['double-pipe', '||', 'is', 'not', 'a', 'pipe'] assert not statement.pipe_to def test_complex_pipe(parser): @@ -138,6 +150,7 @@ def test_complex_pipe(parser): statement = parser.parse(line) assert statement.command == 'command' assert statement.args == "with args, terminator" + assert statement.argv == ['command', 'with', 'args,', 'terminator'] assert statement.terminator == ';' assert statement.suffix == 'sufx' assert statement.pipe_to == 'piped' @@ -147,6 +160,7 @@ def test_output_redirect(parser): statement = parser.parse(line) assert statement.command == 'output' assert statement.args == 'into' + assert statement.argv == ['output', 'into'] assert statement.output == '>' assert statement.output_to == 'afile.txt' @@ -155,6 +169,7 @@ def test_output_redirect_with_dash_in_path(parser): statement = parser.parse(line) assert statement.command == 'output' assert statement.args == 'into' + assert statement.argv == ['output', 'into'] assert statement.output == '>' assert statement.output_to == 'python-cmd2/afile.txt' @@ -163,6 +178,7 @@ def test_output_redirect_append(parser): statement = parser.parse(line) assert statement.command == 'output' assert statement.args == 'appended to' + assert statement.argv == ['output', 'appended', 'to'] assert statement.output == '>>' assert statement.output_to == '/tmp/afile.txt' @@ -171,6 +187,7 @@ def test_pipe_and_redirect(parser): statement = parser.parse(line) assert statement.command == 'output' assert statement.args == 'into' + assert statement.argv == ['output', 'into'] assert statement.terminator == ';' assert statement.suffix == 'sufx' assert statement.pipe_to == 'pipethrume plz' @@ -182,6 +199,7 @@ def test_parse_output_to_paste_buffer(parser): statement = parser.parse(line) assert statement.command == 'output' assert statement.args == 'to paste buffer' + assert statement.argv == ['output', 'to', 'paste', 'buffer'] assert statement.output == '>>' def test_has_redirect_inside_terminator(parser): @@ -191,6 +209,7 @@ def test_has_redirect_inside_terminator(parser): statement = parser.parse(line) assert statement.command == 'has' assert statement.args == '> inside' + assert statement.argv == ['has', '>', 'inside'] assert statement.terminator == ';' def test_parse_unfinished_multiliine_command(parser): @@ -199,6 +218,7 @@ def test_parse_unfinished_multiliine_command(parser): assert statement.multiline_command == 'multiline' assert statement.command == 'multiline' assert statement.args == 'has > inside an unfinished command' + assert statement.argv == ['multiline', 'has', '>', 'inside', 'an', 'unfinished', 'command'] assert not statement.terminator def test_parse_multiline_command_ignores_redirectors_within_it(parser): @@ -206,6 +226,7 @@ def test_parse_multiline_command_ignores_redirectors_within_it(parser): statement = parser.parse(line) assert statement.multiline_command == 'multiline' assert statement.args == 'has > inside' + assert statement.argv == ['multiline', 'has', '>', 'inside'] assert statement.terminator == ';' def test_parse_multiline_with_incomplete_comment(parser): @@ -214,28 +235,36 @@ def test_parse_multiline_with_incomplete_comment(parser): line = 'multiline command /* with comment in progress;' statement = parser.parse(line) assert statement.multiline_command == 'multiline' + assert statement.command == 'multiline' assert statement.args == 'command' + assert statement.argv == ['multiline', 'command'] assert not statement.terminator def test_parse_multiline_with_complete_comment(parser): line = 'multiline command /* with comment complete */ is done;' statement = parser.parse(line) assert statement.multiline_command == 'multiline' + assert statement.command == 'multiline' assert statement.args == 'command is done' + assert statement.argv == ['multiline', 'command', 'is', 'done'] assert statement.terminator == ';' def test_parse_multiline_termninated_by_empty_line(parser): line = 'multiline command ends\n\n' statement = parser.parse(line) assert statement.multiline_command == 'multiline' + assert statement.command == 'multiline' assert statement.args == 'command ends' + assert statement.argv == ['multiline', 'command', 'ends'] assert statement.terminator == '\n' def test_parse_multiline_ignores_terminators_in_comments(parser): line = 'multiline command "with term; ends" now\n\n' statement = parser.parse(line) assert statement.multiline_command == 'multiline' + assert statement.command == 'multiline' assert statement.args == 'command "with term; ends" now' + assert statement.argv == ['multiline', 'command', 'with term; ends', 'now'] assert statement.terminator == '\n' def test_parse_command_with_unicode_args(parser): @@ -243,18 +272,21 @@ def test_parse_command_with_unicode_args(parser): statement = parser.parse(line) assert statement.command == 'drink' assert statement.args == 'café' + assert statement.argv == ['drink', 'café'] def test_parse_unicode_command(parser): line = 'café au lait' statement = parser.parse(line) assert statement.command == 'café' assert statement.args == 'au lait' + assert statement.argv == ['café', 'au', 'lait'] def test_parse_redirect_to_unicode_filename(parser): line = 'dir home > café' statement = parser.parse(line) assert statement.command == 'dir' assert statement.args == 'home' + assert statement.argv == ['dir', 'home'] assert statement.output == '>' assert statement.output_to == 'café' @@ -267,9 +299,9 @@ def test_empty_statement_raises_exception(): app._complete_statement(' ') @pytest.mark.parametrize('line,command,args', [ - ('helpalias', 'help', ''), + ('helpalias', 'help', None), ('helpalias mycommand', 'help', 'mycommand'), - ('42', 'theanswer', ''), + ('42', 'theanswer', None), ('42 arg1 arg2', 'theanswer', 'arg1 arg2'), ('!ls', 'shell', 'ls'), ('!ls -al /tmp', 'shell', 'ls -al /tmp'), @@ -293,20 +325,27 @@ def test_parse_command_only_command_and_args(parser): statement = parser.parse_command_only(line) assert statement.command == 'help' assert statement.args == 'history' + assert statement.argv == ['help', 'history'] assert statement.command_and_args == line def test_parse_command_only_emptyline(parser): line = '' statement = parser.parse_command_only(line) + # statement is a subclass of str(), the value of the str + # should be '', to retain backwards compatibility with + # the cmd in the standard library + assert statement == '' assert statement.command is None - assert statement.args is '' - assert statement.command_and_args is line + assert statement.args is None + assert not statement.argv + assert statement.command_and_args == None def test_parse_command_only_strips_line(parser): line = ' help history ' statement = parser.parse_command_only(line) assert statement.command == 'help' assert statement.args == 'history' + assert statement.argv == ['help', 'history'] assert statement.command_and_args == line.strip() def test_parse_command_only_expands_alias(parser): @@ -314,13 +353,15 @@ def test_parse_command_only_expands_alias(parser): statement = parser.parse_command_only(line) assert statement.command == 'pyscript' assert statement.args == 'foobar.py' + assert statement.argv == ['pyscript', 'foobar.py'] def test_parse_command_only_expands_shortcuts(parser): line = '!cat foobar.txt' statement = parser.parse_command_only(line) assert statement.command == 'shell' assert statement.args == 'cat foobar.txt' - assert statement.command_and_args == line.replace('!', 'shell ') + assert statement.argv == ['shell', 'cat', 'foobar.txt'] + assert statement.command_and_args == 'shell cat foobar.txt' def test_parse_command_only_quoted_args(parser): line = 'l "/tmp/directory with spaces/doit.sh"' -- cgit v1.2.1