from __future__ import annotations from typing import Any DOWNLOAD_LANE = "download" GENERAL_LANE = "general" JOB_STAGE_SEQUENCES: dict[str, tuple[str, ...]] = { "catalog_sync": ("collect", "sync", "download"), "collect_only": ("collect",), "sync_only": ("sync",), "sync_download": ("sync", "download"), "download_only": ("download",), "upload_only": ("upload",), "download_upload": ("download", "upload"), } def job_has_stage(job_type: str, stage_type: str) -> bool: sequence = JOB_STAGE_SEQUENCES.get(str(job_type), ()) return str(stage_type) in sequence def job_lane_type(job_type: str) -> str: if job_has_stage(job_type, "download"): return DOWNLOAD_LANE return GENERAL_LANE def primary_stage_type(job_type: str) -> str | None: for stage_type in ("download", "upload", "sync", "collect"): if job_has_stage(job_type, stage_type): return stage_type return None def display_name(job_type: str, playlist_scope: dict[str, Any] | None = None) -> str: playlist_ids = (playlist_scope or {}).get("playlist_ids") is_scoped = isinstance(playlist_ids, list) and len(playlist_ids) > 0 mapping = { "catalog_sync": "Full Pipeline", "collect_only": "Collect", "sync_only": "Sync Selected Playlists" if is_scoped else "Sync", "sync_download": "Sync Then Download" if is_scoped else "Sync Then Download All", "download_only": "Download Selected Playlists" if is_scoped else "Download", "upload_only": "Upload", "download_upload": "Download Then Upload", } return mapping.get(str(job_type), str(job_type))