""" This task will set the localizations for a single item. """ import json from connectors.graphql import GraphQLError from connectors.logging import log from constants.localization_definitions import ( PRODUCT_LOCALIZATIONS_FIELD, TRACK_LOCALIZATIONS_FIELD, ) from utils.concurrency_utils import prepare_errors_dict from logic.graphql_logic import ( update_track_localizations, update_product_localizations, ) from utils.graphql_utils import ( format_track_localizations_update, format_product_localization_update, ) from config import REPORT_FAILED_PAYLOADS def task_set_track_localizations( tuid: int, localizations: dict, participations: list, vendor_id: int = None, subaccount_id: int = None, task_id: int = None ) -> tuple: """" Set localizations for a single item. Args: tuid (int): The track unique identifier. localization (dict): The localization data. participations (list): A list of dictionaries containing participant data. vendor_id (int) (optional): The label ID. Defaults to None. subaccount_id (int) (optional): The subaccount ID. Defaults to None. task_id (int) (optional): The task ID if called from a multi-threaded process. Defaults to None. Returns: tuple (dict, dict): The updated track data and the errors. """ error = None errors = None localization_result = None payload = None # Construct a message for the log based on params msg = f'Updating track localizations for {tuid}' msg = vendor_id and f'{msg} on vendor {vendor_id}' or msg msg = subaccount_id and f'{msg} on subaccount {subaccount_id}' or msg msg = task_id and f'Task {task_id}: {msg}' or msg log.debug(msg) try: # Set track localizations localization_result = update_track_localizations( tuid, localizations, participations, vendor_id, subaccount_id, task_id) except GraphQLError as ge: codes = [ error['code'] for error in ge.errors ] messages = [ error['message'] for error in ge.errors ] # Get the payload payload = format_track_localizations_update( tuid, localizations, participations) # Push error metadata to method result object error = { 'task_id': task_id, 'tuid': tuid, 'vendor_id': vendor_id, 'subaccount_id': subaccount_id, 'localization': localizations, 'participations': participations, 'status': 'graphql_error', 'error_codes': codes, 'status_text': 'GraphQL Error', 'messages': messages, 'payload': payload, 'thrown_by': 'update_track_localizations()', 'calling_func': 'task_set_localizations()', } # Notify user of GraphQL error msg = f'GraphQL Call Error - Vendor ' \ f'{vendor_id}, TUID {tuid}: ' \ '"Update Track Localizations" call failed - Error Code: ' \ f'graphql_error - {codes[0]} : GraphQL ' \ f'Error : {messages[0]}' msg = vendor_id and f'{msg} on vendor {vendor_id}' or msg msg = subaccount_id and f'{msg} on subaccount {subaccount_id}' or msg msg = task_id and f'Task {task_id}: {msg}' or msg log.error(msg) error['log_error'] = msg else: if not localization_result: # Get the payload payload = format_track_localizations_update( tuid, localizations, participations) error = { 'tuid': tuid, 'vendor_id': vendor_id, 'subaccount_id': subaccount_id, 'localization': localizations, 'participations': participations, 'status': 'edge_case_error', 'status_text': 'No Response', 'message': msg, 'payload': payload, 'calling_func': 'task_set_localizations()' } # Notify user of edge case error msg = f'No response for TUID {tuid}.' msg = task_id and f'Task {task_id}: {msg}' or msg log.error(msg) error['log_error'] = msg else: # FIXME: This is a workaround for the API not returning the # localization field in the response # Add the localization we just set to the result # as the localization field is not properly returned by the API # due to a bug or limitation in the API for loc_result in localization_result: loc_result[TRACK_LOCALIZATIONS_FIELD] = [ { 'iTunesLanguage': { 'id': localization['languageId'], }, 'trackName': localization['trackName'], 'version': localization.get('version', 'null'), } for localization in localizations ] localization_result = { loc_result['isrc']: loc_result for loc_result in localization_result } if error: # Prepare error dict errors = prepare_errors_dict({}, 'tuid', tuid) errors['track'][tuid].append(error) if REPORT_FAILED_PAYLOADS and payload: # Notify user of offending payload msg = f'Offending payload:\n' \ f"{json.dumps(payload, indent=4, ensure_ascii=False)}" msg = task_id and f'Task {task_id}: {msg}' or msg log.error(msg) # TODO sanity check the result against the payload return localization_result, errors def task_set_product_localizations( product_id: int, localizations: dict, vendor_id: int = None, subaccount_id: int = None, task_id: int = None) -> tuple: """" Set localizations for a single item. Args: product_id (int): The product unique identifier. localization (dict): The localization data. vendor_id (int) (optional): The label ID. Defaults to None. subaccount_id (int) (optional): The subaccount ID. Defaults to None. task_id (int) (optional): The task ID if called from a multi-threaded process. Defaults to None. Returns: tuple (dict, dict): The updated product data and the errors. """ error = None errors = None localization_result = None payload = None # Construct a message for the log based on params msg = f'Updating product localizations for {product_id}' msg = vendor_id and f'{msg} on vendor {vendor_id}' or msg msg = subaccount_id and f'{msg} on subaccount {subaccount_id}' or msg msg = task_id and f'Task {task_id}: {msg}' or msg log.debug(msg) try: # Set product localizations localization_result = update_product_localizations( product_id, localizations, vendor_id, subaccount_id, task_id) except GraphQLError as ge: codes = [ error['code'] for error in ge.errors ] messages = [ error['message'] for error in ge.errors ] # Get the payload payload = format_product_localization_update( product_id, localizations) # Push error metadata to method result object error = { 'task_id': task_id, 'product_id': product_id, 'vendor_id': vendor_id, 'subaccount_id': subaccount_id, 'localization': localizations, 'status': 'graphql_error', 'error_codes': codes, 'status_text': 'GraphQL Error', 'messages': messages, 'payload': payload, 'thrown_by': 'update_product_localizations()', 'calling_func': 'task_set_localizations()', } # Notify user of GraphQL error msg = f'GraphQL Call Error - Vendor ' \ f'{vendor_id}, Product ID {product_id}: ' \ '"Update Product Localizations" call failed - Error Code: ' \ f'graphql_error - {codes[0]} : GraphQL ' \ f'Error : {messages[0]}' msg = vendor_id and f'{msg} on vendor {vendor_id}' or msg msg = subaccount_id and f'{msg} on subaccount {subaccount_id}' or msg msg = task_id and f'Task {task_id}: {msg}' or msg log.error(msg) error['log_error'] = msg else: if not localization_result: # Get the payload payload = format_product_localization_update( product_id, localizations) error = { 'product_id': product_id, 'vendor_id': vendor_id, 'subaccount_id': subaccount_id, 'localization': localizations, 'status': 'edge_case_error', 'status_text': 'No Response', 'message': msg, 'payload': payload, 'calling_func': 'task_set_localizations()' } # Notify user of edge case error msg = f'No response for Product ID {product_id}.' msg = task_id and f'Task {task_id}: {msg}' or msg log.error(msg) error['log_error'] = msg else: # FIXME: This is a workaround for the API not returning the # productLocalization field in the response # Add the localization we just set to the result # as the productLocalization field is not properly returned by the # API due to a bug or limitation in the API localization_result = { PRODUCT_LOCALIZATIONS_FIELD: [ { # "product_id": product_id, "deliveredVersion": localization.get('deliveredVersion', 'null'), "productName": localization['productName'], "iTunesLanguage": { "id": localization['languageId'] } } ] for localization in localizations } localization_result = { product_id: localization_result } if error: # Prepare error dict errors = prepare_errors_dict({}, 'product_id', product_id) errors['product'][product_id].append(error) if REPORT_FAILED_PAYLOADS and payload: # Notify user of offending payload msg = f'Offending payload:\n' \ f"{json.dumps(payload, indent=4, ensure_ascii=False)}" msg = task_id and f'Task {task_id}: {msg}' or msg log.error(msg) # TODO sanity check the result against the payload return localization_result, errors