diff --git a/covimerage/__main__.py b/covimerage/__main__.py index 5da29c46..7f752c38 100644 --- a/covimerage/__main__.py +++ b/covimerage/__main__.py @@ -1,3 +1,32 @@ -if __name__ == '__main__': +def wrap_for_errormsg(f, *args, **kwargs): + try: + f(*args, standalone_mode=False, **kwargs) + except Exception as exc: + from click.exceptions import ClickException + if isinstance(exc, ClickException): + import re, sys + from click.utils import echo + from ._compat import StringIO + + # Use `show()` to get extended message with UsageErrors. + out = StringIO() + exc.show(file=out) + out.seek(0) + msg = re.sub("^Error: ", "covimerage: error: ", out.read(), flags=re.MULTILINE) + echo(msg, err=True, nl=False) + sys.exit(exc.exit_code) + raise + + +def main(): from .cli import main + wrap_for_errormsg(main.main, prog_name='covimerage') + + +def run(): + from .cli import run + wrap_for_errormsg(run.main, prog_name='covimerage-run') + + +if __name__ == '__main__': main() diff --git a/covimerage/cli.py b/covimerage/cli.py index 7fb5b141..26f7ad0c 100644 --- a/covimerage/cli.py +++ b/covimerage/cli.py @@ -10,12 +10,14 @@ from .logger import logger from .utils import build_vim_profile_args, join_argv +context_settings = {'help_option_names': ['-h', '--help']} + def default_loglevel(): return logging.getLevelName(logger.level).lower() -@click.group(context_settings={'help_option_names': ['-h', '--help']}) +@click.group(context_settings=context_settings) @click.version_option(get_version(), '-V', '--version', prog_name='covimerage') @click.option('-v', '--verbose', count=True, help='Increase verbosity.') @click.option('-q', '--quiet', count=True, help='Decrease verbosity.') @@ -63,6 +65,7 @@ def write_coverage(profile_file, data_file, source, append): @main.command(context_settings=dict( + context_settings, # ignore_unknown_options=True, allow_interspersed_args=False, )) diff --git a/setup.py b/setup.py index 30997d7e..a9ba292f 100755 --- a/setup.py +++ b/setup.py @@ -73,7 +73,10 @@ def run(self): url='https://github.com/Vimjas/covimerage', packages=['covimerage'], entry_points={ - 'console_scripts': ['covimerage=covimerage.cli:main'], + 'console_scripts': [ + 'covimerage=covimerage.__main__:main', + 'covimerage-run=covimerage.__main__:run', + ], }, use_scm_version={ 'write_to': 'covimerage/__version__.py', diff --git a/tests/test_cli.py b/tests/test_cli.py index b39fe9e7..5cbfccf1 100644 --- a/tests/test_cli.py +++ b/tests/test_cli.py @@ -15,7 +15,7 @@ def test_dunder_main_run(capfd): assert call([sys.executable, '-m', 'covimerage']) == 0 out, err = capfd.readouterr() - assert out.startswith('Usage: __main__') + assert out.startswith('Usage: covimerage') def test_dunder_main_run_help(capfd): @@ -61,6 +61,12 @@ def test_cli_help(arg, runner): assert result.exit_code == 0 +def test_cli_run_shorthelp(runner): + result = runner.invoke(cli.run, ['-h']) + assert result.output.startswith('Usage:') + assert result.exit_code == 0 + + def test_cli_run_with_args_fd(capfd): ret = call(['covimerage', 'run', '--profile-file', '/doesnotexist', 'echo', '--', '--no-profile', '%sMARKER']) @@ -68,7 +74,7 @@ def test_cli_run_with_args_fd(capfd): lines = err.splitlines() assert lines == [ "Running cmd: echo -- --no-profile %sMARKER --cmd 'profile start /doesnotexist' --cmd 'profile! file ./*' (in {})".format(os.getcwd()), - 'Error: The profile file (/doesnotexist) has not been created.'] + 'covimerage: error: The profile file (/doesnotexist) has not been created.'] assert ret == 1 @@ -295,14 +301,14 @@ def test_cli_call(capfd): # click after 6.7 (9cfea14) includes: 'Try "covimerage --help" for help.' assert err_lines[-2:] == [ '', - 'Error: No such command "file not found".'] + 'covimerage: error: No such command "file not found".'] assert out == '' assert call(['covimerage', 'write_coverage', 'file not found']) == 2 out, err = capfd.readouterr() err_lines = err.splitlines() assert err_lines[-1] == ( - 'Error: Invalid value for "%s": Could not open file: file not found: No such file or directory' % ( + 'covimerage: error: Invalid value for "%s": Could not open file: file not found: No such file or directory' % ( "profile_file" if click.__version__ < '7.0' else "[PROFILE_FILE]...",)) assert out == '' @@ -313,7 +319,7 @@ def test_cli_call_verbosity_fd(capfd): assert out == '' assert err.splitlines() == [ 'Not writing coverage file: no data to report!', - 'Error: No data to report.'] + 'covimerage: error: No data to report.'] assert call(['covimerage', '-v', 'write_coverage', os.devnull]) == 1 out, err = capfd.readouterr() @@ -322,7 +328,7 @@ def test_cli_call_verbosity_fd(capfd): 'Parsing file: /dev/null', 'source_files: []', 'Not writing coverage file: no data to report!', - 'Error: No data to report.'] + 'covimerage: error: No data to report.'] assert call(['covimerage', '-vvvv', 'write_coverage', os.devnull]) == 1 out, err = capfd.readouterr() @@ -331,19 +337,19 @@ def test_cli_call_verbosity_fd(capfd): 'Parsing file: /dev/null', 'source_files: []', 'Not writing coverage file: no data to report!', - 'Error: No data to report.'] + 'covimerage: error: No data to report.'] assert call(['covimerage', '-vq', 'write_coverage', os.devnull]) == 1 out, err = capfd.readouterr() assert out == '' assert err.splitlines() == [ 'Not writing coverage file: no data to report!', - 'Error: No data to report.'] + 'covimerage: error: No data to report.'] assert call(['covimerage', '-qq', 'write_coverage', os.devnull]) == 1 out, err = capfd.readouterr() assert out == '' - assert err == 'Error: No data to report.\n' + assert err == 'covimerage: error: No data to report.\n' def test_cli_writecoverage_without_data(runner): @@ -641,7 +647,7 @@ def test_run_handles_exit_code_from_python_fd(capfd): ret = call(['covimerage', 'run', 'python', '-c', 'print("output"); import sys; sys.exit(42)']) out, err = capfd.readouterr() - assert 'Error: Command exited non-zero: 42.' in err.splitlines() + assert 'covimerage: error: Command exited non-zero: 42.' in err.splitlines() assert out == 'output\n' assert ret == 42 @@ -652,7 +658,7 @@ def test_run_handles_exit_code_from_python_pty_fd(capfd): "import pty; pty.spawn(['/bin/sh', '-c', " "'printf output; exit 42'])"]) out, err = capfd.readouterr() - assert ('Error: The profile file (/not/used) has not been created.' in + assert ('covimerage: error: The profile file (/not/used) has not been created.' in err.splitlines()) assert out == 'output' assert ret == 1