implement scrapy + pygea job runner

This commit is contained in:
Abel Luck 2026-03-30 15:04:41 +02:00
parent 916968c579
commit 8af28c2f68
8 changed files with 888 additions and 163 deletions

View file

@ -1,8 +1,10 @@
import sys
from pathlib import Path
from types import SimpleNamespace
import pytest
from repub import media
from repub.config import (
FeedConfig,
RepublisherConfig,
@ -48,3 +50,141 @@ def test_pipeline_from_crawler_uses_configured_store(
assert pipeline.settings is crawler.settings
assert pipeline.store.basedir == crawler.settings[store_setting]
def test_transcode_audio_captures_ffmpeg_output(monkeypatch, tmp_path: Path) -> None:
input_file = tmp_path / "input.mp3"
input_file.write_bytes(b"12345")
output_dir = tmp_path / "audio-out"
output_dir.mkdir()
run_calls: list[dict[str, object]] = []
class FakeOutput:
def __init__(self, output_path: Path):
self.output_path = output_path
def run(self, **kwargs):
run_calls.append(kwargs)
self.output_path.write_bytes(b"12")
return b"", b""
class FakeInput:
def output(self, output_file: str, **params):
del params
return FakeOutput(Path(output_file))
monkeypatch.setattr(media.ffmpeg, "input", lambda _: FakeInput())
result = media.transcode_audio(
str(input_file),
str(output_dir),
{"extension": "mp3", "acodec": "libmp3lame"},
)
assert result == str(output_dir / "converted.mp3")
assert run_calls == [{"capture_stdout": True, "capture_stderr": True}]
def test_transcode_video_two_pass_does_not_print_ffmpeg_output(
monkeypatch, tmp_path: Path
) -> None:
input_file = tmp_path / "input.mp4"
input_file.write_bytes(b"12345")
output_dir = tmp_path / "video-out"
output_dir.mkdir()
run_calls: list[dict[str, object]] = []
printed: list[tuple[tuple[object, ...], dict[str, object]]] = []
class FakeOutput:
def __init__(self, output_path: Path | None):
self.output_path = output_path
def global_args(self, *args):
del args
return self
def run(self, **kwargs):
run_calls.append(kwargs)
if self.output_path is not None:
self.output_path.write_bytes(b"12")
return b"pass-out", b"pass-err"
class FakeInput:
video = object()
audio = object()
def output(self, *args, **params):
del params
output_path = next(
(
Path(arg)
for arg in args
if isinstance(arg, str) and arg.endswith(".mp4")
),
None,
)
return FakeOutput(output_path)
monkeypatch.setattr(media.ffmpeg, "input", lambda _: FakeInput())
monkeypatch.setattr(
"builtins.print", lambda *args, **kwargs: printed.append((args, kwargs))
)
result = media.transcode_video(
str(input_file),
str(output_dir),
{
"extension": "mp4",
"passes": [
{"f": "null"},
{"c:v": "libx264"},
],
},
)
assert result == str(output_dir / "converted.mp4")
assert run_calls == [
{"capture_stdout": True, "capture_stderr": True},
{
"capture_stdout": True,
"capture_stderr": True,
"overwrite_output": True,
},
]
assert printed == []
def test_transcode_video_prints_ffmpeg_output_on_error(
monkeypatch, tmp_path: Path
) -> None:
input_file = tmp_path / "input.mp4"
input_file.write_bytes(b"12345")
output_dir = tmp_path / "video-out"
output_dir.mkdir()
printed: list[tuple[str, bool]] = []
class FakeOutput:
def run(self, **kwargs):
del kwargs
raise media.ffmpeg.Error("ffmpeg", b"video-stdout", b"video-stderr")
class FakeInput:
def output(self, *args, **params):
del args, params
return FakeOutput()
def fake_print(*args, **kwargs):
printed.append((str(args[0]), kwargs.get("file") is sys.stderr))
monkeypatch.setattr(media.ffmpeg, "input", lambda _: FakeInput())
monkeypatch.setattr("builtins.print", fake_print)
with pytest.raises(RuntimeError):
media.transcode_video(
str(input_file),
str(output_dir),
{"extension": "mp4", "c:v": "libx264"},
)
assert ("video-stderr", True) in printed
assert ("video-stdout", False) in printed