Files
alfred/alfred/infrastructure/persistence/dot_alfred/__init__.py
T
francwa c7c11180d9 feat(persistence): add DotAlfredTVShowRepository (filesystem-backed)
Step 3 of specs/dot_alfred.md. Concrete TVShowRepository
implementation reading and writing per-show .alfred YAML files under
a configurable library_root. Writes are atomic (.alfred.tmp +
os.replace), reads tolerate corrupted/wrong-schema sidecars (log +
skip), and the repo never invents a folder name — save(show)
requires the target folder to exist beforehand (raises
ShowFolderUnknown otherwise), matching the spec's
MediaOrganizer-then-sidecar split.

Cold folders without a sidecar are skipped by find_all and yield
None from find_by_imdb_id — the upcoming rescan_show tool (step 4)
will own the opt-in rebuild path.

A small bridge module translates between the rich domain TVShow
(AudioTrack/SubtitleTrack with full ffprobe minutiae) and the
compact sidecar shape (language-only audio, embedded-only subs with
type derived from is_forced). The bridge is intentionally lossy on
probe details the sidecar does not store, per the spec's
factual-only philosophy.

20 integration tests on tmp_path: round-trip save/find,
cold-folder/unknown-id returns, find_all skipping
(corrupted/schema-violating sidecars), delete/exists, atomic write
(no .alfred.tmp leftover), overwrite, and folder-name fallbacks
(get_folder_name guess + full-scan rescue when renamed).
2026-05-22 17:16:41 +02:00

43 lines
1.3 KiB
Python

"""`.alfred` sidecar persistence layer.
Implements the per-show YAML sidecar described in
``specs/dot_alfred.md``. The sidecar is a single file named ``.alfred``
posed at the root of a show's directory, containing the full aggregate
in a factual-only schema.
Public surface:
* :mod:`.sidecar` — DTOs (``ShowSidecar``, ``SeasonSidecar``,
``EpisodeSidecar``, ``SubtitleEntry``) that mirror the YAML schema.
* :mod:`.serializer` — ``serialize`` / ``deserialize`` functions
converting between DTOs and plain dicts (YAML-ready).
* :mod:`.bridge` — ``to_sidecar`` / ``from_sidecar`` translating
between the domain :class:`TVShow` aggregate and the sidecar DTOs.
* :mod:`.repository` — :class:`DotAlfredTVShowRepository`, the
concrete filesystem-backed implementation of the abstract
:class:`TVShowRepository` port.
"""
from .bridge import from_sidecar, to_sidecar
from .repository import DotAlfredTVShowRepository, ShowFolderUnknown
from .serializer import deserialize, serialize
from .sidecar import (
EpisodeSidecar,
SeasonSidecar,
ShowSidecar,
SubtitleEntry,
)
__all__ = [
"deserialize",
"serialize",
"from_sidecar",
"to_sidecar",
"DotAlfredTVShowRepository",
"ShowFolderUnknown",
"EpisodeSidecar",
"SeasonSidecar",
"ShowSidecar",
"SubtitleEntry",
]