mirror of
https://github.com/unshackle-dl/unshackle.git
synced 2026-06-11 11:42:06 +00:00
Replace the class-level Track.download monkeypatch with a per-job progress sink threaded through dl.result(). The API now reports a single aggregate signal instead of each track's bouncing 0-100%:
- bitrate-weighted completion so video/audio dominate subtitles
- completed_tracks/total_tracks counts and active_tracks labels (e.g. "video 2160p DV", "audio en-US 5.1")
- downloads fill 0-90%; repackaging (when needed) and a "muxing" stage carry it to 100% so post-download work is no longer frozen at 100%
- monotonic throughout (handles the download->decrypt callable reuse)
Also:
- accept "HDR10P" as the canonical API range value ("HDR10+" still works)
- declare AUTH_METHODS opt-in on the Service base
- raise typed APIError (WORKER_ERROR/DOWNLOAD_ERROR) from the worker path
- move the progress helpers to unshackle/core/api/progress.py
tests/remote/
Test suite for the unshackle remote-services subsystem:
unshackle/core/remote_service.py—RemoteClient,RemoteService, helpersunshackle/core/api/— routes, handlers, session_store, input_bridge, download_manager, errors, compressionunshackle/commands/serve.py— CLI surface
Two tiers:
| Tier | Where | Network | Default |
|---|---|---|---|
| unit | tests/remote/unit/ |
mocked (responses, in-process aiohttp) |
runs by default |
| e2e | tests/remote/e2e/ |
hits an unshackle serve instance |
skipped unless --live |
Install test deps
uv sync --group test
Run unit tests
uv run pytest tests/remote/unit -v
Fast, hermetic, no external calls.
Run e2e tests
The suite can either:
- Spawn its own serve (default with
--live): startsuv run unshackle serve --host 127.0.0.1 --port <free> --no-key --remote-onlyfor the session, waits for/api/health, tears it down at the end. - Talk to an external serve you started in another shell: pass
--server-url http://host:port.
Spawn mode is controlled by --spawn-serve {auto, always, never} (default
auto — spawn only when --server-url is empty).
Auto-spawn (recommended)
uv run pytest tests/remote/e2e -v --live
External serve
# in shell A
uv run unshackle serve --host 0.0.0.0 --no-key --remote-only
# in shell B
uv run pytest tests/remote/e2e -v --live --server-url http://localhost:8786
With API key
uv run pytest tests/remote/e2e -v --live --secret-key your-key
Limit which services run
uv run pytest tests/remote/e2e -v --live --services FOO,BAR
Configure e2e scenarios
Copy tests/remote/e2e/fixtures/fixtures-example.yaml to
tests/remote/e2e/fixtures/fixtures.yaml (gitignored) and fill in the
services you have access to. Schema (see the example file for full docs):
services:
EXAMPLE:
title_url: "..." # required
series_url: "..." # optional — overrides movie target when set
target_season: 1
target_episode: 1
search_query: "..."
expected_quality:
min_height: 1080
min_codecs: [AVC]
min_ranges: [SDR]
min_track_count: 4
runs_download_test: true # opt in to the download smoke test
runs_license_test: false # opt in to the license test
license_drm: widevine # or "playready"
license_quality: 1080
Tests skip a service if its session can't be created (auth missing,
geofence, etc.) or if the matching runs_*_test flag is false.
Run everything
uv run pytest tests/remote -v --live
CLI flags added
| Flag | Default | Purpose |
|---|---|---|
--live |
off | Opt in to e2e tests |
--server-url URL |
"" (or $UNSHACKLE_SERVE_URL) |
Target external server; empty triggers auto-spawn |
--spawn-serve {auto,always,never} |
auto |
Spawn serve when no URL given |
--secret-key KEY |
"" (or $UNSHACKLE_SECRET_KEY) |
X-Secret-Key header |
--services A,B |
(all) | Restrict e2e to these tags |
Markers
unit— fast, mocked (default)live— needs--liveslow— hits real services; combine with--live
Run only fast unit tests:
uv run pytest tests/remote -m "unit and not slow"
Adding a new service to e2e
- Add a block under
services:in your localfixtures.yaml. - No new Python needed — every e2e test is parametrized over the YAML.