179 lines
6.6 KiB
Python
179 lines
6.6 KiB
Python
"""Tests for ``alfred.infrastructure.subtitle.rule_repository.RuleSetRepository``.
|
|
|
|
Loads/saves the SubtitleRuleSet inheritance chain from ``.alfred/`` YAML.
|
|
|
|
Coverage:
|
|
|
|
- ``TestLoad`` — no files → ``global_default``; rules.yaml override applied
|
|
on top; release_groups/{NAME}.yaml override applied;
|
|
SubtitlePreferences seeds the base when provided; full 3-level chain.
|
|
- ``TestFilterOverride`` — unknown keys discarded.
|
|
- ``TestSaveLocal`` — atomic write, merges with existing, creates .alfred/.
|
|
"""
|
|
|
|
from __future__ import annotations
|
|
|
|
from pathlib import Path
|
|
|
|
import yaml
|
|
|
|
from alfred.infrastructure.persistence.memory.ltm.components.subtitle_preferences import (
|
|
SubtitlePreferences,
|
|
)
|
|
from alfred.infrastructure.subtitle.rule_repository import (
|
|
RuleSetRepository,
|
|
_filter_override,
|
|
)
|
|
|
|
|
|
def _write(path: Path, data: dict) -> None:
|
|
path.parent.mkdir(parents=True, exist_ok=True)
|
|
path.write_text(yaml.safe_dump(data), encoding="utf-8")
|
|
|
|
|
|
# --------------------------------------------------------------------------- #
|
|
# _filter_override #
|
|
# --------------------------------------------------------------------------- #
|
|
|
|
|
|
class TestFilterOverride:
|
|
def test_keeps_only_valid_keys(self):
|
|
out = _filter_override(
|
|
{
|
|
"languages": ["fra"],
|
|
"formats": ["srt"],
|
|
"types": ["standard"],
|
|
"format_priority": ["srt"],
|
|
"min_confidence": 0.8,
|
|
"unknown_key": "ignored",
|
|
"another": 42,
|
|
}
|
|
)
|
|
assert set(out) == {
|
|
"languages",
|
|
"formats",
|
|
"types",
|
|
"format_priority",
|
|
"min_confidence",
|
|
}
|
|
assert "unknown_key" not in out
|
|
|
|
def test_empty(self):
|
|
assert _filter_override({}) == {}
|
|
|
|
|
|
# --------------------------------------------------------------------------- #
|
|
# load #
|
|
# --------------------------------------------------------------------------- #
|
|
|
|
|
|
class TestLoad:
|
|
def test_no_files_returns_global_default(self, tmp_path):
|
|
repo = RuleSetRepository(tmp_path)
|
|
rs = repo.load()
|
|
# Should resolve cleanly using the hardcoded defaults.
|
|
rules = rs.resolve()
|
|
assert rules.preferred_languages # non-empty
|
|
assert rules.min_confidence > 0
|
|
|
|
def test_subtitle_preferences_override_base(self, tmp_path):
|
|
prefs = SubtitlePreferences(
|
|
languages=["jpn"], formats=["ass"], types=["standard"]
|
|
)
|
|
repo = RuleSetRepository(tmp_path)
|
|
rules = repo.load(subtitle_preferences=prefs).resolve()
|
|
assert rules.preferred_languages == ["jpn"]
|
|
assert rules.preferred_formats == ["ass"]
|
|
assert rules.allowed_types == ["standard"]
|
|
|
|
def test_local_rules_yaml_applied(self, tmp_path):
|
|
_write(
|
|
tmp_path / ".alfred" / "rules.yaml",
|
|
{"override": {"languages": ["spa"], "min_confidence": 0.95}},
|
|
)
|
|
repo = RuleSetRepository(tmp_path)
|
|
rules = repo.load().resolve()
|
|
assert rules.preferred_languages == ["spa"]
|
|
assert rules.min_confidence == 0.95
|
|
|
|
def test_release_group_override_applied(self, tmp_path):
|
|
_write(
|
|
tmp_path / ".alfred" / "release_groups" / "KONTRAST.yaml",
|
|
{"override": {"format_priority": ["ass", "srt"]}},
|
|
)
|
|
repo = RuleSetRepository(tmp_path)
|
|
rules = repo.load(release_group="KONTRAST").resolve()
|
|
assert rules.format_priority == ["ass", "srt"]
|
|
|
|
def test_full_three_level_chain(self, tmp_path):
|
|
# Base: prefs sets languages=["jpn"]
|
|
prefs = SubtitlePreferences(languages=["jpn"])
|
|
# Group: overrides format_priority
|
|
_write(
|
|
tmp_path / ".alfred" / "release_groups" / "GRP.yaml",
|
|
{"override": {"format_priority": ["ass"]}},
|
|
)
|
|
# Local: overrides min_confidence
|
|
_write(
|
|
tmp_path / ".alfred" / "rules.yaml",
|
|
{"override": {"min_confidence": 0.99}},
|
|
)
|
|
repo = RuleSetRepository(tmp_path)
|
|
rules = repo.load(release_group="GRP", subtitle_preferences=prefs).resolve()
|
|
# All three levels visible — local overrides on top
|
|
assert rules.preferred_languages == ["jpn"]
|
|
assert rules.format_priority == ["ass"]
|
|
assert rules.min_confidence == 0.99
|
|
|
|
def test_release_group_yaml_without_override_section_ignored(self, tmp_path):
|
|
_write(
|
|
tmp_path / ".alfred" / "release_groups" / "GRP.yaml",
|
|
{"name": "GRP"}, # no 'override' key
|
|
)
|
|
# Must not crash and must not introduce an intermediate node.
|
|
repo = RuleSetRepository(tmp_path)
|
|
rs = repo.load(release_group="GRP")
|
|
# No extra rule set was created → it's still the global default.
|
|
assert rs.scope.level == "global"
|
|
|
|
def test_missing_release_group_file_silently_ignored(self, tmp_path):
|
|
repo = RuleSetRepository(tmp_path)
|
|
rs = repo.load(release_group="DOES_NOT_EXIST")
|
|
assert rs.scope.level == "global"
|
|
|
|
|
|
# --------------------------------------------------------------------------- #
|
|
# save_local #
|
|
# --------------------------------------------------------------------------- #
|
|
|
|
|
|
class TestSaveLocal:
|
|
def test_creates_file(self, tmp_path):
|
|
repo = RuleSetRepository(tmp_path)
|
|
repo.save_local({"languages": ["spa"]})
|
|
path = tmp_path / ".alfred" / "rules.yaml"
|
|
assert path.is_file()
|
|
loaded = yaml.safe_load(path.read_text())
|
|
assert loaded == {"override": {"languages": ["spa"]}}
|
|
|
|
def test_merges_with_existing(self, tmp_path):
|
|
repo = RuleSetRepository(tmp_path)
|
|
repo.save_local({"languages": ["spa"]})
|
|
repo.save_local({"min_confidence": 0.8})
|
|
loaded = yaml.safe_load((tmp_path / ".alfred" / "rules.yaml").read_text())
|
|
assert loaded["override"]["languages"] == ["spa"]
|
|
assert loaded["override"]["min_confidence"] == 0.8
|
|
|
|
def test_overwrites_existing_key(self, tmp_path):
|
|
repo = RuleSetRepository(tmp_path)
|
|
repo.save_local({"languages": ["spa"]})
|
|
repo.save_local({"languages": ["jpn"]})
|
|
loaded = yaml.safe_load((tmp_path / ".alfred" / "rules.yaml").read_text())
|
|
assert loaded["override"]["languages"] == ["jpn"]
|
|
|
|
def test_temp_file_cleaned_up(self, tmp_path):
|
|
repo = RuleSetRepository(tmp_path)
|
|
repo.save_local({"languages": ["spa"]})
|
|
# No stale .tmp file
|
|
assert not (tmp_path / ".alfred" / "rules.yaml.tmp").exists()
|