| from __future__ import annotations |
|
|
| from pathlib import Path |
| from typing import Iterable |
|
|
|
|
| ALLOWED_LAYOUT_TYPES = {"title_slide", "content_slide", "split_slide"} |
|
|
|
|
| def validate_file_extension(filename: str, allowed_extensions: Iterable[str]) -> None: |
| if not any(filename.lower().endswith(ext.lower()) for ext in allowed_extensions): |
| raise ValueError( |
| f"Invalid file extension: {filename}. Allowed extensions are: {list(allowed_extensions)}" |
| ) |
|
|
|
|
| def validate_template(template_path: str | Path) -> Path: |
| if not template_path: |
| raise ValueError("Template path cannot be empty.") |
|
|
| path = Path(template_path) |
| if not path.exists() or not path.is_file(): |
| raise ValueError(f"Template file does not exist: {path}") |
|
|
| validate_file_extension(path.name, [".pptx"]) |
| return path |
|
|
|
|
| def validate_slide_content(slide_content: dict) -> None: |
| if not isinstance(slide_content, dict): |
| raise ValueError("Invalid slide content: Expected a dictionary.") |
|
|
| title = slide_content.get("title", "") |
| bullets = slide_content.get("bullets", []) |
| layout_type = slide_content.get("layout_type", "content_slide") |
|
|
| if not isinstance(title, str) or not title.strip(): |
| raise ValueError("Each slide must include a non-empty 'title' string.") |
|
|
| if not isinstance(bullets, list) or not all(isinstance(item, str) for item in bullets): |
| raise ValueError("Each slide must include 'bullets' as a list of strings.") |
|
|
| if layout_type not in ALLOWED_LAYOUT_TYPES: |
| raise ValueError( |
| f"Invalid layout_type '{layout_type}'. Expected one of {sorted(ALLOWED_LAYOUT_TYPES)}." |
| ) |
|
|
|
|
| def validate_slides(slides: list[dict]) -> bool: |
| if not isinstance(slides, list): |
| raise ValueError("Generated slide data must be a list.") |
|
|
| for slide in slides: |
| validate_slide_content(slide) |
|
|
| return True |