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

"""
SectionReadResponse - dataclass for section read operation results.
Ensures type safety and prevents silent failures.
"""

from __future__ import annotations

from dataclasses import dataclass
from pathlib import Path
from typing import Optional


@dataclass
class SectionReadResponse:
    """Result of reading a section."""

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

    content: str
    """Section content (LaTeX code)"""

    section_name: str
    """Section name (e.g., 'abstract', 'introduction')"""

    section_id: str
    """Full hierarchical section ID (e.g., 'manuscript/abstract')"""

    doc_type: str
    """Document type: 'manuscript', 'supplementary', 'revision', or 'shared'"""

    file_path: Optional[Path] = None
    """Absolute path to the section .tex file"""

    error: Optional[str] = None
    """Error message if read failed"""

    def to_dict(self) -> dict:
        """Convert to dictionary for JSON serialization."""
        return {
            "success": self.success,
            "content": self.content,
            "section_name": self.section_name,
            "section_id": self.section_id,
            "doc_type": self.doc_type,
            "file_path": str(self.file_path) if self.file_path else None,
            "error": self.error,
        }

    def __str__(self):
        """Human-readable summary."""
        if self.success:
            return f"Read {self.section_id}: {len(self.content)} chars"
        else:
            return f"Failed to read {self.section_id}: {self.error}"

    @classmethod
    def create_success(
        cls,
        content: str,
        section_name: str,
        section_id: str,
        doc_type: str,
        file_path: Optional[Path] = None,
    ) -> SectionReadResponse:
        """Create a successful response."""
        return cls(
            success=True,
            content=content,
            section_name=section_name,
            section_id=section_id,
            doc_type=doc_type,
            file_path=file_path,
            error=None,
        )

    @classmethod
    def create_failure(cls, section_id: str, error_message: str) -> SectionReadResponse:
        """Create a failed response."""
        parts = section_id.split("/")
        doc_type = parts[0] if len(parts) > 1 else "manuscript"
        section_name = parts[1] if len(parts) > 1 else section_id

        return cls(
            success=False,
            content="",
            section_name=section_name,
            section_id=section_id,
            doc_type=doc_type,
            file_path=None,
            error=error_message,
        )

    def validate(self) -> None:
        """Validate response data - raises ValueError if invalid."""
        if (
            self.success
            and not self.content
            and self.section_name not in ["compiled_pdf", "compiled_tex"]
        ):
            raise ValueError(
                f"SectionReadResponse marked as success but content is empty for {self.section_id}"
            )

        if not self.success and not self.error:
            raise ValueError(
                f"SectionReadResponse marked as failed but no error message for {self.section_id}"
            )

        if not self.section_name:
            raise ValueError("section_name cannot be empty")

        if not self.section_id:
            raise ValueError("section_id cannot be empty")

        if self.doc_type not in ["manuscript", "supplementary", "revision", "shared"]:
            raise ValueError(f"Invalid doc_type: {self.doc_type}")


__all__ = ["SectionReadResponse"]

# EOF