Prefixless subtitle sidecar files

This commit is contained in:
Javanaut
2026-06-15 12:43:34 +02:00
parent f794f822f2
commit 176cfa06eb
7 changed files with 676 additions and 72 deletions

View File

@@ -6,7 +6,9 @@ from pathlib import Path
import sys
import tempfile
import unittest
from unittest.mock import patch
import click
from click.testing import CliRunner
@@ -17,6 +19,10 @@ if str(SRC_ROOT) not in sys.path:
from ffx import cli # noqa: E402
from ffx.logging_utils import get_ffx_logger # noqa: E402
from ffx.media_descriptor import MediaDescriptor # noqa: E402
from ffx.track_descriptor import TrackDescriptor # noqa: E402
from ffx.track_type import TrackType # noqa: E402
class SubtitleDirectoryCliTests(unittest.TestCase):
@@ -48,6 +54,35 @@ class SubtitleDirectoryCliTests(unittest.TestCase):
env={**os.environ, "HOME": str(self.home_dir)},
)
def make_subtitle_descriptor(self, indices=(2, 3, 4)) -> MediaDescriptor:
return MediaDescriptor(
context={"logger": get_ffx_logger()},
track_descriptors=[
TrackDescriptor(
index=index,
source_index=index,
sub_index=subIndex,
track_type=TrackType.SUBTITLE,
)
for subIndex, index in enumerate(indices)
],
)
def make_import_context(
self,
subtitleDirectory: Path,
noPrompt: bool,
yes: bool = False,
) -> dict:
return {
"subtitle_match_source_basename": True,
"subtitle_directory": str(subtitleDirectory),
"subtitle_prefix": "",
"subtitle_extension": "vtt",
"no_prompt": noPrompt,
"yes": yes,
}
def test_subtitle_prefix_without_directory_or_default_fails(self):
result = self.invoke_convert("--subtitle-prefix", "dball")
@@ -79,6 +114,143 @@ class SubtitleDirectoryCliTests(unittest.TestCase):
self.assertEqual(0, result.exit_code, result.output)
def test_explicit_directory_without_prefix_enables_basename_matching(self):
explicitSubtitleDirectory = self.home_dir / "manual-subtitles"
explicitSubtitleDirectory.mkdir(parents=True, exist_ok=True)
enabled, directory, prefix, matchBasename = cli.resolveSubtitleImportOptions(
{},
str(explicitSubtitleDirectory),
"",
)
self.assertTrue(enabled)
self.assertEqual(str(explicitSubtitleDirectory), directory)
self.assertEqual("", prefix)
self.assertTrue(matchBasename)
def test_subtitle_extension_accepts_optional_leading_dot(self):
self.assertEqual("mkv", cli.normalizeSubtitleExtension(None, None, "mkv"))
self.assertEqual("mkv", cli.normalizeSubtitleExtension(None, None, ".mkv"))
def test_subtitle_extension_rejects_multiple_leading_dots(self):
with self.assertRaises(click.BadParameter):
cli.normalizeSubtitleExtension(None, None, "..mkv")
def test_complete_basename_set_does_not_prompt(self):
subtitleDirectory = Path(__file__).resolve().parents[1] / "assets" / "subtitles"
descriptor = self.make_subtitle_descriptor()
context = self.make_import_context(subtitleDirectory, noPrompt=True)
with patch("ffx.cli.click.confirm") as mockedConfirm:
result = cli.importExternalSubtitles(
context,
descriptor,
"A2_t01",
-1,
-1,
)
self.assertEqual([], result["missing_track_indices"])
mockedConfirm.assert_not_called()
def test_incomplete_basename_set_fails_with_no_prompt(self):
descriptor = self.make_subtitle_descriptor()
subtitleDirectory = self.home_dir / "partial-subtitles"
subtitleDirectory.mkdir()
(subtitleDirectory / "episode_2_deu.vtt").write_text(
"WEBVTT\n\n",
encoding="utf-8",
)
context = self.make_import_context(subtitleDirectory, noPrompt=True)
with patch("ffx.cli.click.confirm") as mockedConfirm:
with self.assertRaisesRegex(click.ClickException, "--no-prompt is set"):
cli.importExternalSubtitles(
context,
descriptor,
"episode",
-1,
-1,
)
mockedConfirm.assert_not_called()
def test_incomplete_basename_set_can_be_confirmed(self):
descriptor = self.make_subtitle_descriptor()
subtitleDirectory = self.home_dir / "partial-subtitles"
subtitleDirectory.mkdir()
(subtitleDirectory / "episode_2_deu.vtt").write_text(
"WEBVTT\n\n",
encoding="utf-8",
)
context = self.make_import_context(subtitleDirectory, noPrompt=False)
with patch("ffx.cli.click.confirm", return_value=True) as mockedConfirm:
result = cli.importExternalSubtitles(
context,
descriptor,
"episode",
-1,
-1,
)
self.assertEqual([3, 4], result["missing_track_indices"])
mockedConfirm.assert_called_once()
def test_incomplete_basename_set_with_yes_does_not_prompt(self):
descriptor = self.make_subtitle_descriptor()
subtitleDirectory = self.home_dir / "partial-subtitles"
subtitleDirectory.mkdir()
(subtitleDirectory / "episode_2_deu.vtt").write_text(
"WEBVTT\n\n",
encoding="utf-8",
)
context = self.make_import_context(
subtitleDirectory,
noPrompt=False,
yes=True,
)
with patch("ffx.cli.click.confirm") as mockedConfirm:
result = cli.importExternalSubtitles(
context,
descriptor,
"episode",
-1,
-1,
)
self.assertEqual([2], result["imported_track_indices"])
self.assertEqual([3, 4], result["missing_track_indices"])
mockedConfirm.assert_not_called()
def test_yes_takes_precedence_over_no_prompt_for_incomplete_set(self):
descriptor = self.make_subtitle_descriptor()
subtitleDirectory = self.home_dir / "partial-subtitles"
subtitleDirectory.mkdir()
(subtitleDirectory / "episode_2_deu.vtt").write_text(
"WEBVTT\n\n",
encoding="utf-8",
)
context = self.make_import_context(
subtitleDirectory,
noPrompt=True,
yes=True,
)
with patch("ffx.cli.click.confirm") as mockedConfirm:
result = cli.importExternalSubtitles(
context,
descriptor,
"episode",
-1,
-1,
)
self.assertEqual([3, 4], result["missing_track_indices"])
mockedConfirm.assert_not_called()
if __name__ == "__main__":
unittest.main()