import pandas as pd from typing import Any, Dict, List def safe_dataframe(df: pd.DataFrame) -> pd.DataFrame: for col in df.columns: df[col] = df[col].astype(str) return df def analysis_to_csv(analysis: Dict[str, Any]) -> str: rows = [] for sb in analysis.get("storyboard", []): rows.append({"Section": "Storyboard", **sb}) for sc in analysis.get("script", []): rows.append({"Section": "Script", **sc}) for met in analysis.get("video_analysis", {}).get("video_metrics", []): rows.append({"Section": "Metrics", **met}) for imp in analysis.get("timestamp_improvements", []): rows.append({"Section": "Improvements", **imp}) if not rows: return "" df = pd.DataFrame(rows) return df.to_csv(index=False) def _normalize_list(value: Any) -> List[str]: if value is None: return [] if isinstance(value, list): return [str(v) for v in value] return [s for s in str(value).splitlines() if s.strip()] def _to_dataframe(items: Any, columns_map: Dict[str, str]) -> pd.DataFrame: if not isinstance(items, list) or not items: return pd.DataFrame(columns=list(columns_map.values())) df = pd.DataFrame(items) df = df.rename(columns=columns_map) ordered_cols = [columns_map[k] for k in columns_map.keys() if columns_map[k] in df.columns] df = df.reindex(columns=ordered_cols) return df def _search_dataframe(df: pd.DataFrame, query: str) -> pd.DataFrame: if not query or df.empty: return df mask = pd.Series([False]*len(df)) for col in df.columns: mask = mask | df[col].astype(str).str.contains(query, case=False, na=False) return df[mask]