refactor(release): freeze ParsedRelease + enrich_from_probe returns new instance

ParsedRelease is now @dataclass(frozen=True). The enrichment passes that
used to patch fields in place now produce new instances:

- enrich_from_probe(parsed, info, kb) returns a new ParsedRelease via
  dataclasses.replace (no allocation when no field changed).
- inspect_release rebinds 'parsed' after detect_media_type (wrapped in
  MediaTypeToken — the strict isinstance check now also runs on
  replace) and after enrich_from_probe.

languages becomes a tuple[str, ...] so the VO is properly immutable.
Parser pipeline packs languages as a tuple in the assemble dict.

Callers updated: inspect_release, testing/recognize_folders_in_downloads.py.
Tests updated: 22 enrich_from_probe call sites rebound, language
assertions switched to tuple literals, test_release_fixtures normalizes
result['languages'] back to list for YAML-fixture comparison.

Suite: 1077 passed.
This commit is contained in:
2026-05-21 07:51:49 +02:00
parent 9f1ce94690
commit b7979c0f8b
10 changed files with 101 additions and 63 deletions
+2 -2
View File
@@ -198,7 +198,7 @@ class TestEnrichers:
assert annotated is not None
fields = assemble(annotated, tag, name, _KB)
assert fields["languages"] == ["FRENCH", "MULTI"]
assert fields["languages"] == ("FRENCH", "MULTI")
assert fields["audio_codec"] == "DTS-HD.MA"
assert fields["audio_channels"] == "5.1"
@@ -212,5 +212,5 @@ class TestEnrichers:
assert fields["title"] == "Show"
assert fields["season"] == 1
assert fields["episode"] == 5
assert fields["languages"] == ["FRENCH"]
assert fields["languages"] == ("FRENCH",)
assert fields["media_type"] == "tv_show"