feat: mehrere Glossare kombinieren, gemeinsames Krone-Schmalz-Glossar

- rede_korrigieren.py: -g mehrfach, Ersetzungen in Reihenfolge der Angabe
- Ersetzungen ohne Treffer werden gesammelt in einer Zeile gemeldet
- krone-schmalz.glossar.txt: wiederkehrende Namen und Hörfehler; die
  Rede-Glossare enthalten nur noch Spezielles
- Magdeburg ergibt exakt denselben Text wie vorher, Ramstein profitiert von
  den gemeinsamen Einträgen (Russland-Versteher, Status quo, vornherein …)

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
Dieter Schlüter 2026-10-10 19:56:18 +02:00
commit 6610679d80

View file

@ -12,6 +12,7 @@ import rede_korrigieren as rk
REPO = Path(__file__).resolve().parent.parent
SAMPLE = REPO / "testdaten" / "ramstein.de.txt"
GLOSSARY = REPO / "ramstein.glossar.txt"
SHARED_GLOSSARY = REPO / "krone-schmalz.glossar.txt"
def flat(text):
@ -99,7 +100,7 @@ def test_apply_replacements_whole_words_in_order(capsys):
text, [("Egon Bars", "Egon Bahrs"), ("Egon Bar", "Egon Bahr"), ("Fehlt", "x")]
)
assert result == "Egon Bahrs Politik, Egon Bahr. Barbara bleibt."
assert "Ersetzung ohne Treffer: „Fehlt“" in capsys.readouterr().out
assert "1 Ersetzung(en) ohne Treffer: „Fehlt“" in capsys.readouterr().out
def test_build_system_appends_terms():
@ -109,18 +110,33 @@ def test_build_system_appends_terms():
assert "- Kreml\n- Egon Bahr" in system
@pytest.mark.parametrize("glossary, sample", [
SAMPLE_GLOSSARIES = [
("ramstein.glossar.txt", "ramstein.de.txt"),
("magdeburg.glossar.txt", "magdeburg.de-orig.txt"),
])
]
@pytest.mark.parametrize("glossary, sample", SAMPLE_GLOSSARIES)
def test_sample_glossary_replacements_all_match(capsys, glossary, sample):
"""Every rule in a sample glossary must hit its sample transcript."""
_, replacements = rk.read_glossary(REPO / glossary)
text = (REPO / "testdaten" / sample).read_text(encoding="utf-8")
rk.apply_replacements(flat(text), replacements)
"""Every rule in a speech glossary must hit its speech, after the shared one."""
text = flat((REPO / "testdaten" / sample).read_text(encoding="utf-8"))
text = rk.apply_replacements(text, rk.read_glossary(SHARED_GLOSSARY)[1])
capsys.readouterr()
rk.apply_replacements(text, rk.read_glossary(REPO / glossary)[1])
assert "ohne Treffer" not in capsys.readouterr().out
def test_shared_glossary_rules_match_some_speech():
texts = [
flat((REPO / "testdaten" / sample).read_text(encoding="utf-8"))
for _, sample in SAMPLE_GLOSSARIES
]
for wrong, right in rk.read_glossary(SHARED_GLOSSARY)[1]:
assert any(
rk.apply_replacements(text, [(wrong, right)]) != text for text in texts
), wrong
# === Model calls (urlopen faked) ===
def stream_body(pieces, done_reason="stop"):
@ -263,7 +279,7 @@ def sample_copy(tmp_path):
def test_main_default_output_resume_and_glossary(sample_copy, monkeypatch, capsys):
monkeypatch.setattr(rk, "correct_chunk", identity_correct)
monkeypatch.setattr(rk, "find_paragraph_starts", every_nth_start(5))
run_main(monkeypatch, "-i", sample_copy, "-g", GLOSSARY)
run_main(monkeypatch, "-i", sample_copy, "-g", SHARED_GLOSSARY, "-g", GLOSSARY)
target = sample_copy.with_name("ramstein.de.korrigiert.txt")
result = target.read_text(encoding="utf-8")
@ -275,7 +291,7 @@ def test_main_default_output_resume_and_glossary(sample_copy, monkeypatch, capsy
# Second run: everything cached, no model calls
monkeypatch.setattr(rk, "correct_chunk", no_model_calls)
monkeypatch.setattr(rk, "find_paragraph_starts", no_model_calls)
run_main(monkeypatch, "-i", sample_copy, "-g", GLOSSARY)
run_main(monkeypatch, "-i", sample_copy, "-g", SHARED_GLOSSARY, "-g", GLOSSARY)
assert target.read_text(encoding="utf-8") == result
@ -362,6 +378,7 @@ def test_main_empty_input(tmp_path, monkeypatch):
(["-i", "gibtsnicht.txt"], "Eingabedatei nicht gefunden"),
(["-i", "{sample}", "-o", "{sample}"], "nicht die Eingabedatei"),
(["-i", "{sample}", "-g", "gibtsnicht.txt"], "Glossar nicht gefunden"),
(["-i", "{sample}", "-g", str(GLOSSARY), "-g", "fehlt.txt"], "Glossar nicht gefunden: fehlt.txt"),
])
def test_cli_errors(sample_copy, monkeypatch, capsys, args, message):
args = [a.format(sample=sample_copy) for a in args]