"""The backfill's own logic: what still needs doing, and what to skip.
Everything that actually fetches or writes is addon's, already covered by
test_subtitles.py. What is new here is deciding which of 226 library items still
need work -- and that decision is made against DISK, not against the work list,
because the list is a snapshot and a re-run must see what really happened.
Run: .venv/bin/python3 -m pytest test_backfill.py -q
"""
import json
import pytest
import backfill_subtitles as bf
@pytest.fixture
def movie(tmp_path):
d = tmp_path / "Some Film (1999) [tmdbid-1]"
d.mkdir()
f = d / "Some Film (1999).mkv"
f.write_bytes(b"video")
return {"kind": "movie", "name": "Some Film", "path": str(f),
"ident": "1", "season": 0, "episode": 0}
class TestNeedsWork:
def test_a_film_with_no_sidecar_needs_work(self, movie):
assert bf.needs_work(movie) is True
def test_a_film_that_already_has_one_does_not(self, movie, tmp_path):
d = tmp_path / "Some Film (1999) [tmdbid-1]"
(d / "Some Film (1999).en.srt").write_text("1\n")
assert bf.needs_work(movie) is False
def test_a_missing_media_file_is_not_work(self, movie):
movie["path"] = movie["path"].replace("Some Film", "Absent Film")
assert bf.needs_work(movie) is False
def test_a_subtitle_for_a_DIFFERENT_film_does_not_count(self, movie, tmp_path):
"""Season folders hold many episodes side by side, so 'some .srt exists
in this directory' is the wrong question -- it would skip every episode
after the first one that got subtitles."""
d = tmp_path / "Some Film (1999) [tmdbid-1]"
(d / "Another Film (2001).en.srt").write_text("1\n")
assert bf.needs_work(movie) is True
def test_an_episode_is_matched_on_its_own_stem(self, tmp_path):
season = tmp_path / "Season 01"
season.mkdir()
(season / "Show S01E01.mkv").write_bytes(b"v")
(season / "Show S01E02.mkv").write_bytes(b"v")
(season / "Show S01E01.en.srt").write_text("1\n")
e1 = {"path": str(season / "Show S01E01.mkv"), "ident": "9", "season": 1, "episode": 1}
e2 = {"path": str(season / "Show S01E02.mkv"), "ident": "9", "season": 1, "episode": 2}
assert bf.needs_work(e1) is False
assert bf.needs_work(e2) is True
def test_an_unreadable_folder_is_skipped_not_crashed(self, movie):
movie["path"] = "/definitely/not/here/film.mkv"
assert bf.needs_work(movie) is False
class TestLoadWork:
def test_entries_without_an_id_or_path_are_dropped(self, tmp_path):
p = tmp_path / "w.json"
p.write_text(json.dumps([
{"path": "/a.mkv", "ident": "1"},
{"path": "/b.mkv"},
{"ident": "3"},
{},
]))
assert len(bf.load_work(str(p))) == 1
def test_a_non_list_is_refused_rather_than_half_processed(self, tmp_path):
p = tmp_path / "w.json"
p.write_text(json.dumps({"not": "a list"}))
with pytest.raises(SystemExit):
bf.load_work(str(p))