from __future__ import annotations from pathlib import Path import tempfile import unittest from tests.support.ffx_bundle import ( PatternTrackSpec, SourceTrackSpec, add_show, build_controller_context, create_source_fixture, dispose_controller_context, expected_output_path, run_ffx_convert, ) from ffx.pattern_controller import PatternController from ffx.track_type import TrackType try: import pytest except ImportError: # pragma: no cover - unittest-only environments pytest = None if pytest is not None: pytestmark = [pytest.mark.integration, pytest.mark.pattern_management] class PatternManagementCliTests(unittest.TestCase): def setUp(self): self.tempdir = tempfile.TemporaryDirectory() self.workdir = Path(self.tempdir.name) self.home_dir = self.workdir / "home" self.home_dir.mkdir() self.database_path = self.workdir / "test.db" def tearDown(self): self.tempdir.cleanup() def prepare_duplicate_matching_patterns(self): context = build_controller_context(self.database_path) try: add_show(context, show_id=1) add_show(context, show_id=2) controller = PatternController(context) track_descriptors = [ PatternTrackSpec(index=0, source_index=0, track_type=TrackType.VIDEO) ] def to_track_descriptor(spec: PatternTrackSpec): from ffx.track_descriptor import TrackDescriptor kwargs = { TrackDescriptor.INDEX_KEY: spec.index, TrackDescriptor.SOURCE_INDEX_KEY: spec.source_index, TrackDescriptor.TRACK_TYPE_KEY: spec.track_type, TrackDescriptor.TAGS_KEY: dict(spec.tags), TrackDescriptor.DISPOSITION_SET_KEY: set(spec.dispositions), } return TrackDescriptor(**kwargs) controller.savePatternSchema( {"show_id": 1, "pattern": r"^dup_(s[0-9]+e[0-9]+)\.mkv$"}, [to_track_descriptor(track_descriptors[0])], ) controller.savePatternSchema( {"show_id": 2, "pattern": r"^dup_.*$"}, [to_track_descriptor(track_descriptors[0])], ) finally: dispose_controller_context(context) def test_convert_fails_when_filename_matches_more_than_one_pattern(self): self.prepare_duplicate_matching_patterns() source_filename = "dup_s01e01.mkv" source_path = create_source_fixture( self.workdir, source_filename, [ SourceTrackSpec(TrackType.VIDEO, identity="video-0"), SourceTrackSpec(TrackType.AUDIO, identity="audio-1", language="eng"), ], ) completed = run_ffx_convert( self.workdir, self.home_dir, self.database_path, "--video-encoder", "copy", "--no-tmdb", "--no-prompt", "--no-signature", str(source_path), ) self.assertNotEqual(completed.returncode, 0) error_output = f"{completed.stdout}\n{completed.stderr}" self.assertIn("matched more than one pattern", error_output) self.assertFalse(expected_output_path(self.workdir, source_filename).exists()) def test_convert_can_ignore_duplicate_matches_when_no_pattern_is_requested(self): self.prepare_duplicate_matching_patterns() source_filename = "dup_s01e01.mkv" source_path = create_source_fixture( self.workdir, source_filename, [ SourceTrackSpec(TrackType.VIDEO, identity="video-0"), SourceTrackSpec(TrackType.AUDIO, identity="audio-1", language="eng"), ], ) completed = run_ffx_convert( self.workdir, self.home_dir, self.database_path, "--video-encoder", "copy", "--no-pattern", "--no-tmdb", "--no-prompt", "--no-signature", str(source_path), ) self.assertEqual( 0, completed.returncode, f"STDOUT:\n{completed.stdout}\nSTDERR:\n{completed.stderr}", ) self.assertTrue(expected_output_path(self.workdir, source_filename).exists()) if __name__ == "__main__": unittest.main()