From ef75ea7d7a9e715c3ae747ef3544ad611d327cf6 Mon Sep 17 00:00:00 2001 From: imSp4rky Date: Mon, 19 Oct 2026 14:25:03 -0600 Subject: [PATCH] feat(dl): add --local to override a remote: true service config --- docs/dev/rest-api/remote-sessions.md | 3 ++- docs/guide/cli-reference.md | 2 ++ docs/reference/configuration/services.md | 2 +- tests/core/test_service_remote_config.py | 3 ++- unshackle/commands/dl.py | 5 ++--- unshackle/commands/search.py | 5 ++--- 6 files changed, 11 insertions(+), 9 deletions(-) diff --git a/docs/dev/rest-api/remote-sessions.md b/docs/dev/rest-api/remote-sessions.md index b7951a9e..54c00664 100644 --- a/docs/dev/rest-api/remote-sessions.md +++ b/docs/dev/rest-api/remote-sessions.md @@ -114,7 +114,8 @@ services: ``` `unshackle dl EXAMPLE 0ABCDEF` and `unshackle search EXAMPLE "query"` then run on -`my_server`. A `--server` on the command line overrides the configured server. The global +`my_server`. A `--server` on the command line overrides the configured server, and `--local` +runs the local service code for that run. The global `dl: remote: true` makes every `dl` run remote, but it has no effect on `search`. The REST API ignores both settings: a job runs remote only when its request asks for it. diff --git a/docs/guide/cli-reference.md b/docs/guide/cli-reference.md index 35d737b1..5d986bfd 100644 --- a/docs/guide/cli-reference.md +++ b/docs/guide/cli-reference.md @@ -211,6 +211,7 @@ order the service used, then renumbers the episodes into the order you asked for | `--no-proxy-download` | Bypass the proxy for **all downloads** (manifest, licence, and auth stay proxied). | | `--proxy-download` | Use a different proxy for **all downloads**, in the same forms as `--proxy` (manifest, licence, and auth stay on `--proxy`). | | `--remote` | Use a remote unshackle server. | +| `--local` | Use the local service code, also when the config sets `remote: true`. | | `--server` | Name a remote server from the `remote_services` config. | ### Concurrency, caching & listing @@ -251,6 +252,7 @@ unshackle logs in to the service before the search. A service that declares a se | `--proxy` | Proxy URI, country or location code, or `provider:region` (e.g. `controld:ca`). | | `--no-proxy` | Force-disable all proxy use. | | `--remote` | Search on a remote unshackle server. The server logs in to the service. unshackle sends it your credentials, cookies and cache for the profile, and saves the cache that the server sends back. A service that searches with no login gets none of them. | +| `--local` | Search with the local service code, also when the config sets `remote: true` for the service. | | `--server` | Name a remote server from the `remote_services` config. | !!! example diff --git a/docs/reference/configuration/services.md b/docs/reference/configuration/services.md index 0d426bf4..6263f818 100644 --- a/docs/reference/configuration/services.md +++ b/docs/reference/configuration/services.md @@ -15,7 +15,7 @@ Per-service configuration, keyed by the canonical service tag (for example `EXAM - **`dl`**: per-service download defaults, using the same keys as the global [`dl`](download.md#dl) block. Set `remote: true` to send the `dl` and `search` runs of that service to a [remote server](#remote_services) without `--remote`. Add `server` to select one of - several servers. A `--server` on the command line overrides it. A REST API job ignores both keys. + several servers. On the command line, `--local` and `--server` override these keys. A REST API job ignores both keys. See [making a service remote by default](../../dev/rest-api/remote-sessions.md#making-a-service-remote-by-default). Individual services may read any additional keys they define. unshackle hands the merged result diff --git a/tests/core/test_service_remote_config.py b/tests/core/test_service_remote_config.py index 54d02839..19b1c970 100644 --- a/tests/core/test_service_remote_config.py +++ b/tests/core/test_service_remote_config.py @@ -64,8 +64,9 @@ def test_service_remote_routes_to_remote_command( ({"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"], + ids=["other-service", "cli-server-wins", "service-false-beats-global", "quoted-false-is-cast", "cli-local-wins"], ) def test_routing_precedence( monkeypatch: pytest.MonkeyPatch, diff --git a/unshackle/commands/dl.py b/unshackle/commands/dl.py index 6b404396..662b2e99 100644 --- a/unshackle/commands/dl.py +++ b/unshackle/commands/dl.py @@ -1218,11 +1218,10 @@ class dl: help="With -r HYBRID, make Dolby Vision from the HDR10+ metadata when a title has no Dolby Vision track.", ) @click.option( - "--remote", - is_flag=True, + "--remote/--local", default=False, is_eager=True, - help="Use a remote unshackle server instead of local service code.", + help="Use a remote unshackle server instead of local service code. --local overrides a remote: true config.", ) @click.option( "--server", diff --git a/unshackle/commands/search.py b/unshackle/commands/search.py index 86902e48..d475aaa1 100644 --- a/unshackle/commands/search.py +++ b/unshackle/commands/search.py @@ -40,11 +40,10 @@ from unshackle.core.utils.redact import mask_proxy ) @click.option("--no-proxy", is_flag=True, default=False, help="Force disable all proxy use.") @click.option( - "--remote", - is_flag=True, + "--remote/--local", default=False, is_eager=True, - help="Search on a remote unshackle server instead of with local service code.", + help="Search on a remote unshackle server instead of with local service code. --local overrides a remote: true config.", ) @click.option( "--server",