"""Helpers for track-level metadata in v43.""" from typing import Dict, List, Optional from soundrecording_utils.constants.ddex import constants from soundrecording_utils.metadata.types import Track, TrackParticipation from .e import E from .party_list import generate_party_reference def generate_p_line(p_info: Optional[str]): """Generate DDEX for a PLine from the string.""" return E('PLine', E('PLineText', f'(P) {p_info}')) def generate_display_artist_name(participations: List[TrackParticipation]): """Format primary artist names into single tag.""" display_names = [ x.participant.name for x in participations if x.participated_as.lower() == 'performer' ] if len(display_names) == 0: result = '' elif len(display_names) == 1: result = display_names[0] elif len(display_names) > 3: result = 'Various Artists' else: result = ' & '.join([', '.join(display_names[:-1]), display_names[-1]]) return E('DisplayArtistName', result) def _generate_contributor_artist_roles( sequence_number: int, participations: List[TrackParticipation], ): """Generate Contributor nodes.""" filtered_participations = [ participation for participation in participations if ( participation.participated_as in constants.USER_DEFINED_ARTIST_ROLES or participation.participated_as in constants.CONTRIBUTOR_ARTIST_ROLES ) ] if not filtered_participations: return None elements = [ E( 'ContributorPartyReference', generate_party_reference(participations[0]), ) ] for participation in filtered_participations: if participation.participated_as in constants.CONTRIBUTOR_ARTIST_ROLES: elements.append( E( 'Role', constants.CONTRIBUTOR_ARTIST_ROLES[participation.participated_as], ) ) else: elements.append( E( 'Role', { 'UserDefinedValue': ( constants.USER_DEFINED_ARTIST_ROLES[ participation.participated_as ] ) }, 'UserDefined', ) ) return E( 'Contributor', { 'SequenceNumber': f'{sequence_number}', }, *elements, ) def _generate_display_artist( sequence_number: int, participations: List[TrackParticipation], ): """Generate a DisplayArtist node.""" elements = [ E( 'ArtistPartyReference', generate_party_reference(participations[0]), ) ] if participations: elements.append( E( 'DisplayArtistRole', constants.DISPLAY_ARTIST_LOOKUP_TABLE[ participations[0].participated_as ], ) ) return E( 'DisplayArtist', { 'SequenceNumber': f'{sequence_number}', }, *elements, ) def generate_track_display_artists(track_metadata: Track): """Generate DisplayArtist nodes for a given Track.""" filtered_participations = [ participation for participation in track_metadata.participations if participation.participated_as in constants.DISPLAY_ARTIST_LOOKUP_TABLE ] # Note: As of Python 3.7 dict iteration order is the same as insertion. unique_participants: Dict[str, List[TrackParticipation]] = {} for participation in filtered_participations: participant_uuid = participation.participant.uuid if participant_uuid not in unique_participants: unique_participants[participant_uuid] = [] unique_participants[participant_uuid].append(participation) return [ _generate_display_artist(i + 1, filtered_participations) for (i, (uuid, filtered_participations)) in enumerate( unique_participants.items() ) ] def generate_track_contributor_artists(track_metadata: Track): """Generate Contributor nodes for a given Track.""" filtered_participations = [ participation for participation in track_metadata.participations if ( participation.participated_as in constants.CONTRIBUTOR_ARTIST_ROLES or participation.participated_as in constants.USER_DEFINED_ARTIST_ROLES ) ] # Note: As of Python 3.7 dict iteration order is the same as insertion. unique_participants: Dict[str, List[TrackParticipation]] = {} for participation in filtered_participations: participant_uuid = participation.participant.uuid if participant_uuid not in unique_participants: unique_participants[participant_uuid] = [] unique_participants[participant_uuid].append(participation) result = [] for i, (_uuid, participations) in enumerate(unique_participants.items()): contributors = _generate_contributor_artist_roles(i + 1, participations) if contributors is not None: result.append(contributors) return result