843c54cd1a
Ampel / ampel (push) Successful in 27s
Meine eigene Testannahme war falsch, nicht der Code: Antwortet keine Metadaten-Quelle, setzt _scan_video bewusst 0,3 mit `type: unknown` und behaelt den Disc-Titel. Der Rip laeuft dann trotzdem, die Datei heisst nur wie das Disc-Label. Genau dieser Zweig ist Bestand und richtig. Gefunden von der Ampel (Lauf 140) - lokal laeuft dieses Modul nicht, es braucht fcntl. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
147 lines
5.2 KiB
Python
147 lines
5.2 KiB
Python
"""Tests für die puren Pre-Scan-/OMDb-Helfer (Label-Normalisierung, Parsing)."""
|
||
|
||
from clients.omdb import parse_runtime_minutes, parse_year
|
||
from prescan.prescan import normalize_disc_label, parse_udf_dstring
|
||
|
||
|
||
def test_udf_dstring_latin1():
|
||
# d-string: [comp_id=8]["MEIN_FILM"][padding][len=10]
|
||
daten = bytes([8]) + b"MEIN_FILM" + bytes(21) + bytes([10])
|
||
assert parse_udf_dstring(daten) == "MEIN_FILM"
|
||
|
||
|
||
def test_udf_dstring_utf16():
|
||
text = "FILM".encode("utf-16-be")
|
||
daten = bytes([16]) + text + bytes(32 - 2 - len(text)) + bytes([1 + len(text)])
|
||
assert parse_udf_dstring(daten) == "FILM"
|
||
|
||
|
||
def test_udf_dstring_kaputt_gibt_leer():
|
||
assert parse_udf_dstring(b"") == ""
|
||
assert parse_udf_dstring(bytes(32)) == "" # Länge 0
|
||
daten = bytes([8]) + b"X" + bytes(29) + bytes([99]) # Länge > Puffer
|
||
assert parse_udf_dstring(daten) == ""
|
||
|
||
|
||
def test_label_normalisierung():
|
||
# Disc-Labels sind fast immer GROSS_MIT_UNTERSTRICHEN
|
||
assert normalize_disc_label("PULP_FICTION") == "Pulp Fiction"
|
||
assert normalize_disc_label("DIE_HARD_4.0_DE") == "Die Hard 4 0 De"
|
||
assert normalize_disc_label(" doppel raum ") == "doppel raum"
|
||
assert normalize_disc_label("") == ""
|
||
|
||
|
||
def test_label_mit_gemischter_schreibung_bleibt():
|
||
# Wer schon sauber benannt hat, wird nicht plattgewalzt
|
||
assert normalize_disc_label("Inception") == "Inception"
|
||
|
||
|
||
def test_omdb_runtime_parsing():
|
||
assert parse_runtime_minutes("142 min") == 142
|
||
assert parse_runtime_minutes("N/A") == 0
|
||
assert parse_runtime_minutes("") == 0
|
||
|
||
|
||
def test_omdb_jahr_parsing():
|
||
assert parse_year("1999") == 1999
|
||
assert parse_year("2005–2012") == 2005 # Serien-Zeitspanne
|
||
assert parse_year("N/A") is None
|
||
assert parse_year("") is None
|
||
|
||
|
||
# --- Reihenfolge der Metadaten-Quellen: exakt schlägt unscharf ---------------
|
||
#
|
||
# Änderung vom 26.07.2026. Vorher galt der erste Jikan-Treffer über dem Gate
|
||
# 0,55 sofort als sicherer Fund, und OMDb kam nie dran — ein Kinofilm, den TMDB
|
||
# verpasst, bekam damit Anime-Metadaten. Die Messwerte dazu stehen in
|
||
# test_jikan_helpers.py („Alien" gegen „Alien 9" = 0,83).
|
||
|
||
|
||
class _StummerClient:
|
||
"""Ein Client, der auf jede Frage dasselbe antwortet — und mitzählt."""
|
||
|
||
def __init__(self, antwort=None):
|
||
self.antwort = antwort
|
||
self.aufrufe = 0
|
||
|
||
def lookup(self, *a, **k):
|
||
self.aufrufe += 1
|
||
return self.antwort
|
||
|
||
def search_movie(self, *a, **k):
|
||
return []
|
||
|
||
def search_tv(self, *a, **k):
|
||
return []
|
||
|
||
def get_movie_details(self, *a, **k):
|
||
return None
|
||
|
||
def find_by_imdb(self, *a, **k):
|
||
return None
|
||
|
||
|
||
def _scanner(monkeypatch, jikan_antwort, omdb_antwort):
|
||
"""PreScan ohne __init__ (das bräuchte DB + API-Keys), Cache stillgelegt."""
|
||
from prescan import prescan as modul
|
||
|
||
monkeypatch.setattr(modul, "get", lambda k: None)
|
||
monkeypatch.setattr(modul, "cache_set", lambda *a, **k: None)
|
||
|
||
scan = modul.PreScan.__new__(modul.PreScan)
|
||
scan.tmdb = _StummerClient()
|
||
scan.jikan = _StummerClient(jikan_antwort)
|
||
scan.omdb = _StummerClient(omdb_antwort)
|
||
return scan
|
||
|
||
|
||
def _jikan(score):
|
||
return {"type": "movie", "id": "mal-1", "title": "Alien 9",
|
||
"source": "jikan", "match_score": score}
|
||
|
||
|
||
def _omdb():
|
||
return {"type": "movie", "id": "tt0078748", "title": "Alien",
|
||
"source": "omdb", "year": 1979}
|
||
|
||
|
||
def test_unscharfer_jikan_treffer_laesst_omdb_zum_zug(monkeypatch):
|
||
"""Der eigentliche Fehler: „Alien" traf mit 0,83 auf den Anime „Alien 9",
|
||
und der Film wurde nie gesucht."""
|
||
scan = _scanner(monkeypatch, _jikan(0.83), _omdb())
|
||
ergebnis = scan._scan_video("/dev/sr0", {"title": "Alien", "disc_type": "Blu-ray"})
|
||
assert ergebnis.metadata["source"] == "omdb"
|
||
assert ergebnis.confidence == 0.8
|
||
assert scan.omdb.aufrufe > 0
|
||
|
||
|
||
def test_exakter_jikan_treffer_gewinnt_sofort(monkeypatch):
|
||
"""Der Fall, für den Jikan gebaut wurde, darf NICHT verlorengehen
|
||
(AGENTS Regel B): Bei einem sicheren Treffer wird OMDb nicht mehr gefragt."""
|
||
scan = _scanner(monkeypatch, _jikan(1.0), _omdb())
|
||
ergebnis = scan._scan_video("/dev/sr0", {"title": "Alien 9", "disc_type": "Blu-ray"})
|
||
assert ergebnis.metadata["source"] == "jikan"
|
||
assert ergebnis.confidence == 0.85
|
||
assert scan.omdb.aufrufe == 0
|
||
|
||
|
||
def test_unscharfer_jikan_treffer_bleibt_als_vorschlag(monkeypatch):
|
||
"""Hat OMDb nichts (kein Key, kein Treffer), ist der unscharfe Jikan-Treffer
|
||
besser als nichts — aber er wird als VORSCHLAG ausgewiesen (0,6), nicht als
|
||
sicherer Fund."""
|
||
scan = _scanner(monkeypatch, _jikan(0.83), None)
|
||
ergebnis = scan._scan_video("/dev/sr0", {"title": "Alien", "disc_type": "Blu-ray"})
|
||
assert ergebnis.metadata["source"] == "jikan"
|
||
assert ergebnis.confidence == 0.6
|
||
|
||
|
||
def test_ohne_jede_quelle_bleibt_es_unbekannt(monkeypatch):
|
||
"""Antwortet keine Quelle, bleibt es beim Disc-Titel mit Confidence 0,3 und
|
||
`type: unknown` — der Bestand, unverändert. Der Rip laeuft trotzdem, die
|
||
Datei heisst dann nur wie das Disc-Label."""
|
||
scan = _scanner(monkeypatch, None, None)
|
||
ergebnis = scan._scan_video("/dev/sr0", {"title": "Nix Da", "disc_type": "DVD"})
|
||
assert ergebnis.confidence == 0.3
|
||
assert ergebnis.metadata["type"] == "unknown"
|
||
assert ergebnis.title == "Nix Da"
|