Adopt "Title (YYYY)" pool naming and clean Filmotéka link names

This commit is contained in:
2026-07-27 20:51:31 +02:00
parent 4c4180f28c
commit 1c78ca9013
13 changed files with 784 additions and 145 deletions
+88 -17
View File
@@ -208,6 +208,78 @@ class TestHardlinkManager:
created2, _, removed2, _ = manager.sync_structure([f], category_roots=roots)
assert (created2, removed2) == (0, 0)
def test_link_name_strips_year_by_default(
self, tmp_path, tag_manager
):
"""A pooled 'Title (YYYY).ext' hardlinks into the tag tree as 'Title.ext'."""
source = tmp_path / "source"
source.mkdir()
(source / "Solaris (1972).mkv").write_text("x")
f = File(source / "Solaris (1972).mkv", tag_manager)
f.tags.clear()
f.title = "Solaris"
f.add_tag(Tag("žánr", "Sci-Fi"))
output = tmp_path / "output"
manager = HardlinkManager(output)
manager.create_structure_for_files([f], category_roots={"žánr": ""})
assert (output / "Sci-Fi" / "Solaris.mkv").exists() # year stripped
assert not (output / "Sci-Fi" / "Solaris (1972).mkv").exists()
def test_link_name_keeps_year_on_collision(
self, tmp_path, tag_manager
):
"""Two same-title films in one folder keep the year to disambiguate."""
source = tmp_path / "source"
source.mkdir()
(source / "Solaris (1972).mkv").write_text("a")
(source / "Solaris (2002).mkv").write_text("b")
f1 = File(source / "Solaris (1972).mkv", tag_manager)
f1.tags.clear()
f1.title = "Solaris"
f1.csfd_cache = {"year": 1972}
f1.add_tag(Tag("žánr", "Sci-Fi"))
f1.add_tag(Tag("rok", "1972"))
f2 = File(source / "Solaris (2002).mkv", tag_manager)
f2.tags.clear()
f2.title = "Solaris"
f2.csfd_cache = {"year": 2002}
f2.add_tag(Tag("žánr", "Sci-Fi"))
f2.add_tag(Tag("rok", "2002"))
output = tmp_path / "output"
manager = HardlinkManager(output)
roots = {"žánr": "", "rok": "Dle roku"}
manager.create_structure_for_files([f1, f2], category_roots=roots)
# Same genre folder → clash → both keep the year
assert (output / "Sci-Fi" / "Solaris (1972).mkv").exists()
assert (output / "Sci-Fi" / "Solaris (2002).mkv").exists()
assert not (output / "Sci-Fi" / "Solaris.mkv").exists()
# Separate year folders → no clash → clean name
assert (output / "Dle roku" / "1972" / "Solaris.mkv").exists()
assert (output / "Dle roku" / "2002" / "Solaris.mkv").exists()
def test_clean_naming_cleanup_is_consistent(
self, tmp_path, tag_manager
):
"""Clean-named links are stable: a second sync removes/creates nothing."""
source = tmp_path / "source"
source.mkdir()
(source / "Solaris (1972).mkv").write_text("x")
f = File(source / "Solaris (1972).mkv", tag_manager)
f.tags.clear()
f.title = "Solaris"
f.add_tag(Tag("žánr", "Sci-Fi"))
roots = {"žánr": ""}
output = tmp_path / "output"
manager = HardlinkManager(output)
manager.sync_structure([f], category_roots=roots)
created, _, removed, _ = manager.sync_structure([f], category_roots=roots)
assert (created, removed) == (0, 0)
def test_sync_removes_root_genre_folder_when_last_movie_drops_tag(
self, temp_source_dir, temp_output_dir, tag_manager
):
@@ -263,8 +335,8 @@ class TestHardlinkManager:
# Templated name inside the collection folder
assert (temp_output_dir / "Dle kolekce" / "James Bond" / "1962 - Dr. No.txt").exists()
# Other categories keep the pool filename
assert (temp_output_dir / "Akční" / "file1.txt").exists()
# Other categories use the default clean title (no year, not the pool name)
assert (temp_output_dir / "Akční" / "Dr. No.txt").exists()
def test_filename_template_cleanup_is_consistent(
self, temp_source_dir, temp_output_dir, tag_manager
@@ -421,30 +493,27 @@ class TestHardlinkManager:
assert fail2 == 0
def test_unique_name_on_conflict(self, temp_source_dir, temp_output_dir, tag_manager):
"""Test že při konfliktu (jiný soubor) se použije unikátní jméno"""
# Create first file
"""Two different movies with the same clean name (no year to tell them
apart) in one folder get distinct links via a numeric suffix."""
f1 = File(temp_source_dir / "file1.txt", tag_manager)
f1.tags.clear()
f1.add_tag(Tag("test", "tag"))
manager = HardlinkManager(temp_output_dir)
manager.create_structure_for_files([f1])
# Create different file with same name in different location
source2 = temp_source_dir / "subdir"
source2.mkdir()
(source2 / "file1.txt").write_text("different content")
f2 = File(source2 / "file1.txt", tag_manager)
f2.tags.clear()
f2.add_tag(Tag("test", "tag"))
# Should create file1_1.txt
manager2 = HardlinkManager(temp_output_dir)
success, fail = manager2.create_structure_for_files([f2])
# One generation over both files → the plan disambiguates the clash.
manager = HardlinkManager(temp_output_dir)
success, fail = manager.create_structure_for_files([f1, f2])
assert success == 1
assert (temp_output_dir / "test" / "tag" / "file1_1.txt").exists()
assert success == 2 and fail == 0
folder = temp_output_dir / "test" / "tag"
assert (folder / "file1.txt").exists()
assert (folder / "file1_2.txt").exists()
def test_czech_characters_in_tags(self, temp_source_dir, temp_output_dir, tag_manager):
"""Test českých znaků v názvech tagů"""
@@ -746,9 +815,11 @@ class TestEdgeCases:
"""Test souboru se speciálními znaky v názvu"""
source = tmp_path / "source"
source.mkdir()
(source / "file with spaces (2024).txt").write_text("content")
# Parentheses that are NOT a four-digit year must survive verbatim
# (a trailing "(YYYY)" would be stripped by the naming rule).
(source / "file with spaces (part 2).txt").write_text("content")
f = File(source / "file with spaces (2024).txt", tag_manager)
f = File(source / "file with spaces (part 2).txt", tag_manager)
f.tags.clear()
f.add_tag(Tag("test", "tag"))
@@ -759,7 +830,7 @@ class TestEdgeCases:
success, fail = manager.create_structure_for_files([f])
assert success == 1
assert (output / "test" / "tag" / "file with spaces (2024).txt").exists()
assert (output / "test" / "tag" / "file with spaces (part 2).txt").exists()
def test_empty_category_filter(self, tmp_path, tag_manager):
"""Test s prázdným seznamem kategorií"""