import os import random from typing import List import pytest from app.logger import log from app.data import load_ids_csv from app.src.tests.insights.tests_common import APPEARANCE_CURRENT PLAYLIST_TYPE = os.environ.get('PLAYLIST_TYPE', 'PRIORITY').upper() PLAYLIST_SAMPLE_SIZE = int(os.environ.get('PLAYLIST_SAMPLE_SIZE', 200)) STORE_ID = 1 if PLAYLIST_TYPE == 'AM' else 286 PAGE_LIMIT = 500 # Map PLAYLIST_TYPE env value to the fixture CSV that backs it. _PLAYLIST_CSV_BY_TYPE = { 'PRIORITY': 'playlists_priority.csv', 'HOURLY': 'playlists_spotify_hourly.csv', 'AM': 'playlists_apple.csv', } def get_playlists_by_type(playlist_type: str) -> List[str]: """Get playlist set based on the playlist type (PRIORITY, HOURLY, AM). `playlist_type` is matched case-insensitively. """ playlist_type = playlist_type.upper() try: playlists = load_ids_csv(_PLAYLIST_CSV_BY_TYPE[playlist_type]) except KeyError: raise ValueError( f"Invalid PLAYLIST_TYPE: {playlist_type}. " f"Must be one of: {sorted(_PLAYLIST_CSV_BY_TYPE)}" ) if not playlists: pytest.skip(f"No playlists defined for type: {playlist_type}") if playlist_type == 'PRIORITY': playlists = sorted(playlists) else: playlists = random.sample(playlists, min(PLAYLIST_SAMPLE_SIZE, len(playlists))) log.info(f"Running tests for {playlist_type} playlists ({len(playlists)} playlists)") return playlists def get_insights_isrc_playlists(isrc, graphql, playlist_types): log.info(f'Getting all playlists for ISRC = {isrc}') variables = {"curatorCountries": [], "isrc": isrc, "limit": PAGE_LIMIT, "offset": 0, "orderBy": "current_position", "orderDir": "asc", "playlistAppearances": APPEARANCE_CURRENT, "playlistTypes": playlist_types, "storeIds": [286], "streamCountries": []} insights_isrc_playlists = graphql.fetch_data('SoundRecordingAnalyticsPlaylistPlacements', variables) # get all playlists for ISRC if not insights_isrc_playlists: log.debug(f'No playlists found for ISRC = {isrc}') return insights_isrc_playlists['globalSoundRecordingByIsrc']['analytics']['playlistPlacements']['placements'] def get_insights_isrc_data(isrc, graphql): log.info(f'Getting ISRC metadata = {isrc}') variables = {"isrc": isrc} song_meta_data = graphql.fetch_data('SongMetadataQuery', variables) recording = song_meta_data['globalSoundRecordingByIsrc'] if not recording: log.warning(f"No metadata found for ISRC = {isrc}") return None return recording def get_isrc_artist(isrc_data): log.info(f'Getting ISRC artist = {isrc_data["isrc"]}') artist_ids = [artist['id'] for artist in isrc_data['globalParticipants']] log.debug(f'Found artists: {artist_ids}') return artist_ids def get_isrc_product(isrc_data): log.info(f'Getting ISRC product = {isrc_data["isrc"]}') products_ids = [product['upc'] for product in isrc_data['catalogProducts']] log.debug(f'Found products: {products_ids}') return products_ids def get_insights_artist_playlists(artist_id, graphql, playlist_types): log.info(f"Getting playlists for Artist = {artist_id}") variables = { "curatorCountries": [], "id": artist_id, "limit": PAGE_LIMIT, "offset": 0, "orderBy": "current_position", "orderDir": "asc", "playlistAppearances": APPEARANCE_CURRENT, "playlistTypes": playlist_types, "storeIds": [286], "streamCountries": [] } insights_artist_playlists = graphql.fetch_data('GlobalParticipantAnalyticsPlaylistPlacements', variables) return insights_artist_playlists['globalParticipantByGpId'][0]['analytics']['playlistPlacements']['placements'] def get_insights_product_playlists(upc, graphql, playlist_types): log.info(f"Getting playlists for Product = {upc}") variables = { "upc": upc, "storeIds": [286], "streamCountries": [], "curatorCountries": [], "playlistTypes": playlist_types, "playlistAppearances": APPEARANCE_CURRENT, "limit": PAGE_LIMIT, "orderBy": "current_position", "orderDir": "asc" } insights_product_playlists = graphql.fetch_data('ProductAnalyticsPlaylistPlacements', variables) return insights_product_playlists['globalProductByUpc']['catalogProduct']['playlistPlacementsV2']['placements'] def find_playlist_in_placements(playlist_id, placements, isrc=None): playlist = next(filter( lambda p: p['playlistId'] == playlist_id and (isrc is None or p['globalSoundRecording']['isrc'] == isrc), placements), None) if playlist is None: log.warning(f"Playlist with ID {playlist_id} not found in placements.") return playlist def fetch_playlist_tracklist(graphql, playlist_id, playlist_store_id): """Helper function to fetch playlist tracklist.""" log.debug(f"------> Fetching playlist tracklist for playlist - {playlist_id}") return graphql.fetch_data( 'PlaylistTracklist', {"date": "", "limit": 1000, "storeId": playlist_store_id, "storePlaylistId": playlist_id, "streamCountries": [] } )