From 42718cbd9912f9977e7b8f872dddeeae70fb65a5 Mon Sep 17 00:00:00 2001 From: imSp4rky Date: Sun, 16 Aug 2026 22:01:12 -0600 Subject: [PATCH] fix(titles): drop folder {year?} when it repeats the dated season label Dated episodes turn the season folder into the air year, so a folder template's {year?} rendered the same year twice (Title.2025.2025). --- docs/guide/output-and-naming.md | 3 +++ tests/core/test_episode_air_date.py | 13 +++++++++++++ unshackle/core/titles/episode.py | 6 ++++-- 3 files changed, 20 insertions(+), 2 deletions(-) diff --git a/docs/guide/output-and-naming.md b/docs/guide/output-and-naming.md index 6a162529..d2b13051 100644 --- a/docs/guide/output-and-naming.md +++ b/docs/guide/output-and-naming.md @@ -494,6 +494,9 @@ how the optional (`?`) variables appear and disappear. The date separator follows your template style: dots here, spaces if your `series` template uses spaces. + In folder names, `{season}` becomes the air year (`Season 2024` style grouping), and a + `{year?}` in the folder template is skipped when it would just repeat that year. + === "Music" ```yaml diff --git a/tests/core/test_episode_air_date.py b/tests/core/test_episode_air_date.py index 693898c2..68abed45 100644 --- a/tests/core/test_episode_air_date.py +++ b/tests/core/test_episode_air_date.py @@ -109,6 +109,19 @@ def test_dated_folder_groups_by_year(reset_template): assert "S2024" not in folder # season folder is the year, not the faked season +def test_dated_folder_drops_year_matching_air_year(reset_template): + """{year?} would repeat the air-year season label (Title.2024.2024); it must render once.""" + folder = make_episode(air_date=date(2024, 6, 30)).get_filename(StubMediaInfo(), folder=True) + assert "2024.2024" not in folder + + +def test_dated_folder_keeps_distinct_year(reset_template): + """A series year different from the air year is real information and stays.""" + folder = make_episode(year=2010, air_date=date(2013, 10, 30)).get_filename(StubMediaInfo(), folder=True) + assert "2010" in folder + assert "2013" in folder + + # --- selection by date ------------------------------------------------------ diff --git a/unshackle/core/titles/episode.py b/unshackle/core/titles/episode.py index fc3bec1d..d8b6daae 100644 --- a/unshackle/core/titles/episode.py +++ b/unshackle/core/titles/episode.py @@ -218,7 +218,8 @@ class Episode(Title): # all parts of an episode land in the same season folder context = self.build_template_context(media_info, show_service, include_part=False) context["season"] = self.folder_season() - context["year"] = self.year or "" # folders keep the year + # folders keep the year, unless the season label is already the air year + context["year"] = "" if str(self.year) == context["season"] else self.year or "" spacer = detect_spacer(template) # one style for the whole path segments = [ TemplateFormatter(seg, spacer).format(context) @@ -242,7 +243,8 @@ class Episode(Title): formatter = TemplateFormatter(derived_template) context = self.build_template_context(media_info, show_service, include_part=False) context["season"] = self.folder_season() - context["year"] = self.year or "" # folders keep the year + # folders keep the year, unless the season label is already the air year + context["year"] = "" if str(self.year) == context["season"] else self.year or "" folder_name = formatter.format(context)