diff --git a/swh/loader/cli.py b/swh/loader/cli.py index a2b341d..475506d 100644 --- a/swh/loader/cli.py +++ b/swh/loader/cli.py @@ -1,91 +1,91 @@ # Copyright (C) 2019 The Software Heritage developers # See the AUTHORS file at the top-level directory of this distribution # License: GNU General Public License version 3, or any later version # See top-level LICENSE file for more information import inspect import logging import click import pkg_resources from typing import Any from swh.core.cli import CONTEXT_SETTINGS from swh.scheduler.cli.utils import parse_options logger = logging.getLogger(__name__) LOADERS = { entry_point.name.split(".", 1)[1]: entry_point for entry_point in pkg_resources.iter_entry_points("swh.workers") if entry_point.name.split(".", 1)[0] == "loader" } -SUPPORTED_LOADERS = list(LOADERS) +SUPPORTED_LOADERS = sorted(list(LOADERS)) def get_loader(name: str, **kwargs) -> Any: """Given a loader name, instantiate it. Args: name: Loader's name kwargs: Configuration dict (url...) Returns: An instantiated loader """ if name not in LOADERS: raise ValueError( "Invalid loader %s: only supported loaders are %s" % (name, SUPPORTED_LOADERS) ) registry_entry = LOADERS[name].load()() logger.debug(f"registry: {registry_entry}") loader_cls = registry_entry["loader"] logger.debug(f"loader class: {loader_cls}") return loader_cls(**kwargs) @click.group(name="loader", context_settings=CONTEXT_SETTINGS) @click.pass_context def loader(ctx): """Loader cli tools """ pass @loader.command(name="run", context_settings=CONTEXT_SETTINGS) @click.argument("type", type=click.Choice(SUPPORTED_LOADERS)) @click.argument("url") @click.argument("options", nargs=-1) @click.pass_context def run(ctx, type, url, options): """Ingest with loader the origin located at """ (_, kw) = parse_options(options) logger.debug(f"kw: {kw}") loader = get_loader(type, url=url, **kw) result = loader.load() click.echo(result) @loader.command(name="list", context_settings=CONTEXT_SETTINGS) @click.argument("type", default="all", type=click.Choice(["all"] + SUPPORTED_LOADERS)) @click.pass_context def list(ctx, type): """List supported loaders and optionally their arguments""" if type == "all": loaders = ", ".join(SUPPORTED_LOADERS) click.echo(f"Supported loaders: {loaders}") else: registry_entry = LOADERS[type].load()() loader_cls = registry_entry["loader"] doc = inspect.getdoc(loader_cls).strip() signature = inspect.signature(loader_cls) click.echo(f"Loader: {doc}\nsignature: {signature}") diff --git a/swh/loader/tests/test_cli.py b/swh/loader/tests/test_cli.py index 3c8ac40..e002cdb 100644 --- a/swh/loader/tests/test_cli.py +++ b/swh/loader/tests/test_cli.py @@ -1,99 +1,111 @@ # Copyright (C) 2019 The Software Heritage developers # See the AUTHORS file at the top-level directory of this distribution # License: GNU General Public License version 3, or any later version # See top-level LICENSE file for more information import pytest from swh.loader.cli import run, list, get_loader, SUPPORTED_LOADERS from swh.loader.package.loader import PackageLoader +from click.formatting import HelpFormatter from click.testing import CliRunner def test_get_loader_wrong_input(swh_config): """Unsupported loader should raise """ loader_type = "unknown" assert loader_type not in SUPPORTED_LOADERS with pytest.raises(ValueError, match="Invalid loader"): get_loader(loader_type, url="db-url") def test_get_loader(swh_config): """Instantiating a supported loader should be ok """ loader_input = { "archive": {"url": "some-url", "artifacts": [],}, "debian": {"url": "some-url", "date": "something", "packages": [],}, "deposit": {"url": "some-url", "deposit_id": 1,}, "npm": {"url": "https://www.npmjs.com/package/onepackage",}, "pypi": {"url": "some-url",}, } for loader_type, kwargs in loader_input.items(): loader = get_loader(loader_type, **kwargs) assert isinstance(loader, PackageLoader) +def _write_usage(command, args, max_width=80): + hf = HelpFormatter(width=max_width) + hf.write_usage(command, args) + return hf.getvalue()[:-1] + + def test_run_help(swh_config): """Help message should be ok """ runner = CliRunner() result = runner.invoke(run, ["-h"]) assert result.exit_code == 0 - expected_help_msg = """Usage: run [OPTIONS] [archive|cran|debian|deposit|nixguix|npm|pypi] URL - [OPTIONS]... + usage_prefix = _write_usage( + "run", f"[OPTIONS] [{'|'.join(SUPPORTED_LOADERS)}] URL [OPTIONS]..." + ) + expected_help_msg = f"""{usage_prefix} Ingest with loader the origin located at Options: -h, --help Show this message and exit. -""" # noqa - +""" assert result.output.startswith(expected_help_msg) def test_run_pypi(mocker, swh_config): """Triggering a load should be ok """ mock_loader = mocker.patch("swh.loader.package.pypi.loader.PyPILoader") runner = CliRunner() result = runner.invoke(run, ["pypi", "https://some-url"]) assert result.exit_code == 0 mock_loader.assert_called_once_with(url="https://some-url") # constructor def test_list_help(mocker, swh_config): """Triggering a load should be ok """ runner = CliRunner() result = runner.invoke(list, ["--help"]) assert result.exit_code == 0 - expected_help_msg = """Usage: list [OPTIONS] [[all|archive|cran|debian|deposit|nixguix|npm|pypi]] + usage_prefix = _write_usage( + "list", f"[OPTIONS] [[{'|'.join(['all'] + SUPPORTED_LOADERS)}]]" + ) + expected_help_msg = f"""{usage_prefix} List supported loaders and optionally their arguments Options: -h, --help Show this message and exit. -""" # noqa +""" assert result.output.startswith(expected_help_msg) def test_list_help_npm(mocker, swh_config): """Triggering a load should be ok """ runner = CliRunner() result = runner.invoke(list, ["npm"]) assert result.exit_code == 0 - expected_help_msg = """Loader: Load npm origin's artifact releases into swh archive. + expected_help_msg = """ +Loader: Load npm origin's artifact releases into swh archive. signature: (url: str) -""" # noqa - assert result.output.startswith(expected_help_msg) +""" + assert result.output.startswith(expected_help_msg[1:])