mirror of
https://github.com/kuhyx/testsAndMisc.git
synced 2026-11-10 21:27:02 +01:00
The last Python file over the cap:
_transcribe_media.py 143 _try_import, both duration probes,
get_media_duration, ffmpeg transcode, cleanup
_transcribe_cluster.py 105 _resample_linear, _kmeans_cosine and its
iteration loop
_transcribe_diarize.py 164 the pipeline: audio loading, the classifier,
embedding extraction, diarize_segments
The graph is a tree: _transcribe_media imports nothing local, _cluster takes
only _try_import from it, _diarize imports from both. All 13 top-level
definitions verified AST-identical to HEAD, and an AST scan confirms the
three module constants travelled to the modules that use them.
transcribe_fw.py now imports get_media_duration from _transcribe_media
rather than through _transcribe_diarize. Ruff removed that re-export as
unused and broke the import; running the program is what caught it, and
naming the owning module is the correct fix under the no-barrels rule.
Verified: transcribe_fw.py /nonexistent.wav still exits 2 and --help exits
0; 63 tests pass at 100% line and branch on all three modules; 338 pass in
the directory. Over-cap files 33 -> 32, and no Python file is over the cap
any more - the remaining 32 are 29 shell, 2 kotlin, 1 dart.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_011w2Pj4Ek3ZNMQVYcFHgXDY
173 lines
6.0 KiB
Python
173 lines
6.0 KiB
Python
"""Tests for media-duration probing and temp-file handling.
|
|
|
|
Duration is probed twice: through the ffmpeg-python binding if it is
|
|
importable, then by shelling out to ffprobe. Both are patched here, so the
|
|
tests pass whether or not ffmpeg is installed on the machine running them.
|
|
"""
|
|
|
|
from __future__ import annotations
|
|
|
|
import shutil
|
|
import subprocess
|
|
|
|
import _transcribe_media as diar
|
|
import pytest
|
|
|
|
|
|
class _FfmpegModule:
|
|
"""An ffmpeg-python double whose probe() returns a fixed payload."""
|
|
|
|
def __init__(self, payload: object) -> None:
|
|
self._payload = payload
|
|
|
|
def probe(self, _path: str) -> object:
|
|
"""Return the canned probe result, or raise it if it is an error."""
|
|
if isinstance(self._payload, Exception):
|
|
raise self._payload
|
|
return self._payload
|
|
|
|
|
|
def _only(name: str, module: object) -> object:
|
|
"""Return a _try_import double resolving exactly one module name."""
|
|
|
|
def _try(requested: str) -> object | None:
|
|
return module if requested == name else None
|
|
|
|
return _try
|
|
|
|
|
|
# --------------------------------------------------------------------------- #
|
|
# The optional-dependency import seam
|
|
# --------------------------------------------------------------------------- #
|
|
def test_try_import_returns_the_module_when_present() -> None:
|
|
"""The seam the other tests patch works against a real module."""
|
|
assert diar._try_import("json") is not None
|
|
|
|
|
|
def test_try_import_returns_none_for_a_missing_module() -> None:
|
|
"""A missing optional dependency is None, not an ImportError."""
|
|
assert diar._try_import("no_such_module_anywhere_12345") is None
|
|
|
|
|
|
# --------------------------------------------------------------------------- #
|
|
# _probe_with_ffmpeg_python
|
|
# --------------------------------------------------------------------------- #
|
|
def test_probe_with_ffmpeg_python_reads_the_format_duration(
|
|
monkeypatch: pytest.MonkeyPatch,
|
|
) -> None:
|
|
"""The binding reports duration under probe()['format']['duration']."""
|
|
module = _FfmpegModule({"format": {"duration": "123.5"}})
|
|
monkeypatch.setattr(diar, "_try_import", _only("ffmpeg", module))
|
|
|
|
assert diar._probe_with_ffmpeg_python("clip.wav") == pytest.approx(123.5)
|
|
|
|
|
|
def test_probe_with_ffmpeg_python_returns_none_without_the_binding(
|
|
monkeypatch: pytest.MonkeyPatch,
|
|
) -> None:
|
|
"""Without ffmpeg-python installed this probe declines."""
|
|
monkeypatch.setattr(diar, "_try_import", lambda _n: None)
|
|
|
|
assert diar._probe_with_ffmpeg_python("clip.wav") is None
|
|
|
|
|
|
def test_probe_with_ffmpeg_python_returns_none_without_a_duration_key(
|
|
monkeypatch: pytest.MonkeyPatch,
|
|
) -> None:
|
|
"""A probe result with no duration falls through to the next method."""
|
|
module = _FfmpegModule({"format": {}})
|
|
monkeypatch.setattr(diar, "_try_import", _only("ffmpeg", module))
|
|
|
|
assert diar._probe_with_ffmpeg_python("clip.wav") is None
|
|
|
|
|
|
@pytest.mark.parametrize("error", [OSError("boom"), RuntimeError("boom")])
|
|
def test_probe_with_ffmpeg_python_survives_a_probe_error(
|
|
monkeypatch: pytest.MonkeyPatch, error: Exception
|
|
) -> None:
|
|
"""A failing probe returns None rather than propagating."""
|
|
monkeypatch.setattr(diar, "_try_import", _only("ffmpeg", _FfmpegModule(error)))
|
|
|
|
assert diar._probe_with_ffmpeg_python("clip.wav") is None
|
|
|
|
|
|
# --------------------------------------------------------------------------- #
|
|
# _probe_with_ffprobe
|
|
# --------------------------------------------------------------------------- #
|
|
def test_probe_with_ffprobe_parses_the_duration(
|
|
monkeypatch: pytest.MonkeyPatch,
|
|
) -> None:
|
|
"""ffprobe prints a bare float, which is parsed to seconds."""
|
|
monkeypatch.setattr(shutil, "which", lambda _b: "/usr/bin/ffprobe")
|
|
monkeypatch.setattr(subprocess, "check_output", lambda *_a, **_k: b" 42.25 \n")
|
|
|
|
assert diar._probe_with_ffprobe("clip.wav") == pytest.approx(42.25)
|
|
|
|
|
|
def test_probe_with_ffprobe_returns_none_when_not_installed(
|
|
monkeypatch: pytest.MonkeyPatch,
|
|
) -> None:
|
|
"""No ffprobe on PATH means no duration."""
|
|
monkeypatch.setattr(shutil, "which", lambda _b: None)
|
|
|
|
assert diar._probe_with_ffprobe("clip.wav") is None
|
|
|
|
|
|
@pytest.mark.parametrize(
|
|
"error",
|
|
[
|
|
OSError("boom"),
|
|
subprocess.CalledProcessError(1, "ffprobe"),
|
|
ValueError("not a float"),
|
|
],
|
|
)
|
|
def test_probe_with_ffprobe_survives_every_failure_mode(
|
|
monkeypatch: pytest.MonkeyPatch, error: Exception
|
|
) -> None:
|
|
"""A crash, a non-zero exit, or unparsable output all yield None."""
|
|
monkeypatch.setattr(shutil, "which", lambda _b: "/usr/bin/ffprobe")
|
|
|
|
def _boom(*_a: object, **_k: object) -> None:
|
|
raise error
|
|
|
|
monkeypatch.setattr(subprocess, "check_output", _boom)
|
|
|
|
assert diar._probe_with_ffprobe("clip.wav") is None
|
|
|
|
|
|
# --------------------------------------------------------------------------- #
|
|
# get_media_duration
|
|
# --------------------------------------------------------------------------- #
|
|
def test_get_media_duration_prefers_the_python_binding(
|
|
monkeypatch: pytest.MonkeyPatch,
|
|
) -> None:
|
|
"""When the binding answers, ffprobe is never invoked."""
|
|
called: list[str] = []
|
|
|
|
def _record_ffprobe(_path: str) -> None:
|
|
called.append("ffprobe")
|
|
|
|
monkeypatch.setattr(diar, "_probe_with_ffmpeg_python", lambda _p: 10.0)
|
|
monkeypatch.setattr(diar, "_probe_with_ffprobe", _record_ffprobe)
|
|
|
|
assert diar.get_media_duration("clip.wav") == pytest.approx(10.0)
|
|
assert called == []
|
|
|
|
|
|
def test_get_media_duration_falls_back_to_ffprobe(
|
|
monkeypatch: pytest.MonkeyPatch,
|
|
) -> None:
|
|
"""Without the binding, the CLI is tried next."""
|
|
monkeypatch.setattr(diar, "_probe_with_ffmpeg_python", lambda _p: None)
|
|
monkeypatch.setattr(diar, "_probe_with_ffprobe", lambda _p: 20.0)
|
|
|
|
assert diar.get_media_duration("clip.wav") == pytest.approx(20.0)
|
|
|
|
|
|
def test_get_media_duration_is_none_when_both_fail(
|
|
monkeypatch: pytest.MonkeyPatch,
|
|
) -> None:
|
|
"""An unprobeable file is not an error - the caller drops the percentage."""
|
|
monkeypatch.setattr(diar, "_probe_with_ffmpeg_python", lambda _p: None)
|
|
monkeypatch.setattr(diar, "_probe_with_ffprobe", lambda _p: None)
|