add exceptions

Changed files
+68 -5
src
+18 -1
src/atpasser/model/__init__.py
···
+
from .exceptions import (
+
AtprotoModelError,
+
ValidationError,
+
SerializationError,
+
DeserializationError,
+
InvalidCIDError,
+
InvalidBlobError,
+
TypeMismatchError
+
)
from .base import DataModel
from .blob import BlobModel
from .typed import TypedDataModel
···
"RecordModel",
"QueryModel",
"ProcedureModel",
-
"SubscriptionModel"
+
"SubscriptionModel",
+
# Exceptions
+
"AtprotoModelError",
+
"ValidationError",
+
"SerializationError",
+
"DeserializationError",
+
"InvalidCIDError",
+
"InvalidBlobError",
+
"TypeMismatchError"
]
+13 -4
src/atpasser/model/base.py
···
from cid.cid import CIDv1, make_cid
from pydantic import BaseModel, field_serializer, field_validator, ConfigDict
from pydantic.fields import FieldInfo
+
from .exceptions import (
+
ValidationError,
+
SerializationError,
+
DeserializationError,
+
InvalidCIDError
+
)
class DataModel(BaseModel):
"""
···
try:
return base64.b64decode(value)
except ValueError as e:
-
raise ValueError(f"Failed to decode base64 bytes: {e}")
+
raise DeserializationError("$bytes", f"Failed to decode base64 bytes: {e}")
# Handle CID objects
elif isinstance(v, dict) and "$link" in v:
···
try:
return make_cid(value)
except ValueError as e:
-
raise ValueError(f"Failed to parse CID: {e}")
+
raise InvalidCIDError(f"Failed to parse CID: {e}")
return v
···
"""
# Handle bytes fields
if isinstance(v, bytes):
-
value = base64.b64encode(v).decode()
-
return {"$bytes": value}
+
try:
+
value = base64.b64encode(v).decode()
+
return {"$bytes": value}
+
except Exception as e:
+
raise SerializationError("bytes", f"Failed to encode bytes: {e}")
# Handle CID fields
elif isinstance(v, CIDv1):
+1
src/atpasser/model/blob.py
···
from typing import Any
from pydantic import field_validator, ConfigDict
from .base import DataModel
+
from .exceptions import ValidationError, InvalidBlobError
class BlobModel(DataModel):
"""
+36
src/atpasser/model/exceptions.py
···
+
class AtprotoModelError(Exception):
+
"""Base exception for all AT Protocol model errors"""
+
pass
+
+
class ValidationError(AtprotoModelError):
+
"""Raised when data validation fails"""
+
def __init__(self, field: str, message: str):
+
self.field = field
+
self.message = message
+
super().__init__(f"Validation error for field '{field}': {message}")
+
+
class SerializationError(AtprotoModelError):
+
"""Raised when data serialization fails"""
+
def __init__(self, field: str, message: str):
+
self.field = field
+
self.message = message
+
super().__init__(f"Serialization error for field '{field}': {message}")
+
+
class DeserializationError(AtprotoModelError):
+
"""Raised when data deserialization fails"""
+
def __init__(self, field: str, message: str):
+
self.field = field
+
self.message = message
+
super().__init__(f"Deserialization error for field '{field}': {message}")
+
+
class InvalidCIDError(AtprotoModelError):
+
"""Raised when CID validation fails"""
+
pass
+
+
class InvalidBlobError(AtprotoModelError):
+
"""Raised when blob validation fails"""
+
pass
+
+
class TypeMismatchError(AtprotoModelError):
+
"""Raised when type validation fails"""
+
pass