"""Generate DDEX XML for sound recordings.""" from typing import Callable, Dict, Optional from soundrecording_utils.constants.ddex.constants import RuleService from soundrecording_utils.metadata.types import Asset, OrchardSoundRecording def _generate_ddex_v38( osr: OrchardSoundRecording, upload_asset: Optional[Asset], execution_metadata: dict, application_name: str, rule_service: RuleService, takedown: bool, ) -> str: """Lazy loader for DDEX 3.8 generator.""" from .v38.generate import generate_ddex as generate_ddex_v38 return generate_ddex_v38( osr, upload_asset, execution_metadata, application_name, rule_service, takedown, ) def _generate_ddex_v43( osr: OrchardSoundRecording, upload_asset: Optional[Asset], execution_metadata: dict, application_name: str, rule_service: RuleService, takedown: bool, ) -> str: """Lazy loader for DDEX 4.3 generator.""" from .v43.generate import generate_ddex as generate_ddex_v43 return generate_ddex_v43( osr, upload_asset, execution_metadata, application_name, rule_service, takedown, ) # Version-to-function mapping for supported DDEX versions _VERSION_GENERATORS: Dict[ str, Callable[ [ OrchardSoundRecording, Optional[Asset], dict, str, RuleService, bool, ], str, ], ] = { '3.8': _generate_ddex_v38, '4.3': _generate_ddex_v43, } def generate_ddex( osr: OrchardSoundRecording, upload_asset: Optional[Asset], execution_metadata: dict, application_name: str, rule_service: RuleService, selected_version: str = '3.8', takedown: bool = False, ) -> str: """Generate DDEX XML for a given sound recording. Args: osr (OrchardSoundRecording): Sound recording metadata upload_asset (Optional[Asset]): Asset to include in the DDEX, if any execution_metadata (dict): Metadata about the execution context. Should contain 'message_thread_id', 'message_id', and 'timestamp' keys. application_name (str): Name of the application generating the DDEX rule_service (RuleService): Service used for rule evaluation selected_version (str): DDEX version to generate (e.g., '3.8' or '4.3') takedown (bool): Whether this DDEX is for a takedown delivery Returns: str: Generated DDEX XML as a string Raises: ValueError: If the selected version is not supported """ normalized_version = selected_version.strip().lower() generator = _VERSION_GENERATORS.get(normalized_version) if generator is None: supported = ', '.join(sorted(_VERSION_GENERATORS.keys())) raise ValueError( f'Unsupported DDEX version: {selected_version!r}. ' f'Supported versions: {supported}' ) return generator( osr, upload_asset, execution_metadata, application_name, rule_service, takedown, )