""" Object factories for the logic. """ from functools import partial from typing import Callable from ...connectors.db import Client from ...constants import AuditTypes, FlagResolutions from ...models import NewAuditFlag from ...typings import ISRC, UPC, AssetID, AuditID, FlagText, UserID, VideoID from ...utils.misc import is_nan, is_nan_no_cache class Flagger: """Factory for creating audit flaggers. This class allows adding flags to an audit, collecting them in a list, so that they can be inserted into the database later, in a single transaction. """ def __init__(self, audit_id: AuditID, user: UserID): self.audit_id: AuditID = audit_id self.user: UserID = user self.flags: list[NewAuditFlag] = [] def __call__( self, text: FlagText, row_idx: int, *, isrc: ISRC = None, upc: UPC = None, asset_id: AssetID = None, video_id: VideoID = None, details: str = None, resolution: FlagResolutions | None = None, resolution_subtype: FlagResolutions = None, ): """Add a flag to the audit. Args: text: Flag text. row_idx: Row index. isrc: ISRC. upc: UPC. asset_id: YouTube Asset ID. video_id: YouTube Video ID (MV audits only). details: Details. resolution: Resolution, if is auto-resolved, else None. resolution_subtype: Resolution subtype, if is auto-resolved, else None. """ details = ( None if is_nan_no_cache(details) # Sets not hashable, so no cache else details ) self.flags.append( # Ensure that np.nan is casted to None for database # insertion purposes NewAuditFlag( text=None if is_nan(text) else text, row_idx=row_idx, isrc=None if is_nan(isrc) else isrc, upc=None if is_nan(upc) else upc, asset_id=None if is_nan(asset_id) else asset_id, video_id=None if is_nan(video_id) else video_id, details=details, resolution=resolution, resolution_subtype=resolution_subtype, ) ) async def db_factory() -> Client: """Create a database client instance.""" return Client() def logger_factory( db: Client, user: UserID, audit_ids: dict[AuditTypes, AuditID | None] ) -> dict[AuditTypes, Callable | None]: """Create audit loggers for each provided audit type. Args: db: Database client. user: User ID. audit_ids: Dictionary mapping audit types to their audit IDs. """ def create_logger(audit_id: AuditID | None): return partial(db.Audits.get_log, audit_id, user=user) if audit_id else None return { audit_type: create_logger(audit_id) for audit_type, audit_id in audit_ids.items() } def flagger_factory( user: UserID, audit_ids: dict[AuditTypes, AuditID | None], ) -> dict[AuditTypes, Flagger | None]: """Create flaggers for each provided audit type. Args: user: User ID. audit_ids: Dictionary mapping audit types to their audit IDs. """ def create_flagger(audit_id: AuditID | None): return Flagger(user=user, audit_id=audit_id) if audit_id else None return { audit_type: create_flagger(audit_id) for audit_type, audit_id in audit_ids.items() } def meta_setter_factory( db: Client, audit_ids: dict[AuditTypes, AuditID | None] ) -> dict[AuditTypes, Callable | None]: """Create audit meta setters for each provided audit type. Args: db: Database client. audit_ids: Dictionary mapping audit types to their audit IDs. """ def create_meta_setter(audit_id: AuditID | None): return partial(db.Meta.set, audit_id) if audit_id else None return { audit_type: create_meta_setter(audit_id) for audit_type, audit_id in audit_ids.items() }