diff --git a/avocado/core/parser.py b/avocado/core/parser.py index a2b7f10091613fb3c7a59f3dcba67d3d21c80a23..557896e82d44f38b976621f4e72c9a4a455770f7 100644 --- a/avocado/core/parser.py +++ b/avocado/core/parser.py @@ -18,7 +18,9 @@ Avocado application command line parsing. """ import argparse +import sys +from . import exit_codes from . import tree from . import settings from .version import VERSION @@ -27,6 +29,18 @@ PROG = 'avocado' DESCRIPTION = 'Avocado Test Runner' +class ArgumentParser(argparse.ArgumentParser): + + """ + Class to override argparse functions + """ + + def error(self, message): + msg = '%s: error: %s\n' % (self.prog, message) + self.print_help(sys.stderr) + self.exit(exit_codes.AVOCADO_FAIL, msg) + + class Parser(object): """ @@ -36,10 +50,9 @@ class Parser(object): def __init__(self): self.args = None self.subcommands = None - self.application = argparse.ArgumentParser( - prog=PROG, - add_help=False, # see parent parsing - description=DESCRIPTION) + self.application = ArgumentParser(prog=PROG, + add_help=False, # see parent parsing + description=DESCRIPTION) self.application.add_argument('-v', '--version', action='version', version='Avocado %s' % VERSION) self.application.add_argument('--config', metavar='CONFIG_FILE', @@ -59,9 +72,9 @@ class Parser(object): settings.settings.process_config_path(self.args.config) # Use parent parsing to avoid breaking the output of --help option - self.application = argparse.ArgumentParser(prog=PROG, - description=DESCRIPTION, - parents=[self.application]) + self.application = ArgumentParser(prog=PROG, + description=DESCRIPTION, + parents=[self.application]) # Subparsers where Avocado subcommands are plugged self.subcommands = self.application.add_subparsers( @@ -80,4 +93,11 @@ class Parser(object): Side effect: set the final value for attribute `args`. """ - self.args = self.application.parse_args(namespace=self.args) + self.args, extra = self.application.parse_known_args(namespace=self.args) + if extra: + msg = 'unrecognized arguments: %s' % ' '.join(extra) + for sub in self.application._subparsers._actions: + if sub.dest == 'subcommand': + sub.choices[self.args.subcommand].error(msg) + + self.application.error(msg) diff --git a/selftests/functional/test_argument_parsing.py b/selftests/functional/test_argument_parsing.py index 2fb6b1d3323a4aef0ca9682f2fb372c6b7284482..4c8554015b766a4153dd0e9331b9d079d030111d 100644 --- a/selftests/functional/test_argument_parsing.py +++ b/selftests/functional/test_argument_parsing.py @@ -23,7 +23,7 @@ class ArgumentParsingTest(unittest.TestCase): os.chdir(basedir) cmd_line = './scripts/avocado whacky-command-that-doesnt-exist' result = process.run(cmd_line, ignore_status=True) - expected_rc = exit_codes.AVOCADO_JOB_FAIL + expected_rc = exit_codes.AVOCADO_FAIL self.assertEqual(result.exit_status, expected_rc, 'Avocado did not return rc %d:\n%s' % (expected_rc, result)) @@ -31,7 +31,7 @@ class ArgumentParsingTest(unittest.TestCase): os.chdir(basedir) cmd_line = './scripts/avocado run --sysinfo=foo passtest' result = process.run(cmd_line, ignore_status=True) - expected_rc = exit_codes.AVOCADO_JOB_FAIL + expected_rc = exit_codes.AVOCADO_FAIL self.assertEqual(result.exit_status, expected_rc, 'Avocado did not return rc %d:\n%s' % (expected_rc, result)) @@ -39,14 +39,17 @@ class ArgumentParsingTest(unittest.TestCase): os.chdir(basedir) cmd_line = './scripts/avocado run --sysinfo=off --whacky-argument passtest' result = process.run(cmd_line, ignore_status=True) - expected_rc = exit_codes.AVOCADO_JOB_FAIL + expected_rc = exit_codes.AVOCADO_FAIL self.assertEqual(result.exit_status, expected_rc, 'Avocado did not return rc %d:\n%s' % (expected_rc, result)) + subcommand_error_msg = 'avocado run: error: unrecognized arguments: '\ + '--whacky-argument' + self.assertIn(subcommand_error_msg, result.stderr) class ArgumentParsingErrorEarlyTest(unittest.TestCase): - def run_but_fail_before_create_job_dir(self, complement_args): + def run_but_fail_before_create_job_dir(self, complement_args, expected_rc): """ Runs avocado but checks that it fails before creating the job dir @@ -60,17 +63,18 @@ class ArgumentParsingErrorEarlyTest(unittest.TestCase): cmd_line = './scripts/avocado run --sysinfo=off --force-job-id=%s %s' cmd_line %= (job, complement_args) result = process.run(cmd_line, ignore_status=True) - expected_rc = exit_codes.AVOCADO_JOB_FAIL self.assertEqual(result.exit_status, expected_rc, 'Avocado did not return rc %d:\n%s' % (expected_rc, result)) path_job_glob = os.path.join(log_dir, "job-*-%s" % job[0:7]) self.assertEquals(glob.glob(path_job_glob), []) def test_whacky_option(self): - self.run_but_fail_before_create_job_dir('--whacky-option passtest') + self.run_but_fail_before_create_job_dir('--whacky-option passtest', + exit_codes.AVOCADO_FAIL) def test_empty_option(self): - self.run_but_fail_before_create_job_dir('') + self.run_but_fail_before_create_job_dir('', + exit_codes.AVOCADO_JOB_FAIL) if __name__ == '__main__': unittest.main() diff --git a/selftests/functional/test_basic.py b/selftests/functional/test_basic.py index 047a27d3eec9081d2d41b333b2c8a397fc93d80d..8a285ecf551a1ba0d651f06ecc5a1e21050919c3 100644 --- a/selftests/functional/test_basic.py +++ b/selftests/functional/test_basic.py @@ -191,7 +191,7 @@ class RunnerOperationTest(unittest.TestCase): os.chdir(basedir) cmd_line = './scripts/avocado' result = process.run(cmd_line, ignore_status=True) - expected_rc = exit_codes.AVOCADO_JOB_FAIL + expected_rc = exit_codes.AVOCADO_FAIL expected_output = 'error: too few arguments' self.assertEqual(result.exit_status, expected_rc) self.assertIn(expected_output, result.stderr) diff --git a/selftests/functional/test_replay.py b/selftests/functional/test_replay.py index 1cda737be2a341ae30734e4002c5f6848c3e53dd..cf7cddadb28b40a355338f0b53f3b5ff0140f5b0 100644 --- a/selftests/functional/test_replay.py +++ b/selftests/functional/test_replay.py @@ -75,7 +75,7 @@ class ReplayTests(unittest.TestCase): cmd_line = ('./scripts/avocado run --replay %s --replay-ignore foo' '--job-results-dir %s --replay-data-dir %s --sysinfo=off' % (self.jobid, self.tmpdir, self.jobdir)) - expected_rc = exit_codes.AVOCADO_JOB_FAIL + expected_rc = exit_codes.AVOCADO_FAIL result = self.run_and_check(cmd_line, expected_rc) msg = 'Invalid --replay-ignore option. Valid options are ' \ '(more than one allowed): mux,config' @@ -94,7 +94,7 @@ class ReplayTests(unittest.TestCase): cmd_line = ('./scripts/avocado run --replay %s --replay-test-status E ' '--job-results-dir %s --replay-data-dir %s --sysinfo=off' % (self.jobid, self.tmpdir, self.jobdir)) - expected_rc = exit_codes.AVOCADO_JOB_FAIL + expected_rc = exit_codes.AVOCADO_FAIL result = self.run_and_check(cmd_line, expected_rc) msg = 'Invalid --replay-test-status option. Valid options are (more ' \ 'than one allowed): SKIP,ERROR,FAIL,WARN,PASS,INTERRUPTED'