"""Model Metadata. This model contains one Release class that represent the structure for release and tracks. It also contains two named tuples. One for release and the other for track. """ class BaseModel: """Base model for all models.""" def __eq__(self, other: object) -> bool: """Equality implementation. Returns: bool: Whether self is equivalent to other. """ return self.__dict__ == other.__dict__ class ArtistMeta(BaseModel): """Description of a single artist/participant.""" name: str role: str def __init__(self, name: str, role: str) -> None: """Initialize artist metadata. Args: name (str): Name of artist/participant. role (str): Participation role on recording. """ self.name = name self.role = role def __hash__(self) -> int: """Hashcode calculation. Returns: int: Hashcode value representing contents. """ return hash( ( self.name, self.role, ) ) class GridMeta(BaseModel): """GRAS product identifier data structure.""" grid: str | None product_no: str | None def __init__(self, grid: str | None, product_no: str | None) -> None: """Initialize GRAS product identifier. Args: grid (str | None): GRid. product_no (str | None): Sony product number. """ self.grid = grid self.product_no = product_no def __hash__(self) -> int: """Hashcode calculation. Returns: int: Hashcode value representing contents. """ return hash( ( self.grid, self.product_no, ) ) class ReleaseIdMeta(BaseModel): """Release identifier data structure.""" release_id: int | None upc: str # this is the display_upc def __init__(self, release_id: int | None, upc: str) -> None: """Initialize release identifier. Args: release_id (int | None): Release ID of release. upc (str): Display UPC in art_relations database. """ self.release_id = release_id self.upc = upc def __hash__(self) -> int: """Hashcode calculation. Returns: int: Hashcode value representing contents. """ return hash( ( self.release_id, self.upc, ) ) class ReleaseMeta(BaseModel): """Metadata associated with a release.""" release_id: int | None upc: str grid: str | None product_number: str | None release_name: str | None release_supplemental_info: str | None configuration: str | None repertoire_owner: str | None display_artist_name: str | None gras_status: str | None format: str | None def __init__( self, release_id: int | None, upc: str, # this is display_upc grid: str | None, product_number: str | None, release_name: str | None, release_supplemental_info: str | None, configuration: str | None, repertoire_owner: str | None, display_artist_name: str | None, gras_status: str | None, release_format: str | None, ) -> None: """Initialize release metadata. Args: release_id (int | None): Release identifier. upc (str | None): Release identifier. grid (str): GRid associated with release. product_number (str): Sony product number associated with release. release_name (str): Name of release. release_supplemental_info (str): Supplemental information about the release. configuration (str): GRAS configuration or type of release. repertoire_owner (str): GRAS repertoire_owner. display_artist_name (str): Name of artist. gras_status (str): Status of release in GRAS. release_format (str): Format of release. """ self.release_id = release_id self.upc = upc self.grid = grid self.product_number = product_number self.release_name = release_name self.release_supplemental_info = release_supplemental_info self.configuration = configuration self.repertoire_owner = repertoire_owner self.display_artist_name = display_artist_name self.gras_status = gras_status self.format = release_format def __hash__(self) -> int: """Hashcode calculation. Returns: int: Hashcode value representing contents. """ return hash( ( self.release_id, self.upc, self.grid, self.product_number, self.release_name, self.release_supplemental_info, self.configuration, self.repertoire_owner, self.display_artist_name, self.gras_status, self.format, ) ) class TrackIdMeta(BaseModel): """Track identifier data structure.""" track_id: int | None isrc: str upc: str # this is display_upc def __init__(self, track_id: int | None, isrc: str, upc: str) -> None: """Initialize track identifier. Args: track_id (int | None): Unique track ID of master. isrc (str): ISRC of master. upc (str): Display UPC associated with track. """ self.track_id = track_id self.isrc = isrc self.upc = upc def __hash__(self) -> int: """Hashcode calculation. Returns: int: Hashcode value representing contents. """ return hash( ( self.track_id, self.isrc, self.upc, ) ) class TrackMeta(BaseModel): """Metadata associated with a track.""" def __init__( self, track_id: int | None, upc: str | None, # this is display_upc isrc: str, track_name: str, track_supplemental_info: str, p_line: str, track_type: str, duration: int, main_participants: set[ArtistMeta], product_numbers: set[GridMeta], ) -> None: """Initialize track metadata. Args: track_id (int): Track identifier, may be None. upc (str): Release identifier display_upc associated with track. isrc (str): Master identifier. track_name (str): Name of track. track_supplemental_info (str): Additional name of track, may be None. p_line (str): P-line of track. See also https://kb.ddex.net/display/HBK/PLine+and+CLine duration (int): Track duration in seconds. track_type (str): Type of track. main_participants (iterable of ArtistMeta): Participants. product_numbers (iterable of GridMeta): Product numbers associated with track. """ self.track_id = track_id self.upc = upc # this is actually the display_upc self.isrc = isrc self.track_name = track_name self.track_supplemental_info = track_supplemental_info self.p_line = p_line self.track_type = track_type self.duration = duration self.main_participants = main_participants self.product_numbers = product_numbers def __hash__(self) -> int: """Hashcode calculation. Returns: int: Hashcode value representing contents. """ return hash( ( self.track_id, self.upc, self.isrc, self.track_name, self.duration, self.track_type, self.p_line, self.track_supplemental_info, ) + tuple(self.main_participants) + tuple(self.product_numbers) ) class Release: """Release class container for release metadata.""" def __init__( self, release_meta: ReleaseMeta | None, tracks: set[TrackMeta] | None = None ) -> None: """Initialize release metadata. Args: release_meta (ReleaseMeta): ReleaseMeta class object tracks (dict): Contains a set of TrackMeta class object """ self.metadata: ReleaseMeta | None = release_meta self.tracks: dict[str, TrackMeta] = {} if tracks: for track in tracks: self.add_track(track) def get_track_by_isrc(self, isrc: str) -> TrackMeta | None: """Return the track found by the given ISRC. Args: isrc (str): ISRC for the track Returns: Track (TrackMeta | None): TrackMeta object if found by the provided ISRC """ return self.tracks.get(isrc) def add_track(self, track: TrackMeta) -> None: """Add new track to self.tracks dict. Args: track (TrackMeta): TrackMeta class object """ self.tracks[track.isrc] = track