Loading...
No commits yet
Not committed History
Blame
_SaveSectionsResponse.py • 3.4 KB
#!/usr/bin/env python3
# -*- coding: utf-8 -*-
# File: src/scitex_writer/_dataclasses/results/_SaveSectionsResponse.py

"""
SaveSectionsResponse - dataclass for section save operation results.
Ensures type safety and prevents silent failures.
"""

from __future__ import annotations

from dataclasses import dataclass, field
from typing import Dict, List


@dataclass
class SaveSectionsResponse:
    """Result of saving multiple sections."""

    success: bool
    """Whether the save operation succeeded"""

    sections_saved: int
    """Number of sections successfully saved"""

    sections_skipped: int = 0
    """Number of sections skipped or failed"""

    message: str = ""
    """Human-readable status message"""

    errors: List[str] = field(default_factory=list)
    """List of error messages (if any)"""

    error_details: Dict[str, str] = field(default_factory=dict)
    """Detailed errors per section: {section_id: error_message}"""

    def to_dict(self) -> dict:
        """Convert to dictionary for JSON serialization."""
        return {
            "success": self.success,
            "sections_saved": self.sections_saved,
            "sections_skipped": self.sections_skipped,
            "message": self.message,
            "errors": self.errors,
            "error_details": self.error_details,
        }

    def __str__(self):
        """Human-readable summary."""
        status = "SUCCESS" if self.success else "FAILED"
        lines = [
            f"Save {status}: {self.sections_saved} saved, {self.sections_skipped} skipped",
        ]
        if self.message:
            lines.append(f"Message: {self.message}")
        if self.errors:
            lines.append(f"Errors: {len(self.errors)}")
            for error in self.errors[:3]:  # Show first 3 errors
                lines.append(f"  - {error}")
        return "\n".join(lines)

    @classmethod
    def create_success(
        cls, sections_saved: int, message: str = ""
    ) -> SaveSectionsResponse:
        """Create a successful response."""
        return cls(
            success=True,
            sections_saved=sections_saved,
            sections_skipped=0,
            message=message or f"Saved {sections_saved} sections",
        )

    @classmethod
    def create_failure(
        cls, error_message: str, errors: List[str] = None, sections_saved: int = 0
    ) -> SaveSectionsResponse:
        """Create a failed response."""
        return cls(
            success=False,
            sections_saved=sections_saved,
            sections_skipped=len(errors) if errors else 0,
            message=error_message,
            errors=errors or [error_message],
        )

    def validate(self) -> None:
        """Validate response data - raises ValueError if invalid."""
        if self.success and self.sections_saved == 0:
            raise ValueError(
                "SaveSectionsResponse marked as success but no sections were saved"
            )

        if not self.success and not self.errors:
            raise ValueError(
                "SaveSectionsResponse marked as failed but no errors provided"
            )

        if self.sections_saved < 0:
            raise ValueError(
                f"Invalid sections_saved: {self.sections_saved} (must be >= 0)"
            )

        if self.sections_skipped < 0:
            raise ValueError(
                f"Invalid sections_skipped: {self.sections_skipped} (must be >= 0)"
            )


__all__ = ["SaveSectionsResponse"]

# EOF