"""Sound Recording Activity schema.""" from typing import Any from marshmallow import Schema, fields, validate class DspName(fields.String): """String field representing DSP names.""" def __init__(self, *args: Any, **kwargs: Any) -> None: """Override fields.String and add additional validation.""" super().__init__(*args, **kwargs) self.validators.append(validate.OneOf(['spotify', 'itunes/apple'])) class Track(Schema): """Schema for track. Properties: - id (int): unique internal identifier of track - vendor_id (int): unique internal identifier of vendor - subaccount_id (int): unique internal identifier of subaccount - isrc (str): unique id of recording (optional) """ id = fields.Integer(required=True, strict=True) vendor_id = fields.Int(required=True, strict=True) subaccount_id = fields.Int(required=True, strict=True, allow_none=True) isrc = fields.String(required=False) class SoundRecording(Schema): """Schema for sound recording. Properties: - isrc (str): unique id of recording - tracks (list): Track objects """ isrc = fields.String(required=True) tracks = fields.Nested(Track, many=True) class Playlist(Schema): """Schema for playlist. Properties: - id (str): identifier for playlist - rank (int): importance of playlist - dsp (str): service playlist exists on """ id = fields.String(required=True) rank = fields.Integer(required=True) dsp = DspName(required=True) store_id = fields.Integer(required=False) name = fields.String(required=True) class PlaylistPlacement(Schema): """Schema for playlist placement event. Properties: - datetime (str): ISO formatted datetime string - sound_recording (SoundRecording): see above - playlist (Playlist): see above """ timestamp = fields.DateTime(required=True, format='%Y-%m-%d %H:%M:%S') sound_recording = fields.Nested(SoundRecording, required=True) playlist = fields.Nested(Playlist, required=True) class TrendingTrack(Schema): """Schema for trending track event. Properties: - date (str): ISO formatted date of event - track (Track): see above - dsp (str): service playlist exists on - avg_streams (int): past daily average streams on track - day_streams (int): spike day streams on track """ date = fields.DateTime(required=True, format='%Y-%m-%d') region = fields.String(required=True) dsp = DspName(required=True) track = fields.Nested(Track, required=True) day_streams = fields.Integer(required=True) percent_diff = fields.Integer(required=True)