summaryrefslogtreecommitdiffstats
path: root/packages
diff options
context:
space:
mode:
Diffstat (limited to 'packages')
-rw-r--r--packages/meshbay-node/src/meshbay_node/indexer/title_parse.py9
-rw-r--r--packages/meshbay-node/tests/test_title_parse.py18
2 files changed, 27 insertions, 0 deletions
diff --git a/packages/meshbay-node/src/meshbay_node/indexer/title_parse.py b/packages/meshbay-node/src/meshbay_node/indexer/title_parse.py
index 985bd7a..24b423e 100644
--- a/packages/meshbay-node/src/meshbay_node/indexer/title_parse.py
+++ b/packages/meshbay-node/src/meshbay_node/indexer/title_parse.py
@@ -45,6 +45,12 @@ _SEASON_RE = re.compile(
re.IGNORECASE,
)
_SPECIALS_RE = re.compile(r"\b(?:bonus|extras?|specials?)\b", re.IGNORECASE)
+# A bare "S" + number as the *whole* folder name — "S1", "S2", "S02" — a
+# common abbreviated convention distinct from SEASON_WORDS' full words.
+# Anchored to the entire name, not just `\b`-bounded within a longer
+# string, so it only matches a folder actually named just that — never
+# some other word that merely starts with "s" followed by digits.
+_SEASON_ABBREV_RE = re.compile(r"^s(\d{1,2})$", re.IGNORECASE)
_ROMAN_NUMERALS = {
2: "II", 3: "III", 4: "IV", 5: "V", 6: "VI",
@@ -110,6 +116,9 @@ def season_from_folder_name(name: str) -> int | None:
"""
if _SPECIALS_RE.search(name):
return 0
+ m = _SEASON_ABBREV_RE.match(name.strip())
+ if m:
+ return int(m.group(1))
m = _SEASON_RE.search(name)
if not m:
return None
diff --git a/packages/meshbay-node/tests/test_title_parse.py b/packages/meshbay-node/tests/test_title_parse.py
index cf51646..5f0977c 100644
--- a/packages/meshbay-node/tests/test_title_parse.py
+++ b/packages/meshbay-node/tests/test_title_parse.py
@@ -119,6 +119,24 @@ def test_season_folder_book_word_roman_numeral():
assert season_from_folder_name("Livre VI") == 6
+def test_season_folder_bare_s_abbreviation():
+ # A common abbreviated convention distinct from SEASON_WORDS' full
+ # words — found live: a show with "S1"/"S2"/"S3" folders instead of
+ # "Season 1" etc, exactly the shape that grouped its later seasons as
+ # loose individual entries rather than under the show.
+ assert season_from_folder_name("S1") == 1
+ assert season_from_folder_name("S2") == 2
+ assert season_from_folder_name("S02") == 2
+
+
+def test_season_folder_bare_s_abbreviation_does_not_match_inside_a_longer_name():
+ # Anchored to the whole folder name — a real folder that merely starts
+ # with "S" followed by digits somewhere in a longer, unrelated name
+ # must not be read as a season abbreviation.
+ assert season_from_folder_name("S1 Extended Cut") is None
+ assert season_from_folder_name("Something2") is None
+
+
def test_specials_folder_maps_to_season_zero():
assert season_from_folder_name("Specials") == 0
assert season_from_folder_name("Bonus") == 0