mirror of
https://github.com/unshackle-dl/unshackle.git
synced 2026-11-12 20:15:10 +00:00
108 lines
4.5 KiB
Python
108 lines
4.5 KiB
Python
"""``services.<TAG>.dl`` ``remote`` and ``server`` route a service without ``--remote``. Explicit CLI values win."""
|
|
|
|
from __future__ import annotations
|
|
|
|
from typing import Any, Optional, cast
|
|
|
|
import click
|
|
import pytest
|
|
|
|
from unshackle.commands.dl import dl
|
|
from unshackle.commands.search import search
|
|
from unshackle.core.config import config
|
|
from unshackle.core.services import Services
|
|
|
|
|
|
def make_ctx(
|
|
command: click.Command, args: Optional[list[str]] = None, default_map: Optional[dict[str, Any]] = None
|
|
) -> click.Context:
|
|
"""Parse the group options of a real ``Services`` command, without running its callback."""
|
|
return command.make_context(
|
|
command.name or "dl", [*(args or []), "EXAMPLE", "title"], default_map=default_map or {}
|
|
)
|
|
|
|
|
|
def group(ctx: click.Context) -> Services:
|
|
return cast(Services, ctx.command)
|
|
|
|
|
|
@pytest.fixture
|
|
def routed(monkeypatch: pytest.MonkeyPatch) -> list[tuple[str, Optional[str]]]:
|
|
"""Record the path get_command takes and the server it passes, without loading a service or calling a server."""
|
|
calls: list[tuple[str, Optional[str]]] = []
|
|
|
|
def remote(name: str, server_name: Optional[str]) -> click.Command:
|
|
calls.append(("remote", server_name))
|
|
return click.Command(name)
|
|
|
|
def local(tag: str) -> Any:
|
|
calls.append(("local", None))
|
|
return type("FakeService", (), {"cli": click.Command(tag)})
|
|
|
|
monkeypatch.setattr(Services, "make_remote_command", staticmethod(remote))
|
|
monkeypatch.setattr(Services, "load", staticmethod(local))
|
|
return calls
|
|
|
|
|
|
@pytest.mark.parametrize("command", [dl.cli, search])
|
|
def test_service_remote_routes_to_remote_command(
|
|
monkeypatch: pytest.MonkeyPatch, routed: list[tuple[str, Optional[str]]], command: click.Command
|
|
) -> None:
|
|
"""The typed name matches the config key in any case, as a service only the server has keeps the typed case."""
|
|
monkeypatch.setattr(config, "services", {"EXAMPLE": {"dl": {"remote": True, "server": "box"}}})
|
|
ctx = make_ctx(command)
|
|
group(ctx).resolve_command(ctx, ["example", "title"])
|
|
assert routed == [("remote", "box")]
|
|
assert ctx.params["remote"] is True
|
|
assert ctx.params["server"] == "box"
|
|
|
|
|
|
@pytest.mark.parametrize(
|
|
("services", "args", "default_map", "expected"),
|
|
[
|
|
({"OTHER": {"dl": {"remote": True}}}, [], None, ("local", None)),
|
|
({"EXAMPLE": {"dl": {"remote": True, "server": "box"}}}, ["--server", "other"], None, ("remote", "other")),
|
|
({"EXAMPLE": {"dl": {"remote": False}}}, [], {"remote": True}, ("local", None)),
|
|
({"EXAMPLE": {"dl": {"remote": "false"}}}, [], None, ("local", None)),
|
|
({"EXAMPLE": {"dl": {"remote": True}}}, ["--local"], {"remote": True}, ("local", None)),
|
|
],
|
|
ids=["other-service", "cli-server-wins", "service-false-beats-global", "quoted-false-is-cast", "cli-local-wins"],
|
|
)
|
|
def test_routing_precedence(
|
|
monkeypatch: pytest.MonkeyPatch,
|
|
routed: list,
|
|
services: dict,
|
|
args: list[str],
|
|
default_map: Optional[dict[str, Any]],
|
|
expected: tuple[str, Optional[str]],
|
|
) -> None:
|
|
monkeypatch.setattr(config, "services", services)
|
|
ctx = make_ctx(dl.cli, args, default_map)
|
|
group(ctx).get_command(ctx, "EXAMPLE")
|
|
assert routed == [expected]
|
|
|
|
|
|
def test_invalid_value_names_the_config_key(monkeypatch: pytest.MonkeyPatch, routed: list) -> None:
|
|
monkeypatch.setattr(config, "services", {"EXAMPLE": {"dl": {"remote": "maybe"}}})
|
|
ctx = make_ctx(dl.cli)
|
|
with pytest.raises(click.ClickException, match=r"services\.EXAMPLE\.dl\.remote"):
|
|
group(ctx).get_command(ctx, "EXAMPLE")
|
|
|
|
|
|
def test_resolved_service_does_not_route_the_next(monkeypatch: pytest.MonkeyPatch, routed: list) -> None:
|
|
"""Help and shell completion call get_command for every service on the context that resolved one."""
|
|
monkeypatch.setattr(config, "services", {"EXAMPLE": {"dl": {"remote": True}}})
|
|
ctx = make_ctx(dl.cli)
|
|
group(ctx).resolve_command(ctx, ["EXAMPLE", "title"])
|
|
assert ctx.params["remote"] is True
|
|
group(ctx).get_command(ctx, "OTHER")
|
|
assert routed == [("remote", None), ("local", None)]
|
|
|
|
|
|
def test_import_ignores_service_remote(monkeypatch: pytest.MonkeyPatch) -> None:
|
|
monkeypatch.setattr(config, "services", {"EXAMPLE": {"dl": {"remote": True}}})
|
|
monkeypatch.setattr(Services, "make_import_command", staticmethod(lambda tag, ctx: click.Command(tag)))
|
|
ctx = make_ctx(dl.cli, ["--import", "export.json"])
|
|
group(ctx).resolve_command(ctx, ["EXAMPLE", "title"])
|
|
assert ctx.params["remote"] is False
|