summaryrefslogtreecommitdiff
path: root/tests
diff options
context:
space:
mode:
authorkotfu <kotfu@kotfu.net>2018-05-23 20:59:26 -0600
committerkotfu <kotfu@kotfu.net>2018-05-23 20:59:26 -0600
commit1a70b90f375997751bc7df16b5e3f58c6194c71b (patch)
tree1abe43d088060e24bb889e3db19fc5a1a4a82562 /tests
parentb1516f4b09518bb6d33abfeb14e1459ed03f34d8 (diff)
parent5d64ebee348aeffb02fc385f903c9af431e3721b (diff)
downloadcmd2-git-1a70b90f375997751bc7df16b5e3f58c6194c71b.tar.gz
Merge branch 'master' into speedup_import
# Conflicts: # cmd2/cmd2.py # tests/test_completion.py # tests/test_submenu.py
Diffstat (limited to 'tests')
-rw-r--r--tests/pyscript/bar1.py1
-rw-r--r--tests/pyscript/custom_echo.py2
-rw-r--r--tests/pyscript/foo1.py1
-rw-r--r--tests/pyscript/foo2.py1
-rw-r--r--tests/pyscript/foo3.py1
-rw-r--r--tests/pyscript/foo4.py1
-rw-r--r--tests/pyscript/help.py3
-rw-r--r--tests/pyscript/help_media.py1
-rw-r--r--tests/pyscript/media_movies_add1.py1
-rw-r--r--tests/pyscript/media_movies_add2.py1
-rw-r--r--tests/pyscript/media_movies_list1.py3
-rw-r--r--tests/pyscript/media_movies_list2.py3
-rw-r--r--tests/pyscript/media_movies_list3.py3
-rw-r--r--tests/pyscript/media_movies_list4.py1
-rw-r--r--tests/pyscript/media_movies_list5.py1
-rw-r--r--tests/pyscript/media_movies_list6.py1
-rw-r--r--tests/pyscript/media_movies_list7.py1
-rw-r--r--tests/pyscript/pyscript_dir1.py3
-rw-r--r--tests/pyscript/pyscript_dir2.py3
-rw-r--r--tests/scripts/recursive.py1
-rw-r--r--tests/test_autocompletion.py4
-rw-r--r--tests/test_bashcompletion.py8
-rw-r--r--tests/test_cmd2.py20
-rw-r--r--tests/test_completion.py124
-rw-r--r--tests/test_parsing.py183
-rw-r--r--tests/test_pyscript.py36
-rw-r--r--tests/test_submenu.py182
27 files changed, 234 insertions, 356 deletions
diff --git a/tests/pyscript/bar1.py b/tests/pyscript/bar1.py
index c6276a87..521e2c29 100644
--- a/tests/pyscript/bar1.py
+++ b/tests/pyscript/bar1.py
@@ -1 +1,2 @@
+app.cmd_echo = True
app.bar('11', '22')
diff --git a/tests/pyscript/custom_echo.py b/tests/pyscript/custom_echo.py
new file mode 100644
index 00000000..14040e4c
--- /dev/null
+++ b/tests/pyscript/custom_echo.py
@@ -0,0 +1,2 @@
+custom.cmd_echo = True
+custom.echo('blah!')
diff --git a/tests/pyscript/foo1.py b/tests/pyscript/foo1.py
index 6e345d95..d9345354 100644
--- a/tests/pyscript/foo1.py
+++ b/tests/pyscript/foo1.py
@@ -1 +1,2 @@
+app.cmd_echo = True
app.foo('aaa', 'bbb', counter=3, trueval=True, constval=True)
diff --git a/tests/pyscript/foo2.py b/tests/pyscript/foo2.py
index d4df7616..d3600a60 100644
--- a/tests/pyscript/foo2.py
+++ b/tests/pyscript/foo2.py
@@ -1 +1,2 @@
+app.cmd_echo = True
app.foo('11', '22', '33', '44', counter=3, trueval=True, constval=True)
diff --git a/tests/pyscript/foo3.py b/tests/pyscript/foo3.py
index db69edaf..fc0e084a 100644
--- a/tests/pyscript/foo3.py
+++ b/tests/pyscript/foo3.py
@@ -1 +1,2 @@
+app.cmd_echo = True
app.foo('11', '22', '33', '44', '55', '66', counter=3, trueval=False, constval=False)
diff --git a/tests/pyscript/foo4.py b/tests/pyscript/foo4.py
index 88fd3ce8..e4b7d01c 100644
--- a/tests/pyscript/foo4.py
+++ b/tests/pyscript/foo4.py
@@ -1,3 +1,4 @@
+app.cmd_echo = True
result = app.foo('aaa', 'bbb', counter=3)
out_text = 'Fail'
if result:
diff --git a/tests/pyscript/help.py b/tests/pyscript/help.py
index 3f67793c..664c0488 100644
--- a/tests/pyscript/help.py
+++ b/tests/pyscript/help.py
@@ -1 +1,2 @@
-app.help() \ No newline at end of file
+app.cmd_echo = True
+app.help()
diff --git a/tests/pyscript/help_media.py b/tests/pyscript/help_media.py
index 78025bdd..d8d97c42 100644
--- a/tests/pyscript/help_media.py
+++ b/tests/pyscript/help_media.py
@@ -1 +1,2 @@
+app.cmd_echo = True
app.help('media')
diff --git a/tests/pyscript/media_movies_add1.py b/tests/pyscript/media_movies_add1.py
index a9139cb1..7249c0ef 100644
--- a/tests/pyscript/media_movies_add1.py
+++ b/tests/pyscript/media_movies_add1.py
@@ -1 +1,2 @@
+app.cmd_echo = True
app.media.movies.add('My Movie', 'PG-13', director=('George Lucas', 'J. J. Abrams'))
diff --git a/tests/pyscript/media_movies_add2.py b/tests/pyscript/media_movies_add2.py
index 5c4617ae..681095d7 100644
--- a/tests/pyscript/media_movies_add2.py
+++ b/tests/pyscript/media_movies_add2.py
@@ -1 +1,2 @@
+app.cmd_echo = True
app.media.movies.add('My Movie', 'PG-13', actor=('Mark Hamill'), director=('George Lucas', 'J. J. Abrams'))
diff --git a/tests/pyscript/media_movies_list1.py b/tests/pyscript/media_movies_list1.py
index 0124bbcb..edbc2021 100644
--- a/tests/pyscript/media_movies_list1.py
+++ b/tests/pyscript/media_movies_list1.py
@@ -1 +1,2 @@
-app.media.movies.list() \ No newline at end of file
+app.cmd_echo = True
+app.media.movies.list()
diff --git a/tests/pyscript/media_movies_list2.py b/tests/pyscript/media_movies_list2.py
index 83f6c8ff..5ad01b7b 100644
--- a/tests/pyscript/media_movies_list2.py
+++ b/tests/pyscript/media_movies_list2.py
@@ -1 +1,2 @@
-app.media().movies().list() \ No newline at end of file
+app.cmd_echo = True
+app.media().movies().list()
diff --git a/tests/pyscript/media_movies_list3.py b/tests/pyscript/media_movies_list3.py
index 4fcf1288..bdbdfceb 100644
--- a/tests/pyscript/media_movies_list3.py
+++ b/tests/pyscript/media_movies_list3.py
@@ -1 +1,2 @@
-app('media movies list') \ No newline at end of file
+app.cmd_echo = True
+app('media movies list')
diff --git a/tests/pyscript/media_movies_list4.py b/tests/pyscript/media_movies_list4.py
index 1165b0c5..5f7bdaa9 100644
--- a/tests/pyscript/media_movies_list4.py
+++ b/tests/pyscript/media_movies_list4.py
@@ -1 +1,2 @@
+app.cmd_echo = True
app.media.movies.list(actor='Mark Hamill')
diff --git a/tests/pyscript/media_movies_list5.py b/tests/pyscript/media_movies_list5.py
index 962b1516..fa4efa5b 100644
--- a/tests/pyscript/media_movies_list5.py
+++ b/tests/pyscript/media_movies_list5.py
@@ -1 +1,2 @@
+app.cmd_echo = True
app.media.movies.list(actor=('Mark Hamill', 'Carrie Fisher'))
diff --git a/tests/pyscript/media_movies_list6.py b/tests/pyscript/media_movies_list6.py
index 5f8d3654..ef1851cd 100644
--- a/tests/pyscript/media_movies_list6.py
+++ b/tests/pyscript/media_movies_list6.py
@@ -1 +1,2 @@
+app.cmd_echo = True
app.media.movies.list(rating='PG')
diff --git a/tests/pyscript/media_movies_list7.py b/tests/pyscript/media_movies_list7.py
index bb0e28bb..7c827b7f 100644
--- a/tests/pyscript/media_movies_list7.py
+++ b/tests/pyscript/media_movies_list7.py
@@ -1 +1,2 @@
+app.cmd_echo = True
app.media.movies.list(rating=('PG', 'PG-13'))
diff --git a/tests/pyscript/pyscript_dir1.py b/tests/pyscript/pyscript_dir1.py
new file mode 100644
index 00000000..14a70a31
--- /dev/null
+++ b/tests/pyscript/pyscript_dir1.py
@@ -0,0 +1,3 @@
+out = dir(app)
+out.sort()
+print(out)
diff --git a/tests/pyscript/pyscript_dir2.py b/tests/pyscript/pyscript_dir2.py
new file mode 100644
index 00000000..28c61c8e
--- /dev/null
+++ b/tests/pyscript/pyscript_dir2.py
@@ -0,0 +1,3 @@
+out = dir(app.media)
+out.sort()
+print(out)
diff --git a/tests/scripts/recursive.py b/tests/scripts/recursive.py
index 32c981b6..4c29d317 100644
--- a/tests/scripts/recursive.py
+++ b/tests/scripts/recursive.py
@@ -3,4 +3,5 @@
"""
Example demonstrating that running a Python script recursively inside another Python script isn't allowed
"""
+app.cmd_echo = True
app('pyscript ../script.py')
diff --git a/tests/test_autocompletion.py b/tests/test_autocompletion.py
index 1d0c9678..e0a71831 100644
--- a/tests/test_autocompletion.py
+++ b/tests/test_autocompletion.py
@@ -168,7 +168,7 @@ def test_autocomp_subcmd_nested(cmd2_app):
first_match = complete_tester(text, line, begidx, endidx, cmd2_app)
assert first_match is not None and \
- cmd2_app.completion_matches == ['add', 'delete', 'list']
+ cmd2_app.completion_matches == ['add', 'delete', 'list', 'load']
def test_autocomp_subcmd_flag_choices_append(cmd2_app):
@@ -246,7 +246,7 @@ def test_autcomp_pos_consumed(cmd2_app):
def test_autcomp_pos_after_flag(cmd2_app):
text = 'Joh'
- line = 'media movies add -d "George Lucas" -- "Han Solo" PG "Emilia Clarke" "{}'.format(text)
+ line = 'video movies add -d "George Lucas" -- "Han Solo" PG "Emilia Clarke" "{}'.format(text)
endidx = len(line)
begidx = endidx - len(text)
diff --git a/tests/test_bashcompletion.py b/tests/test_bashcompletion.py
index ceae2aa9..298bdf1e 100644
--- a/tests/test_bashcompletion.py
+++ b/tests/test_bashcompletion.py
@@ -139,15 +139,13 @@ def test_invalid_ifs(parser1, mock):
@pytest.mark.parametrize('comp_line, exp_out, exp_err', [
('media ', 'movies\013shows', ''),
('media mo', 'movies', ''),
+ ('media movies list -a "J', '"John Boyega"\013"Jake Lloyd"', ''),
+ ('media movies list ', '', ''),
('media movies add ', '\013\013 ', '''
Hint:
TITLE Movie Title'''),
- ('media movies list -a "J', '"John Boyega"\013"Jake Lloyd"', ''),
- ('media movies list ', '', '')
])
def test_commands(parser1, capfd, mock, comp_line, exp_out, exp_err):
- completer = CompletionFinder()
-
mock.patch.dict(os.environ, {'_ARGCOMPLETE': '1',
'_ARGCOMPLETE_IFS': '\013',
'COMP_TYPE': '63',
@@ -157,6 +155,8 @@ def test_commands(parser1, capfd, mock, comp_line, exp_out, exp_err):
mock.patch.object(os, 'fdopen', my_fdopen)
with pytest.raises(SystemExit):
+ completer = CompletionFinder()
+
choices = {'actor': query_actors, # function
}
autocompleter = AutoCompleter(parser1, arg_choices=choices)
diff --git a/tests/test_cmd2.py b/tests/test_cmd2.py
index 11c2cad8..c66b1264 100644
--- a/tests/test_cmd2.py
+++ b/tests/test_cmd2.py
@@ -1427,7 +1427,7 @@ def test_clipboard_failure(capsys):
# Make sure we got the error output
out, err = capsys.readouterr()
assert out == ''
- assert 'Cannot redirect to paste buffer; install ``xclip`` and re-run to enable' in err
+ assert "Cannot redirect to paste buffer; install 'pyperclip' and re-run to enable" in err
class CmdResultApp(cmd2.Cmd):
@@ -1685,12 +1685,6 @@ def test_alias_lookup_invalid_alias(base_app, capsys):
out, err = capsys.readouterr()
assert "not found" in err
-def test_alias_with_invalid_name(base_app, capsys):
- run_cmd(base_app, 'alias @ help')
- out, err = capsys.readouterr()
- assert "can only contain the following characters" in err
-
-
def test_unalias(base_app):
# Create an alias
run_cmd(base_app, 'alias fake pyscript')
@@ -1708,6 +1702,18 @@ def test_unalias_non_existing(base_app, capsys):
out, err = capsys.readouterr()
assert "does not exist" in err
+@pytest.mark.parametrize('alias_name', [
+ '">"',
+ '"no>pe"',
+ '"no spaces"',
+ '"nopipe|"',
+ '"noterm;"',
+ 'noembedded"quotes',
+])
+def test_create_invalid_alias(base_app, alias_name, capsys):
+ run_cmd(base_app, 'alias {} help'.format(alias_name))
+ out, err = capsys.readouterr()
+ assert "can not contain" in err
def test_ppaged(base_app):
msg = 'testing...'
diff --git a/tests/test_completion.py b/tests/test_completion.py
index 2d1ee2b7..2faa4a08 100644
--- a/tests/test_completion.py
+++ b/tests/test_completion.py
@@ -13,8 +13,7 @@ import os
import sys
import pytest
-from cmd2 import cmd2
-import cmd2.submenu
+import cmd2
from .conftest import complete_tester, StdOut
from examples.subcommands import SubcommandsExample
@@ -950,124 +949,3 @@ def test_subcommand_tab_completion_space_in_text_scu(scu_app):
assert first_match is not None and \
scu_app.completion_matches == ['Ball" '] and \
scu_app.display_matches == ['Space Ball']
-
-####################################################
-
-
-class SecondLevel(cmd2.Cmd):
- """To be used as a second level command class. """
-
- def __init__(self, *args, **kwargs):
- cmd2.Cmd.__init__(self, *args, **kwargs)
- self.prompt = '2ndLevel '
-
- def do_foo(self, line):
- self.poutput("You called a command in SecondLevel with '%s'. " % line)
-
- def help_foo(self):
- self.poutput("This is a second level menu. Options are qwe, asd, zxc")
-
- def complete_foo(self, text, line, begidx, endidx):
- return [s for s in ['qwe', 'asd', 'zxc'] if s.startswith(text)]
-
-
-second_level_cmd = SecondLevel()
-
-
-@cmd2.submenu.AddSubmenu(second_level_cmd,
- command='second',
- require_predefined_shares=False)
-class SubmenuApp(cmd2.Cmd):
- """To be used as the main / top level command class that will contain other submenus."""
-
- def __init__(self, *args, **kwargs):
- cmd2.Cmd.__init__(self, *args, **kwargs)
- self.prompt = 'TopLevel '
-
-
-@pytest.fixture
-def sb_app():
- app = SubmenuApp()
- return app
-
-
-def test_cmd2_submenu_completion_single_end(sb_app):
- text = 'f'
- line = 'second {}'.format(text)
- endidx = len(line)
- begidx = endidx - len(text)
-
- first_match = complete_tester(text, line, begidx, endidx, sb_app)
-
- # It is at end of line, so extra space is present
- assert first_match is not None and sb_app.completion_matches == ['foo ']
-
-
-def test_cmd2_submenu_completion_multiple(sb_app):
- text = 'e'
- line = 'second {}'.format(text)
- endidx = len(line)
- begidx = endidx - len(text)
-
- expected = ['edit', 'eof', 'eos']
- first_match = complete_tester(text, line, begidx, endidx, sb_app)
-
- assert first_match is not None and sb_app.completion_matches == expected
-
-
-def test_cmd2_submenu_completion_nomatch(sb_app):
- text = 'z'
- line = 'second {}'.format(text)
- endidx = len(line)
- begidx = endidx - len(text)
-
- first_match = complete_tester(text, line, begidx, endidx, sb_app)
- assert first_match is None
-
-
-def test_cmd2_submenu_completion_after_submenu_match(sb_app):
- text = 'a'
- line = 'second foo {}'.format(text)
- endidx = len(line)
- begidx = endidx - len(text)
-
- first_match = complete_tester(text, line, begidx, endidx, sb_app)
- assert first_match is not None and sb_app.completion_matches == ['asd ']
-
-
-def test_cmd2_submenu_completion_after_submenu_nomatch(sb_app):
- text = 'b'
- line = 'second foo {}'.format(text)
- endidx = len(line)
- begidx = endidx - len(text)
-
- first_match = complete_tester(text, line, begidx, endidx, sb_app)
- assert first_match is None
-
-
-def test_cmd2_help_submenu_completion_multiple(sb_app):
- text = 'p'
- line = 'help second {}'.format(text)
- endidx = len(line)
- begidx = endidx - len(text)
-
- matches = sorted(sb_app.complete_help(text, line, begidx, endidx))
- assert matches == ['py', 'pyscript']
-
-
-def test_cmd2_help_submenu_completion_nomatch(sb_app):
- text = 'fake'
- line = 'help second {}'.format(text)
- endidx = len(line)
- begidx = endidx - len(text)
- assert sb_app.complete_help(text, line, begidx, endidx) == []
-
-
-def test_cmd2_help_submenu_completion_subcommands(sb_app):
- text = 'p'
- line = 'help second {}'.format(text)
- endidx = len(line)
- begidx = endidx - len(text)
-
- matches = sorted(sb_app.complete_help(text, line, begidx, endidx))
- assert matches == ['py', 'pyscript']
diff --git a/tests/test_parsing.py b/tests/test_parsing.py
index 19237f6e..7b361b7e 100644
--- a/tests/test_parsing.py
+++ b/tests/test_parsing.py
@@ -16,7 +16,7 @@ from cmd2 import utils
def parser():
parser = StatementParser(
allow_redirection=True,
- terminators=[';'],
+ terminators=[';', '&'],
multiline_commands=['multiline'],
aliases={'helpalias': 'help',
'42': 'theanswer',
@@ -38,7 +38,13 @@ def test_parse_empty_string(parser):
('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'])
+ ('l', ['shell', 'ls', '-al']),
+ ('termbare ; > /tmp/output', ['termbare', ';', '>', '/tmp/output']),
+ ('termbare; > /tmp/output', ['termbare', ';', '>', '/tmp/output']),
+ ('termbare & > /tmp/output', ['termbare', '&', '>', '/tmp/output']),
+ ('termbare& > /tmp/output', ['termbare', '&', '>', '/tmp/output']),
+ ('help|less', ['help', '|', 'less']),
+ ('l|less', ['shell', 'ls', '-al', '|', 'less']),
])
def test_tokenize(parser, line, tokens):
tokens_to_test = parser.tokenize(line)
@@ -46,7 +52,7 @@ def test_tokenize(parser, line, tokens):
def test_tokenize_unclosed_quotes(parser):
with pytest.raises(ValueError):
- tokens = parser.tokenize('command with "unclosed quotes')
+ _ = parser.tokenize('command with "unclosed quotes')
@pytest.mark.parametrize('tokens,command,args', [
([], None, None),
@@ -69,18 +75,28 @@ def test_parse_single_word(parser, line):
assert not statement.args
assert statement.argv == [utils.strip_quotes(line)]
-def test_parse_word_plus_terminator(parser):
- line = 'termbare;'
+@pytest.mark.parametrize('line,terminator', [
+ ('termbare;', ';'),
+ ('termbare ;', ';'),
+ ('termbare&', '&'),
+ ('termbare &', '&'),
+])
+def test_parse_word_plus_terminator(parser, line, terminator):
statement = parser.parse(line)
assert statement.command == 'termbare'
- assert statement.terminator == ';'
+ assert statement.terminator == terminator
assert statement.argv == ['termbare']
-def test_parse_suffix_after_terminator(parser):
- line = 'termbare; suffx'
+@pytest.mark.parametrize('line,terminator', [
+ ('termbare; suffx', ';'),
+ ('termbare ;suffx', ';'),
+ ('termbare& suffx', '&'),
+ ('termbare &suffx', '&'),
+])
+def test_parse_suffix_after_terminator(parser, line, terminator):
statement = parser.parse(line)
assert statement.command == 'termbare'
- assert statement.terminator == ';'
+ assert statement.terminator == terminator
assert statement.suffix == 'suffx'
assert statement.argv == ['termbare']
@@ -134,12 +150,16 @@ def test_parse_what_if_quoted_strings_seem_to_start_comments(parser):
assert not statement.pipe_to
assert statement.argv == ['what', 'if', 'quoted strings /* seem to ', 'start', 'comments?']
-def test_parse_simple_piped(parser):
- statement = parser.parse('simple | piped')
+@pytest.mark.parametrize('line',[
+ 'simple | piped',
+ 'simple|piped',
+])
+def test_parse_simple_pipe(parser, line):
+ statement = parser.parse(line)
assert statement.command == 'simple'
assert not statement.args
assert statement.argv == ['simple']
- assert statement.pipe_to == 'piped'
+ assert statement.pipe_to == ['piped']
def test_parse_double_pipe_is_not_a_pipe(parser):
line = 'double-pipe || is not a pipe'
@@ -150,16 +170,29 @@ def test_parse_double_pipe_is_not_a_pipe(parser):
assert not statement.pipe_to
def test_parse_complex_pipe(parser):
- line = 'command with args, terminator;sufx | piped'
+ line = 'command with args, terminator&sufx | piped'
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.terminator == '&'
assert statement.suffix == 'sufx'
- assert statement.pipe_to == 'piped'
+ assert statement.pipe_to == ['piped']
+
+@pytest.mark.parametrize('line,output', [
+ ('help > out.txt', '>'),
+ ('help>out.txt', '>'),
+ ('help >> out.txt', '>>'),
+ ('help>>out.txt', '>>'),
+])
+def test_parse_redirect(parser,line, output):
+ statement = parser.parse(line)
+ assert statement.command == 'help'
+ assert not statement.args
+ assert statement.output == output
+ assert statement.output_to == 'out.txt'
-def test_parse_output_redirect(parser):
+def test_parse_redirect_with_args(parser):
line = 'output into > afile.txt'
statement = parser.parse(line)
assert statement.command == 'output'
@@ -168,7 +201,7 @@ def test_parse_output_redirect(parser):
assert statement.output == '>'
assert statement.output_to == 'afile.txt'
-def test_parse_output_redirect_with_dash_in_path(parser):
+def test_parse_redirect_with_dash_in_path(parser):
line = 'output into > python-cmd2/afile.txt'
statement = parser.parse(line)
assert statement.command == 'output'
@@ -177,7 +210,7 @@ def test_parse_output_redirect_with_dash_in_path(parser):
assert statement.output == '>'
assert statement.output_to == 'python-cmd2/afile.txt'
-def test_parse_output_redirect_append(parser):
+def test_parse_redirect_append(parser):
line = 'output appended to >> /tmp/afile.txt'
statement = parser.parse(line)
assert statement.command == 'output'
@@ -194,9 +227,9 @@ def test_parse_pipe_and_redirect(parser):
assert statement.argv == ['output', 'into']
assert statement.terminator == ';'
assert statement.suffix == 'sufx'
- assert statement.pipe_to == 'pipethrume plz'
- assert statement.output == '>'
- assert statement.output_to == 'afile.txt'
+ assert statement.pipe_to == ['pipethrume', 'plz', '>', 'afile.txt']
+ assert not statement.output
+ assert not statement.output_to
def test_parse_output_to_paste_buffer(parser):
line = 'output to paste buffer >> '
@@ -207,8 +240,9 @@ def test_parse_output_to_paste_buffer(parser):
assert statement.output == '>>'
def test_parse_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."""
+ """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'
@@ -216,6 +250,23 @@ def test_parse_redirect_inside_terminator(parser):
assert statement.argv == ['has', '>', 'inside']
assert statement.terminator == ';'
+@pytest.mark.parametrize('line,terminator',[
+ ('multiline with | inside;', ';'),
+ ('multiline with | inside ;', ';'),
+ ('multiline with | inside;;;', ';'),
+ ('multiline with | inside;; ;;', ';'),
+ ('multiline with | inside&', '&'),
+ ('multiline with | inside &;', '&'),
+ ('multiline with | inside&&;', '&'),
+ ('multiline with | inside &; &;', '&'),
+])
+def test_parse_multiple_terminators(parser, line, terminator):
+ statement = parser.parse(line)
+ assert statement.multiline_command == 'multiline'
+ assert statement.args == 'with | inside'
+ assert statement.argv == ['multiline', 'with', '|', 'inside']
+ assert statement.terminator == terminator
+
def test_parse_unfinished_multiliine_command(parser):
line = 'multiline has > inside an unfinished command'
statement = parser.parse(line)
@@ -225,13 +276,19 @@ def test_parse_unfinished_multiliine_command(parser):
assert statement.argv == ['multiline', 'has', '>', 'inside', 'an', 'unfinished', 'command']
assert not statement.terminator
-def test_parse_multiline_command_ignores_redirectors_within_it(parser):
- line = 'multiline has > inside;'
+@pytest.mark.parametrize('line,terminator',[
+ ('multiline has > inside;', ';'),
+ ('multiline has > inside;;;', ';'),
+ ('multiline has > inside;; ;;', ';'),
+ ('multiline has > inside &', '&'),
+ ('multiline has > inside & &', '&'),
+])
+def test_parse_multiline_command_ignores_redirectors_within_it(parser, line, terminator):
statement = parser.parse(line)
assert statement.multiline_command == 'multiline'
assert statement.args == 'has > inside'
assert statement.argv == ['multiline', 'has', '>', 'inside']
- assert statement.terminator == ';'
+ assert statement.terminator == terminator
def test_parse_multiline_with_incomplete_comment(parser):
"""A terminator within a comment will be ignored and won't terminate a multiline command.
@@ -296,7 +353,7 @@ def test_parse_redirect_to_unicode_filename(parser):
def test_parse_unclosed_quotes(parser):
with pytest.raises(ValueError):
- tokens = parser.tokenize("command with 'unclosed quotes")
+ _ = parser.tokenize("command with 'unclosed quotes")
def test_empty_statement_raises_exception():
app = cmd2.Cmd()
@@ -315,12 +372,12 @@ def test_empty_statement_raises_exception():
('!ls -al /tmp', 'shell', 'ls -al /tmp'),
('l', 'shell', 'ls -al')
])
-def test_alias_and_shortcut_expansion(parser, line, command, args):
+def test_parse_alias_and_shortcut_expansion(parser, line, command, args):
statement = parser.parse(line)
assert statement.command == command
assert statement.args == args
-def test_alias_on_multiline_command(parser):
+def test_parse_alias_on_multiline_command(parser):
line = 'anothermultiline has > inside an unfinished command'
statement = parser.parse(line)
assert statement.multiline_command == 'multiline'
@@ -328,6 +385,43 @@ def test_alias_on_multiline_command(parser):
assert statement.args == 'has > inside an unfinished command'
assert not statement.terminator
+@pytest.mark.parametrize('line,output', [
+ ('helpalias > out.txt', '>'),
+ ('helpalias>out.txt', '>'),
+ ('helpalias >> out.txt', '>>'),
+ ('helpalias>>out.txt', '>>'),
+])
+def test_parse_alias_redirection(parser, line, output):
+ statement = parser.parse(line)
+ assert statement.command == 'help'
+ assert not statement.args
+ assert statement.output == output
+ assert statement.output_to == 'out.txt'
+
+@pytest.mark.parametrize('line', [
+ 'helpalias | less',
+ 'helpalias|less',
+])
+def test_parse_alias_pipe(parser, line):
+ statement = parser.parse(line)
+ assert statement.command == 'help'
+ assert not statement.args
+ assert statement.pipe_to == ['less']
+
+@pytest.mark.parametrize('line', [
+ 'helpalias;',
+ 'helpalias;;',
+ 'helpalias;; ;',
+ 'helpalias ;',
+ 'helpalias ; ;',
+ 'helpalias ;; ;',
+])
+def test_parse_alias_terminator_no_whitespace(parser, line):
+ statement = parser.parse(line)
+ assert statement.command == 'help'
+ assert not statement.args
+ assert statement.terminator == ';'
+
def test_parse_command_only_command_and_args(parser):
line = 'help history'
statement = parser.parse_command_only(line)
@@ -373,3 +467,34 @@ def test_parse_command_only_quoted_args(parser):
assert statement.command == 'shell'
assert statement.args == 'ls -al "/tmp/directory with spaces/doit.sh"'
assert statement.command_and_args == line.replace('l', 'shell ls -al')
+
+@pytest.mark.parametrize('line', [
+ 'helpalias > out.txt',
+ 'helpalias>out.txt',
+ 'helpalias >> out.txt',
+ 'helpalias>>out.txt',
+ 'help|less',
+ 'helpalias;',
+ 'help ;;',
+ 'help; ;;',
+])
+def test_parse_command_only_specialchars(parser, line):
+ statement = parser.parse_command_only(line)
+ assert statement.command == 'help'
+
+@pytest.mark.parametrize('line', [
+ ';',
+ ';;',
+ ';; ;',
+ '&',
+ '& &',
+ ' && &',
+ '>',
+ "'",
+ '"',
+ '|',
+])
+def test_parse_command_only_none(parser, line):
+ statement = parser.parse_command_only(line)
+ assert statement.command == None
+ assert statement.args == None
diff --git a/tests/test_pyscript.py b/tests/test_pyscript.py
index 8d0cefd8..73c1a62a 100644
--- a/tests/test_pyscript.py
+++ b/tests/test_pyscript.py
@@ -101,7 +101,14 @@ class PyscriptExample(Cmd):
@with_argparser(bar_parser)
def do_bar(self, args):
- print('bar ' + str(args.__dict__))
+ out = 'bar '
+ arg_dict = args.__dict__
+ keys = list(arg_dict.keys())
+ keys.sort()
+ out += '{'
+ for key in keys:
+ out += "'{}':'{}'".format(key, arg_dict[key])
+ print(out)
@pytest.fixture
@@ -160,7 +167,7 @@ def test_pyscript_help(ps_app, capsys, request, command, pyscript_file):
('foo aaa bbb -ccc -t -n', 'foo1.py'),
('foo 11 22 33 44 -ccc -t -n', 'foo2.py'),
('foo 11 22 33 44 55 66 -ccc', 'foo3.py'),
- ('bar 11 22', 'bar1.py')
+ ('bar 11 22', 'bar1.py'),
])
def test_pyscript_out(ps_app, capsys, request, command, pyscript_file):
test_dir = os.path.dirname(request.module.__file__)
@@ -204,11 +211,30 @@ def test_pyscript_results(ps_app, capsys, request, pyscript_file, exp_out):
assert exp_out in expected
-def test_pyscript_custom_name(ps_echo, capsys):
+@pytest.mark.parametrize('expected, pyscript_file', [
+ ("['_relative_load', 'alias', 'bar', 'cmd_echo', 'edit', 'eof', 'eos', 'foo', 'help', 'history', 'load', 'media', 'py', 'pyscript', 'quit', 'set', 'shell', 'shortcuts', 'unalias']",
+ 'pyscript_dir1.py'),
+ ("['movies', 'shows']", 'pyscript_dir2.py')
+])
+def test_pyscript_dir(ps_app, capsys, request, expected, pyscript_file):
+ test_dir = os.path.dirname(request.module.__file__)
+ python_script = os.path.join(test_dir, 'pyscript', pyscript_file)
+
+ run_cmd(ps_app, 'pyscript {}'.format(python_script))
+ out, _ = capsys.readouterr()
+ out = out.strip()
+ assert len(out) > 0
+ assert out == expected
+
+
+def test_pyscript_custom_name(ps_echo, capsys, request):
message = 'blah!'
- run_cmd(ps_echo, 'py custom.echo("{}")'.format(message))
+
+ test_dir = os.path.dirname(request.module.__file__)
+ python_script = os.path.join(test_dir, 'pyscript', 'custom_echo.py')
+
+ run_cmd(ps_echo, 'pyscript {}'.format(python_script))
expected, _ = capsys.readouterr()
assert len(expected) > 0
expected = expected.splitlines()
assert message == expected[0]
-
diff --git a/tests/test_submenu.py b/tests/test_submenu.py
deleted file mode 100644
index 2603c536..00000000
--- a/tests/test_submenu.py
+++ /dev/null
@@ -1,182 +0,0 @@
-# coding=utf-8
-"""
-Cmd2 testing for argument parsing
-"""
-import pytest
-
-from cmd2 import cmd2
-import cmd2.submenu
-from .conftest import run_cmd, StdOut, normalize
-
-
-class SecondLevelB(cmd2.Cmd):
- """To be used as a second level command class. """
-
- def __init__(self, *args, **kwargs):
- cmd2.Cmd.__init__(self, *args, **kwargs)
- self.prompt = '2ndLevel B '
-
- def do_get_top_level_attr(self, line):
- self.poutput(str(self.top_level_attr))
-
- def do_set_top_level_attr(self, line):
- self.top_level_attr = 987654321
-
-
-class SecondLevel(cmd2.Cmd):
- """To be used as a second level command class. """
-
- def __init__(self, *args, **kwargs):
- cmd2.Cmd.__init__(self, *args, **kwargs)
- self.prompt = '2ndLevel '
- self.top_level_attr = None
-
- def do_say(self, line):
- self.poutput("You called a command in SecondLevel with '%s'. " % line)
-
- def help_say(self):
- self.poutput("This is a second level menu. Options are qwe, asd, zxc")
-
- def complete_say(self, text, line, begidx, endidx):
- return [s for s in ['qwe', 'asd', 'zxc'] if s.startswith(text)]
-
- def do_get_top_level_attr(self, line):
- self.poutput(str(self.top_level_attr))
-
- def do_get_prompt(self, line):
- self.poutput(self.prompt)
-
-
-second_level_cmd = SecondLevel()
-second_level_b_cmd = SecondLevelB()
-
-
-@cmd2.submenu.AddSubmenu(SecondLevelB(),
- command='should_work_with_default_kwargs')
-@cmd2.submenu.AddSubmenu(second_level_b_cmd,
- command='secondb',
- shared_attributes=dict(top_level_attr='top_level_attr'),
- require_predefined_shares=False,
- preserve_shares=True
- )
-@cmd2.submenu.AddSubmenu(second_level_cmd,
- command='second',
- aliases=('second_alias',),
- shared_attributes=dict(top_level_attr='top_level_attr'))
-class SubmenuApp(cmd2.Cmd):
- """To be used as the main / top level command class that will contain other submenus."""
-
- def __init__(self, *args, **kwargs):
- cmd2.Cmd.__init__(self, *args, **kwargs)
- self.prompt = 'TopLevel '
- self.top_level_attr = 123456789
-
- def do_say(self, line):
- self.poutput("You called a command in TopLevel with '%s'. " % line)
-
- def help_say(self):
- self.poutput("This is a top level submenu. Options are qwe, asd, zxc")
-
- def complete_say(self, text, line, begidx, endidx):
- return [s for s in ['qwe', 'asd', 'zxc'] if s.startswith(text)]
-
-
-@pytest.fixture
-def submenu_app():
- app = SubmenuApp()
- app.stdout = StdOut()
- second_level_cmd.stdout = StdOut()
- second_level_b_cmd.stdout = StdOut()
- return app
-
-
-@pytest.fixture
-def secondlevel_app():
- app = SecondLevel()
- app.stdout = StdOut()
- return app
-
-
-@pytest.fixture
-def secondlevel_app_b():
- app = SecondLevelB()
- app.stdout = StdOut()
- return app
-
-
-def run_submenu_cmd(app, second_level_app, cmd):
- """ Clear StdOut buffers, run the command, extract the buffer contents."""
- app.stdout.clear()
- second_level_app.stdout.clear()
- app.onecmd_plus_hooks(cmd)
- out1 = app.stdout.buffer
- out2 = second_level_app.stdout.buffer
- app.stdout.clear()
- second_level_app.stdout.clear()
- return normalize(out1), normalize(out2)
-
-
-def test_submenu_say_from_top_level(submenu_app):
- line = 'testing'
- out1, out2 = run_submenu_cmd(submenu_app, second_level_cmd, 'say ' + line)
- assert len(out1) == 1
- assert len(out2) == 0
- assert out1[0] == "You called a command in TopLevel with {!r}.".format(line)
-
-
-def test_submenu_second_say_from_top_level(submenu_app):
- line = 'testing'
- out1, out2 = run_submenu_cmd(submenu_app, second_level_cmd, 'second say ' + line)
-
- # No output expected from the top level
- assert out1 == []
-
- # Output expected from the second level
- assert len(out2) == 1
- assert out2[0] == "You called a command in SecondLevel with {!r}.".format(line)
-
-
-def test_submenu_say_from_second_level(secondlevel_app):
- line = 'testing'
- out = run_cmd(secondlevel_app, 'say ' + line)
- assert out == ["You called a command in SecondLevel with '%s'." % line]
-
-
-def test_submenu_help_second_say_from_top_level(submenu_app):
- out1, out2 = run_submenu_cmd(submenu_app, second_level_cmd, 'help second say')
- # No output expected from the top level
- assert out1 == []
-
- # Output expected from the second level
- assert out2 == ["This is a second level menu. Options are qwe, asd, zxc"]
-
-
-def test_submenu_help_say_from_second_level(secondlevel_app):
- out = run_cmd(secondlevel_app, 'help say')
- assert out == ["This is a second level menu. Options are qwe, asd, zxc"]
-
-
-def test_submenu_help_second(submenu_app):
- out1, out2 = run_submenu_cmd(submenu_app, second_level_cmd, 'help second')
- out3 = run_cmd(second_level_cmd, 'help')
- assert out2 == out3
-
-
-def test_submenu_from_top_help_second_say(submenu_app):
- out1, out2 = run_submenu_cmd(submenu_app, second_level_cmd, 'help second say')
- out3 = run_cmd(second_level_cmd, 'help say')
- assert out2 == out3
-
-
-def test_submenu_shared_attribute(submenu_app):
- out1, out2 = run_submenu_cmd(submenu_app, second_level_cmd, 'second get_top_level_attr')
- assert out2 == [str(submenu_app.top_level_attr)]
-
-
-def test_submenu_shared_attribute_preserve(submenu_app):
- out1, out2 = run_submenu_cmd(submenu_app, second_level_b_cmd, 'secondb get_top_level_attr')
- assert out2 == [str(submenu_app.top_level_attr)]
- out1, out2 = run_submenu_cmd(submenu_app, second_level_b_cmd, 'secondb set_top_level_attr')
- assert submenu_app.top_level_attr == 987654321
- out1, out2 = run_submenu_cmd(submenu_app, second_level_b_cmd, 'secondb get_top_level_attr')
- assert out2 == [str(987654321)]