feat(download_imageset): Use tricklebar for download when possible
This commit is contained in:
1 parent
50ea658fc7
commit
afdb0ac636
2 files changed
+155
-8
No files matched your search
@@ -6,7 +6,10 @@
|
||||
import shutil
|
||||
import subprocess
|
||||
import sys
|
||||
import threading
|
||||
import urllib.parse
|
||||
import zipfile
|
||||
from concurrent.futures import ThreadPoolExecutor
|
||||
from pathlib import Path
|
||||
from functools import partial
|
||||
from unittest.mock import Mock
|
||||
@@ -330,6 +333,7 @@ def test_filehost_resumes_unfinished_downloads(
|
||||
)),
|
||||
)
|
||||
run_command = Mock()
|
||||
monkeypatch.setattr(download_imageset, "_TRICKLEBAR_APP", tmp_path / "missing.app")
|
||||
monkeypatch.setattr(download_imageset, "run_command", run_command)
|
||||
monkeypatch.setattr(download_imageset, "process_imageset", Mock())
|
||||
|
||||
@@ -350,6 +354,97 @@ def test_filehost_resumes_unfinished_downloads(
|
||||
run_command.assert_not_called()
|
||||
|
||||
|
||||
def test_aria2_download_failure_propagates(monkeypatch: pytest.MonkeyPatch) -> None:
|
||||
failure = subprocess.CalledProcessError(returncode=1, cmd="aria2c")
|
||||
monkeypatch.setattr(download_imageset, "run_command", Mock(side_effect=failure))
|
||||
|
||||
with pytest.raises(subprocess.CalledProcessError):
|
||||
download_imageset.download_url_with_aria2(
|
||||
url="https://example.com/archive.zip", destination=Path("archive.zip")
|
||||
)
|
||||
|
||||
|
||||
@pytest.mark.parametrize(
|
||||
("status", "file_state", "error"),
|
||||
[
|
||||
("complete", "valid", None),
|
||||
("error", "valid", "download failed"),
|
||||
("complete", "missing", "without a downloaded file"),
|
||||
("complete", "wrong_path", "instead of"),
|
||||
("complete", "unfinished", "download is unfinished"),
|
||||
],
|
||||
)
|
||||
def test_tricklebar_waits_for_callback(
|
||||
tmp_path: Path, monkeypatch: pytest.MonkeyPatch,
|
||||
status: str, file_state: str, error: str | None,
|
||||
) -> None:
|
||||
destination = tmp_path / "download & photos.zip"
|
||||
downloaded_path = tmp_path / "wrong.zip" if file_state == "wrong_path" else destination
|
||||
if file_state != "missing":
|
||||
downloaded_path.write_bytes(data=b"downloaded archive")
|
||||
if file_state == "unfinished":
|
||||
destination.with_name(f"{destination.name}.aria2").touch()
|
||||
url = "https://example.com/photos.zip?token=a+b&other=value"
|
||||
opened = threading.Event()
|
||||
callback_paths: list[Path] = []
|
||||
|
||||
def open_download(args: list[str]) -> None:
|
||||
assert args[0] == "open"
|
||||
parsed = urllib.parse.urlparse(url=args[1])
|
||||
assert "+" not in parsed.query
|
||||
assert parsed.scheme == "tricklebar"
|
||||
assert parsed.netloc == "add-download"
|
||||
query = urllib.parse.parse_qs(qs=parsed.query)
|
||||
assert query["url"] == [url]
|
||||
assert query["dir"] == [str(destination.parent)]
|
||||
assert query["out"] == [destination.name]
|
||||
assert query["continue"] == ["true"]
|
||||
callback_paths.append(Path(query["on_done"][0]))
|
||||
opened.set()
|
||||
|
||||
monkeypatch.setattr(download_imageset, "run_command", open_download)
|
||||
|
||||
with ThreadPoolExecutor(max_workers=1) as executor:
|
||||
download = executor.submit(
|
||||
download_imageset.download_url_with_tricklebar, url=url, destination=destination
|
||||
)
|
||||
assert opened.wait(timeout=5)
|
||||
assert not download.done()
|
||||
callback = callback_paths[0]
|
||||
subprocess.run(args=[str(callback), status, str(downloaded_path), "gid", url], check=True)
|
||||
if error is None:
|
||||
assert download.result(timeout=5) is None
|
||||
else:
|
||||
with pytest.raises(download_imageset.click.ClickException, match=error):
|
||||
download.result(timeout=5)
|
||||
|
||||
assert not callback.parent.exists()
|
||||
|
||||
|
||||
@pytest.mark.parametrize("installed", [False, True])
|
||||
def test_download_selects_backend(
|
||||
tmp_path: Path, monkeypatch: pytest.MonkeyPatch, installed: bool
|
||||
) -> None:
|
||||
application = tmp_path / "TrickleBar.app"
|
||||
if installed:
|
||||
application.mkdir()
|
||||
monkeypatch.setattr(download_imageset, "_TRICKLEBAR_APP", application)
|
||||
aria2 = Mock()
|
||||
tricklebar = Mock()
|
||||
monkeypatch.setattr(download_imageset, "download_url_with_aria2", aria2)
|
||||
monkeypatch.setattr(download_imageset, "download_url_with_tricklebar", tricklebar)
|
||||
destination = tmp_path / "photos" / "album.zip"
|
||||
url = "https://example.com/album.zip"
|
||||
|
||||
download_imageset.download_url(url=url, destination=destination)
|
||||
|
||||
assert destination.parent.is_dir()
|
||||
selected = tricklebar if installed else aria2
|
||||
unused = aria2 if installed else tricklebar
|
||||
selected.assert_called_once_with(url=url, destination=destination.resolve())
|
||||
unused.assert_not_called()
|
||||
|
||||
|
||||
@pytest.mark.parametrize("process_directory", [False, True])
|
||||
def test_process_skips_unfinished_archive(
|
||||
tmp_path: Path,
|
||||
|
||||
Reference in new issue
Block a user