fix(prescan): makemkvcon ueber den Katalog suchen, nicht ueber shutil.which
Ampel / ampel (push) Successful in 55s

Auf die Frage des Commanders: "du hast jetzt nur mein laufwerk analysiert
oder? wenn ich rippy weitergebe wie laeuft es dort?"

Berechtigt -- und beim Nachsehen fiel derselbe Fehler auf wie heute Vormittag
im Werkzeug-Katalog:

    shutil.which("makemkvcon")   ->  None, auch bei installiertem MakeMKV

`which` sucht nur im PATH. Windows-Programme liegen in "Programme". Der
Zweig, der die Titelliste von makemkvcon holt, lief unter Windows also NIE --
unabhaengig vom Laufwerk, auf jedem Rechner. Jetzt ueber
`katalog.finden("makemkv")`, das genau dafuer da ist.

Dazu vier Tests fuer Disc-Arten, die ICH NICHT HABE, damit die Zusage nicht
an einer einzigen Disc haengt:

    Blu-ray ohne BDMV/META   -> None (sehr haeufig; Rueckfall aufs Label)
    DVD (nur VIDEO_TS)       -> None
    bdmt_deu.xml vorhanden   -> Titel wird gelesen
    deu + eng vorhanden      -> eng gewinnt (APIs suchen damit besser)

Und ein Waechter gegen shutil.which in prescan.py. Der erste Anlauf davon
fiel ueber den eigenen Erklaertext, in dem der alte Aufruf zitiert wird --
er prueft jetzt nur Code, keine Kommentare.

Ampel lokal: 774 gruen, ruff sauber.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
Hitonabi
2026-08-28 16:05:25 +02:00
co-authored by Claude Opus 5
parent 878b24c43b
commit be3fac53af
2 changed files with 82 additions and 4 deletions
+13 -4
View File
@@ -6,11 +6,11 @@ lieferte seitdem immer „Unknown Disc". Dies ist die echte Logik, bereinigt.
""" """
import os import os
import shutil
import subprocess import subprocess
from typing import Dict, List, Optional from typing import Dict, List, Optional
from rippy import drives as _laufwerks_schicht from rippy import drives as _laufwerks_schicht
from rippy.tools import katalog as werkzeug_katalog
from clients.tmdb import TMDBClient from clients.tmdb import TMDBClient
from clients.jikan import JikanClient from clients.jikan import JikanClient
from clients.musicbrainz import MusicBrainzClient from clients.musicbrainz import MusicBrainzClient
@@ -346,10 +346,19 @@ class PreScan:
if label: if label:
toc["title"] = normalize_disc_label(label) toc["title"] = normalize_disc_label(label)
# Titel-Quelle 2 (optional, falls makemkvcon doch da ist): # Titel-Quelle 3: die Titelliste von makemkvcon (optional).
if shutil.which("makemkvcon"): #
# ⚠️ Über den Werkzeug-Katalog, NICHT über `shutil.which`
# (Befund 28.08.2026). `which` sucht nur im PATH — unter
# Windows liegen Programme in „Programme", nicht im PATH.
# Gemessen: `shutil.which("makemkvcon")` gibt dort auch bei
# installiertem MakeMKV None zurück, und dieser Zweig lief
# NIE. Genau derselbe Fehler, für den es `tools/katalog.py`
# gibt.
makemkv = werkzeug_katalog.finden("makemkv")
if makemkv:
result = subprocess.run( result = subprocess.run(
["makemkvcon", "-r", "--noscan", "--minlength=300", "info", f"dev:{device_path}"], [makemkv, "-r", "--noscan", "--minlength=300", "info", f"dev:{device_path}"],
capture_output=True, capture_output=True,
text=True, text=True,
timeout=120 timeout=120
+69
View File
@@ -144,3 +144,72 @@ def test_ohne_jede_quelle_bleibt_es_unbekannt(monkeypatch):
assert ergebnis.confidence == 0.3 assert ergebnis.confidence == 0.3
assert ergebnis.metadata["type"] == "unknown" assert ergebnis.metadata["type"] == "unknown"
assert ergebnis.title == "Nix Da" assert ergebnis.title == "Nix Da"
# ── Was auf FREMDEN Rechnern gilt (Befund 28.08.2026) ───────────────────
#
# Der Commander: "du hast jetzt nur mein laufwerk analysiert oder? wenn ich
# rippy weitergebe wie laeuft es dort?"
#
# Berechtigt. Gemessen wurde an EINEM Laufwerk (LG BU40N) und EINER Disc
# (BD-50 mit BDMV/META). Diese Tests halten fest, was bei ANDEREN Discs
# passieren muss -- ohne dass eine davon vorhanden sein muss.
def test_bluray_ohne_metadaten_gibt_ehrlich_nichts_zurueck(tmp_path):
"""Sehr viele Blu-rays haben kein BDMV/META. Dann greift der Rueckfall
auf das Volume-Label -- aber diese Funktion darf nichts erfinden."""
from prescan.prescan import titel_aus_bdmt
(tmp_path / "BDMV" / "STREAM").mkdir(parents=True)
assert titel_aus_bdmt(str(tmp_path)) is None
def test_dvd_hat_kein_bdmv(tmp_path):
from prescan.prescan import titel_aus_bdmt
(tmp_path / "VIDEO_TS").mkdir()
assert titel_aus_bdmt(str(tmp_path)) is None
def test_bdmt_wird_gelesen_wenn_da(tmp_path):
"""Der Weg, der bei der Disc des Commanders 'Evangelion 2.22' lieferte —
hier ohne Disc nachgestellt."""
from prescan.prescan import titel_aus_bdmt
meta = tmp_path / "BDMV" / "META" / "DL"
meta.mkdir(parents=True)
(meta / "bdmt_deu.xml").write_text(
'<?xml version="1.0"?><disclib><di:discinfo>'
'<di:title><di:name>Evangelion 2.22</di:name></di:title>'
'</di:discinfo></disclib>', encoding="utf-8")
assert titel_aus_bdmt(str(tmp_path)) == "Evangelion 2.22"
def test_englisch_wird_bevorzugt(tmp_path):
"""Die APIs suchen mit englischen Titeln besser."""
from prescan.prescan import titel_aus_bdmt
meta = tmp_path / "BDMV" / "META" / "DL"
meta.mkdir(parents=True)
for datei, name in (("bdmt_deu.xml", "Deutscher Titel"),
("bdmt_eng.xml", "English Title")):
(meta / datei).write_text(
"<x><di:name>%s</di:name></x>" % name, encoding="utf-8")
assert titel_aus_bdmt(str(tmp_path)) == "English Title"
def test_makemkvcon_wird_ueber_den_katalog_gesucht():
"""DER Fehler: `shutil.which("makemkvcon")` gibt unter Windows auch bei
installiertem MakeMKV None zurueck -- Windows-Programme liegen in
„Programme", nicht im PATH. Dieser Zweig lief dort also NIE."""
import os
hier = os.path.dirname(os.path.abspath(__file__))
with open(os.path.join(hier, "prescan", "prescan.py"), encoding="utf-8") as f:
# NUR Code, keine Kommentare: Der erste Anlauf dieses Tests fiel ueber
# den eigenen Erklaertext, in dem der alte Aufruf zitiert wird. Ein
# Waechter, der an einer Erklaerung scheitert, prueft das Falsche.
code = [z for z in f if not z.strip().startswith("#")]
quelle = "".join(code)
assert "shutil.which(" not in quelle, (
"shutil.which findet unter Windows keine Programme aus 'Programme'")
assert 'werkzeug_katalog.finden("makemkv")' in quelle