89 lines
2.4 KiB
Python
89 lines
2.4 KiB
Python
"""Structured error types for GnommoEditor pipeline."""
|
|
|
|
from dataclasses import dataclass
|
|
from pathlib import Path
|
|
from typing import Optional
|
|
|
|
|
|
class GnommoError(Exception):
|
|
"""Base exception for all GnommoEditor errors."""
|
|
|
|
pass
|
|
|
|
|
|
@dataclass
|
|
class ValidationIssue:
|
|
"""A single validation issue with location context."""
|
|
|
|
message: str
|
|
file: Optional[Path] = None
|
|
line: Optional[int] = None
|
|
|
|
def __str__(self) -> str:
|
|
parts = []
|
|
if self.file:
|
|
parts.append(str(self.file))
|
|
if self.line is not None:
|
|
parts.append(f"line {self.line}")
|
|
location = ":".join(parts) if parts else "project"
|
|
return f"[{location}] {self.message}"
|
|
|
|
|
|
class ParseError(GnommoError):
|
|
"""Error during parsing of input files."""
|
|
|
|
def __init__(
|
|
self, message: str, file: Optional[Path] = None, line: Optional[int] = None
|
|
):
|
|
self.issue = ValidationIssue(message, file, line)
|
|
super().__init__(str(self.issue))
|
|
|
|
|
|
class ValidationError(GnommoError):
|
|
"""Error during validation stage. Can contain multiple issues."""
|
|
|
|
def __init__(self, issues: list[ValidationIssue]):
|
|
self.issues = issues
|
|
message = f"Validation failed with {len(issues)} error(s):\n"
|
|
message += "\n".join(f" - {issue}" for issue in issues)
|
|
super().__init__(message)
|
|
|
|
|
|
class RenderError(GnommoError):
|
|
"""Error during rendering stage."""
|
|
|
|
def __init__(
|
|
self, message: str, command: Optional[str] = None, stderr: Optional[str] = None
|
|
):
|
|
self.command = command
|
|
self.stderr = stderr
|
|
full_message = message
|
|
if command:
|
|
full_message += f"\nCommand: {command}"
|
|
if stderr:
|
|
full_message += f"\nFFmpeg output:\n{stderr}"
|
|
super().__init__(full_message)
|
|
|
|
|
|
class PreprocessError(GnommoError):
|
|
"""Error during preprocessing stage."""
|
|
|
|
def __init__(
|
|
self,
|
|
message: str,
|
|
filter_type: Optional[str] = None,
|
|
command: Optional[str] = None,
|
|
stderr: Optional[str] = None,
|
|
):
|
|
self.filter_type = filter_type
|
|
self.command = command
|
|
self.stderr = stderr
|
|
full_message = message
|
|
if filter_type:
|
|
full_message = f"[{filter_type}] {full_message}"
|
|
if command:
|
|
full_message += f"\nCommand: {command}"
|
|
if stderr:
|
|
full_message += f"\nFFmpeg output:\n{stderr}"
|
|
super().__init__(full_message)
|