refactor(domain): freeze Movie and Episode, switch track collections to tuple
Movie and Episode become @dataclass(frozen=True, eq=False), with audio_tracks/subtitle_tracks held as tuple[...] instead of list[...]. Identity-based equality is preserved via the existing __eq__/__hash__. __post_init__ coercion (imdb_id, title, season_number, episode_number) uses object.__setattr__ to stay compatible with frozen. The MediaWithTracks mixin contract is updated to tuple accordingly. Callers projecting enrichment results (probe output, file metadata) now rebuild via dataclasses.replace(...) — same pattern recently adopted for ParsedRelease. Season and TVShow stay mutable for now: freezing the aggregate root would cascade a full reconstruction on every add_episode, deferred.
This commit is contained in:
@@ -77,6 +77,19 @@ callers).
|
||||
|
||||
### Changed
|
||||
|
||||
- **`Movie` and `Episode` are now frozen dataclasses.** Both entities
|
||||
hold their track collections as `tuple[AudioTrack, ...]` and
|
||||
`tuple[SubtitleTrack, ...]` instead of mutable lists, and are
|
||||
`@dataclass(frozen=True, eq=False)` (identity-based equality
|
||||
preserved via `__eq__`/`__hash__`). `__post_init__` coercion uses
|
||||
`object.__setattr__` for the `imdb_id` / `title` /
|
||||
`season_number` / `episode_number` normalizations. To project
|
||||
enrichment results (probe output, file metadata) callers now rebuild
|
||||
via `dataclasses.replace(...)`. Pattern aligned with the recent
|
||||
`ParsedRelease` freeze. `MediaWithTracks` mixin contract updated to
|
||||
`tuple` accordingly. `Season` and `TVShow` remain mutable for now —
|
||||
freezing the aggregate root would cascade a full reconstruction on
|
||||
every `add_episode`, deferred.
|
||||
- **`SubtitleCandidate` renamed to `SubtitleScanResult`.** The old name
|
||||
conflated "this might become a placed subtitle" with "this is what a
|
||||
scan pass produced". The class is the output of a scan/identify pass
|
||||
|
||||
Reference in New Issue
Block a user