From 4046a6968405dce820168913dbfe3690c446dac9 Mon Sep 17 00:00:00 2001 From: Todd Leonhardt Date: Sat, 20 Jan 2018 12:59:39 -0500 Subject: Fixed unit tests Updated unit tests due to changes in how help is output for commands decorated with an argparse ArgumentParser. --- tests/test_argparse.py | 18 ++++++++++++------ 1 file changed, 12 insertions(+), 6 deletions(-) (limited to 'tests/test_argparse.py') diff --git a/tests/test_argparse.py b/tests/test_argparse.py index 21e81603..733e741b 100644 --- a/tests/test_argparse.py +++ b/tests/test_argparse.py @@ -138,20 +138,26 @@ def test_argparse_quoted_arguments_posix_multiple(argparse_app): out = run_cmd(argparse_app, 'tag strong this "should be" loud') assert out == ['this should be loud'] -def test_argparse_help_docstring(argparse_app): - out = run_cmd(argparse_app, 'help say') +def test_argparse_help_docstring(argparse_app, capsys): + run_cmd(argparse_app, 'help say') + out, err = capsys.readouterr() + out = out.splitlines() assert out[0].startswith('usage: say') assert out[1] == '' assert out[2] == 'Repeat what you tell me to.' -def test_argparse_help_description(argparse_app): - out = run_cmd(argparse_app, 'help tag') +def test_argparse_help_description(argparse_app, capsys): + run_cmd(argparse_app, 'help tag') + out, err = capsys.readouterr() + out = out.splitlines() assert out[0].startswith('usage: tag') assert out[1] == '' assert out[2] == 'create a html tag' -def test_argparse_prog(argparse_app): - out = run_cmd(argparse_app, 'help tag') +def test_argparse_prog(argparse_app, capsys): + run_cmd(argparse_app, 'help tag') + out, err = capsys.readouterr() + out = out.splitlines() progname = out[0].split(' ')[1] assert progname == 'tag' -- cgit v1.2.1 From 5550ab73a91d2834e6bda72eb3889998ad59be51 Mon Sep 17 00:00:00 2001 From: Todd Leonhardt Date: Sat, 20 Jan 2018 16:48:52 -0500 Subject: Added unit tests for sub-commands --- tests/test_argparse.py | 92 ++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 92 insertions(+) (limited to 'tests/test_argparse.py') diff --git a/tests/test_argparse.py b/tests/test_argparse.py index 733e741b..bb494d49 100644 --- a/tests/test_argparse.py +++ b/tests/test_argparse.py @@ -8,6 +8,7 @@ import pytest import cmd2 from conftest import run_cmd, StdOut + class ArgparseApp(cmd2.Cmd): def __init__(self): self.maxrepeats = 3 @@ -168,3 +169,94 @@ def test_arglist(argparse_app): def test_arglist_decorator_twice(argparse_app): out = run_cmd(argparse_app, 'arglisttwice "we should" get these') assert out[0] == 'we should get these' + + +class SubcommandApp(cmd2.Cmd): + """ Example cmd2 application where we a base command which has a couple subcommands.""" + + def __init__(self): + cmd2.Cmd.__init__(self) + + # sub-command functions for the base command + def foo(self, args): + """foo subcommand of base command""" + self.poutput(args.x * args.y) + + def bar(self, args): + """bar sucommand of base command""" + self.poutput('((%s))' % args.z) + + # create the top-level parser for the base command + base_parser = argparse.ArgumentParser(prog='base') + base_subparsers = base_parser.add_subparsers(title='subcommands', help='subcommand help') + + # create the parser for the "foo" sub-command + parser_foo = base_subparsers.add_parser('foo', help='foo help') + parser_foo.add_argument('-x', type=int, default=1, help='integer') + parser_foo.add_argument('y', type=float, help='float') + parser_foo.set_defaults(func=foo) + + # create the parser for the "bar" sub-command + parser_bar = base_subparsers.add_parser('bar', help='bar help') + parser_bar.add_argument('z', help='string') + parser_bar.set_defaults(func=bar) + + # Create a list of subcommand names, which is used to enable tab-completion of sub-commands + subcommands = ['foo', 'bar'] + + @cmd2.with_argparser_and_unknown_args(base_parser, subcommands) + def do_base(self, args, arglist): + """Base command help""" + try: + # Call whatever sub-command function was selected + args.func(self, args) + except AttributeError: + # No sub-command was provided, so as called + self.do_help('base') + +@pytest.fixture +def subcommand_app(): + app = SubcommandApp() + app.stdout = StdOut() + return app + + +def test_subcommand_foo(subcommand_app): + out = run_cmd(subcommand_app, 'base foo -x2 5.0') + assert out == ['10.0'] + + +def test_subcommand_bar(subcommand_app): + out = run_cmd(subcommand_app, 'base bar baz') + assert out == ['((baz))'] + +def test_subcommand_invalid(subcommand_app, capsys): + run_cmd(subcommand_app, 'base baz') + out, err = capsys.readouterr() + err = err.splitlines() + assert err[0].startswith('usage: base') + assert err[1].startswith("base: error: invalid choice: 'baz'") + +def test_subcommand_base_help(subcommand_app, capsys): + run_cmd(subcommand_app, 'help base') + out, err = capsys.readouterr() + out = out.splitlines() + assert out[0].startswith('usage: base') + assert out[1] == '' + assert out[2] == 'Base command help' + +def test_subcommand_help(subcommand_app, capsys): + run_cmd(subcommand_app, 'help base foo') + out, err = capsys.readouterr() + out = out.splitlines() + assert out[0].startswith('usage: base foo') + assert out[1] == '' + assert out[2] == 'positional arguments:' + + +def test_subcommand_invalid_help(subcommand_app, capsys): + run_cmd(subcommand_app, 'help base baz') + out, err = capsys.readouterr() + err = err.splitlines() + assert err[0].startswith('usage: base') + assert err[1].startswith("base: error: invalid choice: 'baz'") -- cgit v1.2.1 From c9f7c012bda012b4df7a8c5e853bd5d3e6d99b1b Mon Sep 17 00:00:00 2001 From: Todd Leonhardt Date: Sun, 21 Jan 2018 22:24:09 -0500 Subject: Renamed @with_argument_parser decorator to @with_argparser Also: - Reanamed foo and bar subcommand methods to base_foo and base_bar --- tests/test_argparse.py | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) (limited to 'tests/test_argparse.py') diff --git a/tests/test_argparse.py b/tests/test_argparse.py index bb494d49..ecaa1049 100644 --- a/tests/test_argparse.py +++ b/tests/test_argparse.py @@ -20,7 +20,7 @@ class ArgparseApp(cmd2.Cmd): say_parser.add_argument('-r', '--repeat', type=int, help='output [n] times') say_parser.add_argument('words', nargs='+', help='words to say') - @cmd2.with_argument_parser(say_parser) + @cmd2.with_argparser(say_parser) def do_say(self, args): """Repeat what you tell me to.""" words = [] @@ -41,7 +41,7 @@ class ArgparseApp(cmd2.Cmd): tag_parser.add_argument('tag', help='tag') tag_parser.add_argument('content', nargs='+', help='content to surround with tag') - @cmd2.with_argument_parser(tag_parser) + @cmd2.with_argparser(tag_parser) def do_tag(self, args): self.stdout.write('<{0}>{1}'.format(args.tag, ' '.join(args.content))) self.stdout.write('\n') @@ -178,11 +178,11 @@ class SubcommandApp(cmd2.Cmd): cmd2.Cmd.__init__(self) # sub-command functions for the base command - def foo(self, args): + def base_foo(self, args): """foo subcommand of base command""" self.poutput(args.x * args.y) - def bar(self, args): + def base_bar(self, args): """bar sucommand of base command""" self.poutput('((%s))' % args.z) @@ -194,12 +194,12 @@ class SubcommandApp(cmd2.Cmd): parser_foo = base_subparsers.add_parser('foo', help='foo help') parser_foo.add_argument('-x', type=int, default=1, help='integer') parser_foo.add_argument('y', type=float, help='float') - parser_foo.set_defaults(func=foo) + parser_foo.set_defaults(func=base_foo) # create the parser for the "bar" sub-command parser_bar = base_subparsers.add_parser('bar', help='bar help') parser_bar.add_argument('z', help='string') - parser_bar.set_defaults(func=bar) + parser_bar.set_defaults(func=base_bar) # Create a list of subcommand names, which is used to enable tab-completion of sub-commands subcommands = ['foo', 'bar'] -- cgit v1.2.1 From f28c10a50535f753419bd2120ac6cb0bea9f56e2 Mon Sep 17 00:00:00 2001 From: Todd Leonhardt Date: Mon, 22 Jan 2018 00:08:27 -0500 Subject: help command temporarily redirects sys.stdout and sys.stderr to self.stdout for argparse commands In order to make "help" behave more consistently for decorated and undecorated commands, argparse output is temporarily redirected to self.stdout. So doing "help history" is similar to "help load". However, when using the "-h" with argparse commands without using the "help" command, the output from argparse isn't redirected to self.stdout. Fixing this would be rather difficult and would essentially involve creating a pyparsing rule to detect it at the parser level. --- tests/test_argparse.py | 40 ++++++++++++++-------------------------- 1 file changed, 14 insertions(+), 26 deletions(-) (limited to 'tests/test_argparse.py') diff --git a/tests/test_argparse.py b/tests/test_argparse.py index ecaa1049..d3646046 100644 --- a/tests/test_argparse.py +++ b/tests/test_argparse.py @@ -139,26 +139,20 @@ def test_argparse_quoted_arguments_posix_multiple(argparse_app): out = run_cmd(argparse_app, 'tag strong this "should be" loud') assert out == ['this should be loud'] -def test_argparse_help_docstring(argparse_app, capsys): - run_cmd(argparse_app, 'help say') - out, err = capsys.readouterr() - out = out.splitlines() +def test_argparse_help_docstring(argparse_app): + out = run_cmd(argparse_app, 'help say') assert out[0].startswith('usage: say') assert out[1] == '' assert out[2] == 'Repeat what you tell me to.' -def test_argparse_help_description(argparse_app, capsys): - run_cmd(argparse_app, 'help tag') - out, err = capsys.readouterr() - out = out.splitlines() +def test_argparse_help_description(argparse_app): + out = run_cmd(argparse_app, 'help tag') assert out[0].startswith('usage: tag') assert out[1] == '' assert out[2] == 'create a html tag' -def test_argparse_prog(argparse_app, capsys): - run_cmd(argparse_app, 'help tag') - out, err = capsys.readouterr() - out = out.splitlines() +def test_argparse_prog(argparse_app): + out = run_cmd(argparse_app, 'help tag') progname = out[0].split(' ')[1] assert progname == 'tag' @@ -237,26 +231,20 @@ def test_subcommand_invalid(subcommand_app, capsys): assert err[0].startswith('usage: base') assert err[1].startswith("base: error: invalid choice: 'baz'") -def test_subcommand_base_help(subcommand_app, capsys): - run_cmd(subcommand_app, 'help base') - out, err = capsys.readouterr() - out = out.splitlines() +def test_subcommand_base_help(subcommand_app): + out = run_cmd(subcommand_app, 'help base') assert out[0].startswith('usage: base') assert out[1] == '' assert out[2] == 'Base command help' -def test_subcommand_help(subcommand_app, capsys): - run_cmd(subcommand_app, 'help base foo') - out, err = capsys.readouterr() - out = out.splitlines() +def test_subcommand_help(subcommand_app): + out = run_cmd(subcommand_app, 'help base foo') assert out[0].startswith('usage: base foo') assert out[1] == '' assert out[2] == 'positional arguments:' -def test_subcommand_invalid_help(subcommand_app, capsys): - run_cmd(subcommand_app, 'help base baz') - out, err = capsys.readouterr() - err = err.splitlines() - assert err[0].startswith('usage: base') - assert err[1].startswith("base: error: invalid choice: 'baz'") +def test_subcommand_invalid_help(subcommand_app): + out = run_cmd(subcommand_app, 'help base baz') + assert out[0].startswith('usage: base') + assert out[1].startswith("base: error: invalid choice: 'baz'") -- cgit v1.2.1