#193 Add --set/--season overrides for batch episode renaming

--season auto-numbers episodes (E01, E02, ...) across a directory;
--set TYPE=VALUE overrides any parsed chunk, e.g. forcing name when
release text buries it in noise. Requires splitting SxxExx tokens
into separate season/episode chunks (previously one glued value)
and rejoining them without a separator in the generated name.

Also scopes --season numbering per directory instead of the whole
tree, drops leftover unknown text when overriding name on titles
with nothing else recognized, and makes extension matching
case-insensitive.
This commit is contained in:
2026-07-14 21:20:26 -07:00
parent ae47d476f3
commit 6f404840f8
3 changed files with 234 additions and 23 deletions

View File

@@ -10,7 +10,8 @@ class TestParserParts(unittest.TestCase):
self.assertEqual(
res,
{
"episode": ["S04E06"],
"season": ["S04"],
"episode": ["E06"],
"resolution": ["1080p"],
"quality": ["WEB-DL"],
"episode_name": ["Live", "Bait"],
@@ -23,11 +24,13 @@ class TestParserParts(unittest.TestCase):
def test_episode_number(self):
title = "Vikings.S01E01.720p.BluRay.4xRus.Eng.HDCLUB"
res = parse_title(title)
self.assertIn("S01E01", res.get("episode", []))
self.assertEqual(["S01"], res.get("season"))
self.assertEqual(["E01"], res.get("episode"))
self.assertEqual(
res,
{
"episode": ["S01E01"],
"season": ["S01"],
"episode": ["E01"],
"resolution": ["720p"],
"quality": ["BluRay"],
"language": ["4xRus", "Eng"],
@@ -59,7 +62,8 @@ class TestParserParts(unittest.TestCase):
res,
{
"name": ["The", "Guild"],
"episode": ["s04e06"],
"season": ["s04"],
"episode": ["e06"],
"episode_name": ["Weird", "Respawn", "by", "Swich"],
"file_extension": ["mkv"],
},
@@ -266,7 +270,8 @@ class TestCornerCases(unittest.TestCase):
res,
{
"name": ["The", "IT", "Crowd"],
"episode": ["S01E04"],
"season": ["S01"],
"episode": ["E04"],
"episode_name": ["The", "Red", "Door", "HR"],
"quality": ["DVDRip"],
"edition": ["HQ.Edition"],
@@ -284,7 +289,8 @@ class TestCornerCases(unittest.TestCase):
{
"name": ["The", "Big", "Bang", "Theory"],
"year": ["2019"],
"episode": ["S12E20"],
"season": ["S12"],
"episode": ["E20"],
"episode_name": ["The", "Decision", "Reverberation"],
"unknown": ["NTb", "EniaHD"],
"resolution": ["1080p"],
@@ -303,7 +309,8 @@ class TestCornerCases(unittest.TestCase):
res,
{
"name": ["The", "Big", "Bang", "Theory"],
"episode": ["S04E06"],
"season": ["S04"],
"episode": ["E06"],
"resolution": ["720p"],
"quality": ["WEB-DL"],
"language": ["eng", "rus"],
@@ -318,8 +325,26 @@ class TestCornerCases(unittest.TestCase):
self.assertEqual(
res,
{
"episode": ["S27E01"],
"season": ["S27"],
"episode": ["E01"],
"episode_name": ["Every", "Man's", "Dream"],
"file_extension": ["mkv"],
},
)
def test_season_episode_divided(self):
title = "Lethal.Weapon.S01.E18.2016.1080p.WEBRip.Rus.Eng.HDCLUB"
res = parse_title(title)
self.assertEqual(
res,
{
"season": ["S01"],
"episode": ["E18"],
"language": ["Rus", "Eng"],
"name": ["Lethal", "Weapon"],
"quality": ["WEBRip"],
"resolution": ["1080p"],
"unknown": ["HDCLUB"],
"year": ["2016"],
},
)