Skip to content

Handle season ranges in folder names, and reject if unparsable#434

Open
slbyrnes1 wants to merge 1 commit intomaxdorninger:masterfrom
slbyrnes1:fix/season-parser-and-orphaned-torrents
Open

Handle season ranges in folder names, and reject if unparsable#434
slbyrnes1 wants to merge 1 commit intomaxdorninger:masterfrom
slbyrnes1:fix/season-parser-and-orphaned-torrents

Conversation

@slbyrnes1
Copy link

@slbyrnes1 slbyrnes1 commented Feb 14, 2026

Hello!

First, thank you so much for writing and maintaining this software. I recently dove into the world of the *Arr suite, and after playing with Sonarr and Radarr a couple weeks, it's been a delight picking up MediaManager as a replacement.

I hope you don't mind I opened a PR for this. Feel free to reject it or let me know how I can improve it. I reviewed the contributing guide and, while this is more than a couple lines, I ended up just "doing the work" first alongside Claude Code as it helped me learn and understand this project.

AI disclaimer: I used Claude Code to help me navigate and learn the project. This code was written by Claude with modifications by me, after planning mode where I gave direction and instructions. If you feel the need to reject the PR for that reason, I understand. (I'm a python developer by trade, for what it is worth). The rest of this PR description was also mostly written by Claude, with my editing.

Summary

This fixes a couple "bugs" that were causing import issues for me:

  1. Season parser fails on range-style torrent titles — The IndexerQueryResult.season regex only handled exactly 1 or 2 \bS(\d+)\b matches. Titles with season ranges like S01-8 S01-S08 produced 3 matches, which fell through to the else branch and returned []. This caused torrents to download without any SeasonFile association.

  2. Multi-episode files fail to match during import — The import_episode regex used [. ] as the separator after the episode number, so multi-episode files like S09E19-E20 - Double Episode Special.mkv never matched when importing E19 (the - after E19 isn't . or space).

Observed behavior

Torrents downloaded via the UI were never imported by the scheduled job. Logs showed:

WARNING - torrent My TV Show (2026) S01-8 S01-S08 (1080p BluRay x265 is not a tv torrent, skipping import.

For multi-episode files, the import job silently skipped the file because the regex couldn't match:

Pattern: .*[. ]S0?9E0?19[. ].*
File:    Another TV Show - S09E19-E20 - Double Episode Special.mkv
                            ^^ hyphen not in [. ]

Changes

media_manager/indexer/schemas.py — Improved IndexerQueryResult.season parser:

  • Try explicit range first (S01-S08[1,2,...,8])
  • Try shorthand range (S01-8[1,2,...,8])
  • Fall back to collecting all individual S## matches, deduplicated
  • Titles without any S## pattern still return []

media_manager/tv/service.py — Updated import_episode regex:

  • Added (?:\d+-?E)? to optionally match the first episode in a multi-episode range (e.g., 19-E before 20)
  • Changed trailing separator from [. ] to [. -] to allow hyphen

tests/test_season_parser.py — Added parametrized tests for the season parser covering single seasons, explicit ranges, shorthand ranges, and titles that should return empty.

Summary by CodeRabbit

Release Notes

  • New Features

    • Enhanced episode and season detection with support for flexible numbering formats
    • Added multilingual support for season identification across multiple languages
  • Tests

    • Comprehensive test coverage added for episode and season import workflows
    • New test suite for season parsing validation
  • Chores

    • Added make test command for running the test suite
    • Updated development tooling configuration

@maxdorninger
Copy link
Owner

Hi!

thanks for taking the time to contribute :)

I think some of the changes were already implemented in another PR that was just merged. It would still be great if you could rebase this onto master so I can merge it.

@maxdorninger maxdorninger linked an issue Feb 24, 2026 that may be closed by this pull request
@slbyrnes1 slbyrnes1 force-pushed the fix/season-parser-and-orphaned-torrents branch from cd156f4 to a3acd91 Compare February 27, 2026 02:51
@coderabbitai
Copy link

coderabbitai bot commented Feb 27, 2026

Note

Reviews paused

It looks like this branch is under active development. To avoid overwhelming you with review comments due to an influx of new commits, CodeRabbit has automatically paused this review. You can configure this behavior by changing the reviews.auto_review.auto_pause_after_reviewed_commits setting.

Use the following commands to manage reviews:

  • @coderabbitai resume to resume automatic reviews.
  • @coderabbitai review to trigger a single review.

Use the checkboxes below for quick actions:

  • ▶️ Resume reviews
  • 🔍 Trigger review

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info

Configuration used: Repository UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between bccdf55 and 39226e6.

📒 Files selected for processing (7)
  • Makefile
  • media_manager/indexer/schemas.py
  • media_manager/tv/service.py
  • ruff.toml
  • tests/__init__.py
  • tests/test_season_parser.py
  • tests/test_tv_service.py
🚧 Files skipped from review as they are similar to previous changes (3)
  • ruff.toml
  • media_manager/tv/service.py
  • tests/test_season_parser.py
📜 Recent review details
🧰 Additional context used
🪛 checkmake (0.2.2)
Makefile

[warning] 15-15: Missing required phony target "all"

(minphony)


[warning] 15-15: Missing required phony target "clean"

(minphony)

🔇 Additional comments (8)
Makefile (1)

15-15: LGTM!

The new test target is well-structured with $(ARGS) passthrough for flexibility. The .PHONY declaration is correctly updated. The static analysis warnings about missing all and clean targets can be safely ignored as this Makefile is for development workflow orchestration rather than a traditional build system.

Also applies to: 27-28, 51-55

media_manager/indexer/schemas.py (2)

72-75: LGTM!

The multi-match season parsing with findall, deduplication via set(), and sorting handles complex titles like "Show S01 S03 S05 1080p" correctly. This resolves the PR objective of handling multiple season indicators.


77-80: The concern is unfounded. The code correctly guards against the stated scenario through execution order: "The Series 7 Adventures S01E05" matches the SxxExx pattern at step 1 and returns [1] immediately, never reaching the multilingual word pattern at step 4. The "Series" keyword matching is intentional (confirmed by test line 45), and word boundaries (\b) prevent false positives in compound show names. No action required.

Likely an incorrect or invalid review comment.

tests/test_tv_service.py (5)

12-55: LGTM!

The helper functions are well-structured and provide clean, reusable test fixtures. The defaults are sensible and the factory pattern makes tests readable.


61-198: LGTM!

Comprehensive test coverage for import_episode:

  • Parametrised tests for separator variants cover the regex fix mentioned in the PR objectives
  • Edge cases for missing/wrong episodes are well-tested
  • Subtitle handling tests verify both positive and negative cases

The test structure with fixtures and parametrisation follows pytest best practices.


203-268: LGTM!

Good coverage of import_season functionality including success, partial failure, directory creation, and empty season edge case. The directory path assertion on line 255 validates the expected naming convention.


274-379: LGTM!

Thorough end-to-end testing of the torrent import flow. The _setup helper method cleanly configures the mock chain for episode file processing. Tests cover:

  • Success/failure state transitions
  • Torrent persistence behaviour
  • Notification dispatch with correct titles
  • Multiple episode handling with mixed results
  • Early exit when no files exist

1-8: LGTM!

Imports are clean and necessary for the test module.


📝 Walkthrough

Walkthrough

This pull request enhances season and episode parsing logic to support flexible numbering and multilingual season variants, improves regex pattern matching in TV service imports, adds comprehensive test coverage for TV service functionality, and introduces a test target to the build system.

Changes

Cohort / File(s) Summary
TV Service Pattern Enhancements
media_manager/tv/service.py, media_manager/indexer/schemas.py
Replaced hard-coded regex patterns with flexible se_marker pattern supporting variable S/E numbering. Enhanced season extraction to collect all individual season indicators (multi-match collection with deduplication and sorting), support multilingual variants (Season, Saison, Series, Stagione), and improved subtitle pattern matching. Public signatures remain unchanged.
TV Service Test Coverage
tests/test_season_parser.py, tests/test_tv_service.py
Added comprehensive test modules verifying season parsing logic across patterns (single seasons, ranges, em-dash variants, multiple seasons) and TV service import workflows (episode imports, season imports, torrent-based imports) with fixture helpers, mocks for filesystem/repository/indexer interactions, and edge case validation.
Build and Linting Configuration
Makefile, ruff.toml
Added new public test target to Makefile running pytest via uv; updated PHONY list. Introduced per-file linting ignores for tests/** directory to skip annotations (ANN) and assertion (S101) checks.

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~25 minutes

Poem

A rabbit hops through patterns new and true, 🐰
With seasons parsed in every tongue's debut,
From S01 to Stagione, all aligned,
The test cases verify by design—
Flexible formats, multilingual might! ✨

🚥 Pre-merge checks | ✅ 2 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 2.56% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (2 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title clearly and accurately summarises the main changes: handling season ranges in folder names and rejecting unparsable entries, which aligns with the core objectives of fixing season-range parsing issues.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Post copyable unit tests in a comment

Comment @coderabbitai help to get the list of available commands and usage tips.

Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (2)
media_manager/indexer/schemas.py (1)

57-130: ⚠️ Potential issue | 🔴 Critical

Critical: Unresolved Git merge conflict markers must be removed.

The file contains merge conflict markers (<<<<<<< HEAD, =======, >>>>>>> bf4cd4e) which will cause a syntax error and prevent the code from running. This aligns with the maintainer's request to rebase the branch onto master.

Additionally, the two conflicting implementations have different capabilities:

  • HEAD version (lines 58-107): Supports S01E01, range S01-S03, pack S01, and Season 1 patterns, plus episode parsing
  • PR branch version (lines 109-129): Supports explicit range S01-S08, shorthand S01-8, and individual S## matches

The PR branch version appears to lose support for the Season X format (e.g., "Show Season 3 Complete" would return [] instead of [3]) and does not include the episode computed field.

Please resolve the merge conflicts by rebasing onto master and deciding which logic to keep or how to merge them appropriately.

media_manager/tv/service.py (1)

711-714: ⚠️ Potential issue | 🟡 Minor

Inconsistency with import_episode regex pattern.

Both import_episode and import_episode_files serve equivalent purposes but use different regex patterns. The import_episode pattern supports multi-episode formats (E1-2E3) and hyphen separators, while import_episode_files uses the older pattern without these features. This means they handle different filename formats despite serving the same role.

Update import_episode_files to match the pattern from import_episode for consistency:

Suggested fix
         pattern = (
-            r".*[. ]S0?" + str(season.number) + r"E0?" + str(episode.number) + r"[. ].*"
+            r".*[. ]S0?" + str(season.number) + r"E(?:\d+-?E)?0?" + str(episode.number) + r"[. -].*"
         )
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@media_manager/tv/service.py` around lines 711 - 714, The regex used in
import_episode_files is out of sync with import_episode: update the pattern and
subtitle_pattern definitions in import_episode_files to match import_episode’s
more flexible regex (supporting multi-episode ranges like E1-2E3 and hyphen
separators). Specifically, replace the old pattern construction with the same
logic used in import_episode so the variable pattern (built from season.number
and episode.number) and subtitle_pattern (adding language capture + .srt) match
import_episode’s regex behavior; ensure import_episode_files uses the same
symbol names pattern and subtitle_pattern so both functions handle the same
filename formats.
🧹 Nitpick comments (3)
media_manager/indexer/schemas.py (1)

119-121: Minor edge case consideration for shorthand range validation.

The condition if end > start correctly prevents invalid ranges like S05-3 from being interpreted as ranges. However, explicit ranges like S05-S03 on line 112 don't have this validation and would produce list(range(5, 4)) which is an empty list.

Consider adding similar validation for explicit ranges for consistency:

💡 Suggested improvement
         range_match = re.search(r"\bS(\d+)\s*-\s*S(\d+)\b", self.title, re.IGNORECASE)
         if range_match:
-            return list(range(int(range_match.group(1)), int(range_match.group(2)) + 1))
+            start, end = int(range_match.group(1)), int(range_match.group(2))
+            if start <= end:
+                return list(range(start, end + 1))
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@media_manager/indexer/schemas.py` around lines 119 - 121, The explicit-range
parsing block that parses patterns like "S05-S03" should mirror the shorthand
validation: after extracting start and end (the same start, end variables used
in the shorthand block), ensure you check that end > start before returning
list(range(start, end + 1)); if the check fails, handle it consistently (e.g.,
return an empty list or raise a ValueError) so explicit ranges do not produce an
unintended empty range.
tests/test_season_parser.py (1)

20-31: Consider adding test coverage for additional patterns.

The test cases cover the main scenarios well, but a few additional cases would improve confidence:

  1. S##E## format: Titles with episode numbers (e.g., "Show S01E05 720p"[1])
  2. Invalid/reversed range: Edge case like "Show S05-3 720p" → should probably return [5] (falls through to individual match)
  3. Multiple individual seasons: "Show S01 S03 S05 720p"[1, 3, 5]
💡 Suggested additional test cases
`@pytest.mark.parametrize`(
    "title, expected",
    [
        # ... existing cases ...
        ("Show S01E05 720p", [1]),  # with episode number
        ("Show S05-3 720p", [5]),   # invalid range falls back to individual
        ("Show S01 S03 S05 720p", [1, 3, 5]),  # multiple individual seasons
    ],
)
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@tests/test_season_parser.py` around lines 20 - 31, Add three new
parameterized test cases to the existing parametrize block in
tests/test_season_parser.py for the season parser: include a title with an
episode number ("Show S01E05 720p" expecting [1]), an invalid/reversed range
("Show S05-3 720p" expecting [5] to treat as individual season), and a
multiple-individual-seasons case ("Show S01 S03 S05 720p" expecting [1,3,5]);
update the same parametrize list (the "title, expected" block) so the test
function that consumes these parameters validates these additional patterns
alongside the existing cases.
media_manager/tv/service.py (1)

614-619: Regex may not match shorthand multi-episode format for the second episode.

The updated regex E(?:\d+-?E)?0?{episode} correctly handles formats like S09E19-E20 but won't match the shorthand format S09E19-20 when searching for episode 20.

For example, with S01E01-02.mkv:

  • Finding episode 1: ✓ (matches E01 directly)
  • Finding episode 2: ✗ (E(?:\d+-?E)?0?2 cannot match E01-02 since the optional group requires E after digits)

If shorthand ranges like E01-02 are common in your media library, consider extending the pattern:

💡 Suggested improvement
         pattern = (
             r".*[. ]S0?"
             + str(season.number)
-            + r"E(?:\d+-?E)?0?"
+            + r"E(?:\d+-?E?)?0?"
             + str(episode_number)
             + r"[. -].*"
         )

This change makes the E within the optional group itself optional, allowing both E19-E20 and E19-20 formats.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@media_manager/tv/service.py` around lines 614 - 619, The regex in the pattern
variable used when locating episodes (built near season.number and
episode_number) doesn't match shorthand ranges like "S01E01-02" because the
optional group forces an 'E' after the first episode; update the optional group
so the second 'E' is optional (e.g., make the group something like (?:\d+-?E?)?
or equivalent) so both "E19-E20" and "E19-20" forms are accepted while keeping
the rest of the pattern (the leading "E", optional zero-padding, and
episode_number insertion) intact in the same spot where pattern is constructed.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Outside diff comments:
In `@media_manager/tv/service.py`:
- Around line 711-714: The regex used in import_episode_files is out of sync
with import_episode: update the pattern and subtitle_pattern definitions in
import_episode_files to match import_episode’s more flexible regex (supporting
multi-episode ranges like E1-2E3 and hyphen separators). Specifically, replace
the old pattern construction with the same logic used in import_episode so the
variable pattern (built from season.number and episode.number) and
subtitle_pattern (adding language capture + .srt) match import_episode’s regex
behavior; ensure import_episode_files uses the same symbol names pattern and
subtitle_pattern so both functions handle the same filename formats.

---

Nitpick comments:
In `@media_manager/indexer/schemas.py`:
- Around line 119-121: The explicit-range parsing block that parses patterns
like "S05-S03" should mirror the shorthand validation: after extracting start
and end (the same start, end variables used in the shorthand block), ensure you
check that end > start before returning list(range(start, end + 1)); if the
check fails, handle it consistently (e.g., return an empty list or raise a
ValueError) so explicit ranges do not produce an unintended empty range.

In `@media_manager/tv/service.py`:
- Around line 614-619: The regex in the pattern variable used when locating
episodes (built near season.number and episode_number) doesn't match shorthand
ranges like "S01E01-02" because the optional group forces an 'E' after the first
episode; update the optional group so the second 'E' is optional (e.g., make the
group something like (?:\d+-?E?)? or equivalent) so both "E19-E20" and "E19-20"
forms are accepted while keeping the rest of the pattern (the leading "E",
optional zero-padding, and episode_number insertion) intact in the same spot
where pattern is constructed.

In `@tests/test_season_parser.py`:
- Around line 20-31: Add three new parameterized test cases to the existing
parametrize block in tests/test_season_parser.py for the season parser: include
a title with an episode number ("Show S01E05 720p" expecting [1]), an
invalid/reversed range ("Show S05-3 720p" expecting [5] to treat as individual
season), and a multiple-individual-seasons case ("Show S01 S03 S05 720p"
expecting [1,3,5]); update the same parametrize list (the "title, expected"
block) so the test function that consumes these parameters validates these
additional patterns alongside the existing cases.

ℹ️ Review info

Configuration used: Repository UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between f525399 and a3acd91.

📒 Files selected for processing (4)
  • media_manager/indexer/schemas.py
  • media_manager/tv/service.py
  • tests/__init__.py
  • tests/test_season_parser.py
📜 Review details
🧰 Additional context used
🧬 Code graph analysis (2)
media_manager/tv/service.py (2)
media_manager/indexer/schemas.py (1)
  • season (56-56)
tests/test_season_parser.py (1)
  • season (16-17)
tests/test_season_parser.py (1)
media_manager/indexer/schemas.py (2)
  • IndexerQueryResult (13-56)
  • season (56-56)
🔇 Additional comments (1)
tests/test_season_parser.py (1)

5-17: LGTM!

The test fixture structure is clean and well-organised. The DEFAULTS dict provides all required fields, and the season() helper function makes tests readable and maintainable.

@slbyrnes1 slbyrnes1 force-pushed the fix/season-parser-and-orphaned-torrents branch 2 times, most recently from 89c3901 to 4e6e71b Compare February 27, 2026 05:07
Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🧹 Nitpick comments (1)
media_manager/tv/service.py (1)

602-610: Good refactoring; consider tightening the episode number matching to avoid false positives.

Centralising the pattern is a good improvement, and the [. -] fix correctly addresses multi-episode filenames like S09E19-E20 - Title.mkv.

However, the (?:\d+-?E?)?0?{episode} portion can produce false positives when the target episode number is a substring of the actual episode number. For example, when matching episode 1 against filename Show.S01E11.mkv:

  • (?:\d+-?E?)? matches 1 (first digit only)
  • 0? matches empty
  • 1 matches the second 1
  • [. -] matches .

This would incorrectly identify E11 as E01.

This is a pre-existing issue, so it's not a blocker for this PR, but worth considering a fix since you're centralising the pattern.

🔧 Suggested fix using zero-padded format
     `@staticmethod`
     def _episode_file_pattern(season_number: int, episode_number: int) -> str:
         return (
-            r".*[. ]S0?"
-            + str(season_number)
-            + r"E(?:\d+-?E?)?0?"
-            + str(episode_number)
+            r".*[. ]S"
+            + f"{season_number:02d}"
+            + r"E(?:\d{2,3}-?E?)?"
+            + f"{episode_number:02d}"
             + r"[. -].*"
         )

This enforces zero-padded two-digit format (the standard for media files), eliminating substring false matches.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@media_manager/tv/service.py` around lines 602 - 610, The current
_episode_file_pattern allows substring matches (e.g., E11 matching target
episode 1); change the episode portion to require a two-digit zero-padded
episode token so matches are exact. In _episode_file_pattern(season_number,
episode_number) format episode_number as two digits (e.g., "01", "11") and
update the regex to expect two digits for the episode (use \d{2} where
applicable) instead of the current optional "0?" + str(episode_number) and
loosened digit group; keep the existing multi-episode/range handling (the
(?:\d+-?E?)? group) but constrain it to two-digit numbers (e.g., \d{2}) so E11
cannot be misread as E01 when matching episode 1.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Nitpick comments:
In `@media_manager/tv/service.py`:
- Around line 602-610: The current _episode_file_pattern allows substring
matches (e.g., E11 matching target episode 1); change the episode portion to
require a two-digit zero-padded episode token so matches are exact. In
_episode_file_pattern(season_number, episode_number) format episode_number as
two digits (e.g., "01", "11") and update the regex to expect two digits for the
episode (use \d{2} where applicable) instead of the current optional "0?" +
str(episode_number) and loosened digit group; keep the existing
multi-episode/range handling (the (?:\d+-?E?)? group) but constrain it to
two-digit numbers (e.g., \d{2}) so E11 cannot be misread as E01 when matching
episode 1.

ℹ️ Review info

Configuration used: Repository UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 89c3901 and 4e6e71b.

📒 Files selected for processing (4)
  • media_manager/indexer/schemas.py
  • media_manager/tv/service.py
  • tests/__init__.py
  • tests/test_season_parser.py
🚧 Files skipped from review as they are similar to previous changes (1)
  • tests/test_season_parser.py
📜 Review details
🔇 Additional comments (3)
media_manager/indexer/schemas.py (1)

72-75: LGTM!

The refactored season extraction logic correctly handles multiple season pack indicators (e.g., S01 S03 S05) by collecting all matches, deduplicating with set(), and returning a sorted list. The placement after the range-matching block ensures explicit ranges like S01-S08 are handled first.

media_manager/tv/service.py (2)

624-624: LGTM!

Correctly uses the new centralised helper method.


715-715: LGTM!

Correctly uses the new centralised helper method, consistent with the usage in import_episode.

@slbyrnes1
Copy link
Author

Thanks so much!

I realized that the r"E(?:\d+-?E?)?0?" regex I was suggesting for ranges is flawed. I plan to update this MR one more time before it's ready for merge.

@slbyrnes1 slbyrnes1 force-pushed the fix/season-parser-and-orphaned-torrents branch from 4e6e71b to bccdf55 Compare March 1, 2026 22:38
Season parser now collects all individual season tokens (S01 S03 S05)
via re.findall instead of re.search, returning a sorted, deduplicated
list. Also adds multi-language season keyword support (saison, series,
stagione) to match Sonarr parity.

Episode file-matching regex replaces [. ] separator anchors with
negative lookbehind/lookahead word-boundary assertions, preventing
false positives on adjacent digits. Subtitle pattern is now
end-of-string anchored with a flexible separator before the language
code.

Adds a parametrized test suite covering all parser cases and import
method behavior (separator variants, zero-padding, wrong-episode
rejection, subtitle extraction), a `make test` target, and ruff
per-file ignores for the tests/ directory.
@slbyrnes1 slbyrnes1 force-pushed the fix/season-parser-and-orphaned-torrents branch from bccdf55 to 39226e6 Compare March 1, 2026 23:58
@slbyrnes1
Copy link
Author

Wow! You've done a lot of amazing work since I opened my very random PR two weeks ago, hah. At this point, I think the biggest thing this PR provides are just some pytests, but I did also enable the season parsing to understand a couple more cases.

I also realized I forgot to put this back in draft :) oops!

This PR can be considered "ready" now.

Season parser now collects all individual season tokens (S01 S03 S05)
via re.findall instead of re.search, returning a sorted, deduplicated
list. Also adds multi-language season keyword support (saison, series,
stagione) to match Sonarr parity.

Episode file-matching regex replaces [. ] separator anchors with
negative lookbehind/lookahead word-boundary assertions, preventing
false positives on adjacent digits. Subtitle pattern is now
end-of-string anchored with a flexible separator before the language
code.

Adds a parametrized test suite covering all parser cases and import
method behavior (separator variants, zero-padding, wrong-episode
rejection, subtitle extraction), a `make test` target, and ruff
per-file ignores for the tests/ directory.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[REQUEST] Support wider range of matching for Seasons

2 participants