Source code for glyph_forge.core.client.exceptions
# glyph_forge/core/client/exceptions.py
"""
Exception hierarchy for ForgeClient.
All exceptions inherit from ForgeClientError for easy catching.
"""
from __future__ import annotations
from typing import Optional, Any
[docs]
class ForgeClientError(Exception):
"""Base exception for all ForgeClient errors."""
[docs]
def __init__(
self,
message: str,
*,
endpoint: Optional[str] = None,
payload_summary: Optional[str] = None,
):
self.message = message
self.endpoint = endpoint
self.payload_summary = payload_summary
super().__init__(self._format_message())
def _format_message(self) -> str:
parts = [self.message]
if self.endpoint:
parts.append(f"endpoint={self.endpoint}")
if self.payload_summary:
parts.append(f"payload={self.payload_summary}")
return " | ".join(parts)
[docs]
class ForgeClientIOError(ForgeClientError):
"""Network or connection-related errors (timeouts, DNS failures, etc.)."""
[docs]
def __init__(
self,
message: str,
*,
endpoint: Optional[str] = None,
original_error: Optional[Exception] = None,
):
self.original_error = original_error
super().__init__(message, endpoint=endpoint)
def _format_message(self) -> str:
base = super()._format_message()
if self.original_error:
return f"{base} | cause={type(self.original_error).__name__}: {self.original_error}"
return base
[docs]
class ForgeClientHTTPError(ForgeClientError):
"""HTTP errors (non-2xx status codes)."""
[docs]
def __init__(
self,
message: str,
*,
status_code: int,
response_body: Optional[str] = None,
endpoint: Optional[str] = None,
):
self.status_code = status_code
self.response_body = response_body
super().__init__(message, endpoint=endpoint)
def _format_message(self) -> str:
base = super()._format_message()
parts = [base, f"status={self.status_code}"]
if self.response_body:
# Truncate long bodies
body_preview = self.response_body[:200]
if len(self.response_body) > 200:
body_preview += "..."
parts.append(f"body={body_preview}")
return " | ".join(parts)