from dataclasses import dataclass from typing import Iterable, Tuple from serato_doctor.models.crate import Crate from serato_doctor.models.filesystem import BrokenSymlink from serato_doctor.models.reference import ReferenceResult, TrackReference from serato_doctor.models.track import DiskTrack @dataclass(frozen=True) class Library: """The read-only view of crate references and audio found on disk.""" references: Tuple[TrackReference, ...] tracks: Tuple[DiskTrack, ...] crates: Tuple[Crate, ...] = () broken_symlinks: Tuple[BrokenSymlink, ...] = () @classmethod def build( cls, references: Iterable[TrackReference], tracks: Iterable[DiskTrack], broken_symlinks: Iterable[BrokenSymlink] = (), ) -> "Library": return cls( tuple(references), tuple(tracks), broken_symlinks=tuple(broken_symlinks), ) @classmethod def from_crates( cls, crates: Iterable[Crate], tracks: Iterable[DiskTrack], broken_symlinks: Iterable[BrokenSymlink] = (), ) -> "Library": crate_tuple = tuple(crates) references = tuple( reference for crate in crate_tuple for reference in crate.references ) return cls( references, tuple(tracks), crate_tuple, tuple(broken_symlinks), ) def reconcile_by_filename(self) -> Tuple[ReferenceResult, ...]: disk_names = {track.filename for track in self.tracks} return tuple( ReferenceResult( reference=reference, exists_by_filename=reference.filename in disk_names, ) for reference in self.references )