diff --git a/swh/core/cli/__init__.py b/swh/core/cli/__init__.py --- a/swh/core/cli/__init__.py +++ b/swh/core/cli/__init__.py @@ -14,16 +14,34 @@ logger = logging.getLogger(__name__) -@click.group(context_settings=CONTEXT_SETTINGS) +class AliasedGroup(click.Group): + 'A simple Group that supports command aliases' + + @property + def aliases(self): + if not hasattr(self, '_aliases'): + self._aliases = {} + return self._aliases + + def get_command(self, ctx, cmd_name): + return super().get_command(ctx, self.aliases.get(cmd_name, cmd_name)) + + def add_alias(self, name, alias): + if not isinstance(name, str): + name = name.name + self.aliases[alias] = name + + +@click.group(context_settings=CONTEXT_SETTINGS, cls=AliasedGroup) @click.option('--log-level', '-l', default='INFO', type=click.Choice(LOG_LEVEL_NAMES), help="Log level (default to INFO)") @click.pass_context def swh(ctx, log_level): - """Command line interface for Software Heritage + """Command line interface for Software Heritage. """ log_level = logging.getLevelName(log_level) - logger.setLevel(log_level) + logging.root.setLevel(log_level) ctx.ensure_object(dict) ctx.obj['log_level'] = log_level diff --git a/swh/core/tests/test_cli.py b/swh/core/tests/test_cli.py new file mode 100644 --- /dev/null +++ b/swh/core/tests/test_cli.py @@ -0,0 +1,109 @@ +# + +import logging + +import click +from click.testing import CliRunner + +from swh.core.cli import swh as swhmain + + +help_msg = '''Usage: swh [OPTIONS] COMMAND [ARGS]... + + Command line interface for Software Heritage. + +Options: + -l, --log-level [NOTSET|DEBUG|INFO|WARNING|ERROR|CRITICAL] + Log level (default to INFO) + -h, --help Show this message and exit. +''' + + +def test_swh_help(): + runner = CliRunner() + result = runner.invoke(swhmain, ['-h']) + assert result.exit_code == 0 + assert result.output == help_msg + + result = runner.invoke(swhmain, ['--help']) + assert result.exit_code == 0 + assert result.output == help_msg + + +def test_command(): + @swhmain.command(name='test') + @click.pass_context + def swhtest(ctx): + click.echo('Hello SWH!') + + runner = CliRunner() + result = runner.invoke(swhmain, ['test']) + assert result.exit_code == 0 + assert result.output.strip() == 'Hello SWH!' + + +def test_loglevel_default(caplog): + @swhmain.command(name='test') + @click.pass_context + def swhtest(ctx): + assert logging.root.level == 20 + click.echo('Hello SWH!') + + runner = CliRunner() + result = runner.invoke(swhmain, ['test']) + assert result.exit_code == 0 + print(result.output) + assert result.output.strip() == '''Hello SWH!''' + + +def test_loglevel_error(caplog): + @swhmain.command(name='test') + @click.pass_context + def swhtest(ctx): + assert logging.root.level == 40 + click.echo('Hello SWH!') + + runner = CliRunner() + result = runner.invoke(swhmain, ['-l', 'ERROR', 'test']) + assert result.exit_code == 0 + assert result.output.strip() == '''Hello SWH!''' + + +def test_loglevel_debug(caplog): + @swhmain.command(name='test') + @click.pass_context + def swhtest(ctx): + assert logging.root.level == 10 + click.echo('Hello SWH!') + + runner = CliRunner() + result = runner.invoke(swhmain, ['-l', 'DEBUG', 'test']) + assert result.exit_code == 0 + assert result.output.strip() == '''Hello SWH!''' + + +def test_aliased_command(): + @swhmain.command(name='canonical-test') + @click.pass_context + def swhtest(ctx): + 'A test command.' + click.echo('Hello SWH!') + swhmain.add_alias(swhtest, 'othername') + + runner = CliRunner() + + # check we have only 'canonical-test' listed in the usage help msg + result = runner.invoke(swhmain, ['-h']) + assert result.exit_code == 0 + assert 'canonical-test A test command.' in result.output + assert 'othername' not in result.output + + # check we can execute the cmd with 'canonical-test' + result = runner.invoke(swhmain, ['canonical-test']) + assert result.exit_code == 0 + assert result.output.strip() == '''Hello SWH!''' + + # check we can also execute the cmd with the alias 'othername' + result = runner.invoke(swhmain, ['othername']) + assert result.exit_code == 0 + assert result.output.strip() == '''Hello SWH!'''