Skip to content
Snippets Groups Projects
Commit 72aea6d5 authored by David Douard's avatar David Douard
Browse files

cli: add a new 'backend' cli group to list and document backends

Adds a new 'backend' cli group with a 'list' command.

Example:

  $ swh backend list vault

  memory     Stub vault backend, for use in the CLI.
  postgresql Backend for the Software Heritage Vault.
  remote     Client to the Software Heritage vault cache.

  $ swh backend list vault memory
  vault:memory

  Stub vault backend, for use in the CLI.
parent 1a818dbe
No related branches found
Tags v3.6.1
1 merge request!397cli: add a new 'backend' cli group to list and document backends
Pipeline #11803 failed
......@@ -39,6 +39,7 @@ testing = {file = [
[project.entry-points."swh.cli.subcommands"]
"swh.core.db" = "swh.core.cli.db"
"swh.core.backend" = "swh.core.cli.backend"
[project.entry-points.pytest11]
"pytest_swh_core" = "swh.core.pytest_plugin"
......
#!/usr/bin/env python3
# Copyright (C) 2024 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 logging
from os import get_terminal_size
import click
from swh.core.cli import CONTEXT_SETTINGS
from swh.core.cli import swh as swh_cli_group
logger = logging.getLogger(__name__)
@swh_cli_group.group(name="backend", context_settings=CONTEXT_SETTINGS)
@click.pass_context
def backend(ctx):
"""Software Heritage backend generic tools."""
pass
@backend.command(name="list", context_settings=CONTEXT_SETTINGS)
@click.argument("package", required=True)
@click.argument("cls", required=False, default=None)
@click.pass_context
def bk_list(ctx, package, cls):
"""Show registered backends for the given package
With their documentation, if any. Example::
\b
$ swh backend list vault
memory Stub vault backend, for use in the CLI.
postgresql Backend for the Software Heritage Vault.
remote Client to the Software Heritage vault cache.
If 'cls' is given, display the full docstring for the corresponding
backend.
Example::
\b
$ swh backend list vault memory
vault:memory
Stub vault backend, for use in the CLI.
"""
from swh.core.config import get_swh_backend_module, list_swh_backends
if cls is None:
items = []
for backend in list_swh_backends(package):
_, BackendCls = get_swh_backend_module(package, backend)
msg = BackendCls.__doc__
if msg is None:
msg = ""
msg = msg.strip()
if "\n" in msg:
firstline = msg.splitlines()[0]
else:
firstline = msg
items.append((backend, firstline, msg))
if not items:
click.secho(
f"No backend found for package '{package}'",
fg="red",
bold=True,
err=True,
)
raise click.Abort()
max_name = max(len(name) for name, _, _ in items)
try:
width = get_terminal_size().columns
except OSError:
width = 78
for name, firstline, msg in items:
click.echo(
click.style(
f"{name:<{max_name + 1}}",
fg="green",
bold=True,
),
nl=False,
)
firstline = firstline[: width - max_name - 1]
click.echo(firstline)
else:
try:
_, BackendCls = get_swh_backend_module(package, cls)
except ValueError:
BackendCls = None
if BackendCls is None:
click.secho(
f"No backend '{cls}' found for package '{package}'",
fg="red",
bold=True,
err=True,
)
raise click.Abort()
click.echo(
click.style(
package,
fg="green",
bold=True,
)
+ ":"
+ click.style(
cls,
fg="yellow",
bold=True,
)
+ "\n",
)
click.echo(BackendCls.__doc__.strip())
......@@ -373,6 +373,13 @@ def get_swh_backend_from_fullmodule(
return None, None
def list_swh_backends(package: str) -> List[str]:
if package.startswith("swh."):
package = package[4:]
entry_points = get_entry_points(group=f"swh.{package}.classes")
return [ep.name for ep in entry_points]
def list_db_config_entries(cfg) -> Generator[Tuple[str, str, dict, str], None, None]:
"""List all the db config entries in the given config structure
......
......@@ -471,7 +471,7 @@ def mock_get_entry_points(request, mocker, datadir, mock_import_module):
pkgdir = Path(datadir) / package
if pkgdir.is_dir():
for entry in pkgdir.iterdir():
if entry.is_dir():
if not entry.name.startswith("_") and entry.is_dir():
ep = mock(
module=f"swh.{package}.{entry.name}",
load=lambda: mock(
......
# Copyright (C) 2024 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
from click.testing import CliRunner
import pytest
from swh.core.tests.test_cli import assert_result
@pytest.fixture
def swhmain(swhmain):
from swh.core.cli.backend import backend as swhbackend
swhmain.add_command(swhbackend)
return swhmain
def test_backend_list_ok(swhmain, mock_get_entry_points):
runner = CliRunner()
result = runner.invoke(swhmain, ["backend", "list", "test"])
assert_result(result)
assert result.output.strip() == "backend1 A mockup backend for tests"
def test_backend_list_empty(swhmain, mock_get_entry_points):
runner = CliRunner()
result = runner.invoke(swhmain, ["backend", "list", "wrong_package"])
assert result.exit_code == 1
assert "No backend found for package 'wrong_package'" in result.output.strip()
def test_backend_list_cls_ok(swhmain, mock_get_entry_points):
runner = CliRunner()
result = runner.invoke(swhmain, ["backend", "list", "test", "backend1"])
assert_result(result)
assert result.output.strip() == "test:backend1\n\nA mockup backend for tests"
def test_backend_list_cls_no_package(swhmain, mock_get_entry_points):
runner = CliRunner()
result = runner.invoke(swhmain, ["backend", "list", "wrong_package", "backend1"])
assert result.exit_code == 1
assert (
"No backend 'backend1' found for package 'wrong_package'"
in result.output.strip()
)
def test_backend_list_cls_no_backend(swhmain, mock_get_entry_points):
runner = CliRunner()
result = runner.invoke(swhmain, ["backend", "list", "test", "backend2"])
assert result.exit_code == 1
assert "No backend 'backend2' found for package 'test'" in result.output.strip()
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment