"""Interface for managing sound recording versions in s3.""" import os import json from typing import Optional import boto3 from botocore.exceptions import ClientError from soundrecording_utils.metadata.typedload import get_loader from soundrecording_utils.metadata.types import OrchardSoundRecording s3_client = boto3.client('s3') ENV_CONFIG = { 'qa': { 'bucket': 'qa-sr-versions-bucket', 'prefix': '' }, 'prod': { 'bucket': 'prod-sr-versions-bucket', 'prefix': '' } } def _get_sound_recording_version(sound_recording_id, version_id): """Retrieve sound recording data by version. Args: sound_recording_id (str): unique id version_id (str): snapshot unique id Returns: bytes: data if retrieved else None datetime: last modified date else None """ (bucket, prefix) = _config() data = None last_modified = None try: response = s3_client.get_object( Bucket=bucket, Key=f'{prefix}{sound_recording_id}', VersionId=version_id ) data = response['Body'].read() last_modified = response['LastModified'] except ClientError as e: if e.response['Error']['Code'] == 'NoSuchKey' \ or e.response['Error']['Message'] == \ 'Invalid version id specified': return data, last_modified else: raise e return data, last_modified def _get_latest_sound_recording_version(sound_recording_id): """Retrieve sound recording data. Args: sound_recording_id (str): unique id for sound recording Returns: str: latest s3 version unique ID else None bytes: data if retrieved else None datetime: last modified date else None """ (bucket, prefix) = _config() data = None version_id = None last_modified = None try: response = s3_client.get_object( Bucket=bucket, Key=f'{prefix}{sound_recording_id}' ) data = response['Body'].read() version_id = response['VersionId'] last_modified = response['LastModified'] except ClientError as e: if e.response['Error']['Code'] == 'NoSuchKey' \ or e.response['Error']['Message'] == \ 'Invalid version id specified': return version_id, data, last_modified else: raise e return version_id, data, last_modified def _config(): """Get config based on value of Environment var.""" env = os.environ['ENVIRONMENT'] config = ENV_CONFIG[env] return ( config['bucket'], config['prefix'] ) def get_osr(sound_recording_id: str, version_id: Optional[str] = None) -> OrchardSoundRecording: """Get the metadata blob from s3.""" if version_id: (raw_data, _) = _get_sound_recording_version( sound_recording_id, version_id ) else: (_, raw_data, _) = _get_latest_sound_recording_version( sound_recording_id ) loader = get_loader() if raw_data is None: raise ValueError(f'Sound recording {sound_recording_id} not found') osr = loader.load(json.loads(raw_data), OrchardSoundRecording) return osr