Files
voidea/app/core/base.py
T

97 lines
2.5 KiB
Python

"""Base classes for VoIdea models and services."""
from datetime import datetime
from typing import Any, Generic, TypeVar
from uuid import UUID, uuid4
from pydantic import BaseModel, ConfigDict, Field
from sqlalchemy import DateTime, func
from sqlalchemy.orm import DeclarativeBase, Mapped, mapped_column
T = TypeVar("T")
class SQLBase(DeclarativeBase):
"""Base class for all SQLAlchemy models."""
type_annotation_map = {
datetime: DateTime(timezone=True),
}
class CoreModel(BaseModel):
"""Base Pydantic model with common fields."""
model_config = ConfigDict(
from_attributes=True,
populate_by_name=True,
)
class TimestampMixin:
"""Mixin for timestamp fields."""
created_at: Mapped[datetime] = mapped_column(
DateTime(timezone=True),
server_default=func.now(),
)
updated_at: Mapped[datetime] = mapped_column(
DateTime(timezone=True),
server_default=func.now(),
onupdate=func.now(),
)
class UUIDMixin:
"""Mixin for UUID primary key."""
id: Mapped[UUID] = mapped_column(primary_key=True, default=uuid4)
class BaseRepository(Generic[T]):
"""Base repository for data access."""
model: type[T]
def __init__(self, session: Any):
self.session = session
async def get_by_id(self, id: UUID) -> T | None:
"""Get entity by ID."""
return await self.session.get(self.model, id)
async def get_all(self, limit: int = 100, offset: int = 0) -> list[T]:
"""Get all entities with pagination."""
result = await self.session.execute(
select(self.model).limit(limit).offset(offset)
)
return list(result.scalars().all())
async def create(self, **kwargs: Any) -> T:
"""Create new entity."""
entity = self.model(**kwargs)
self.session.add(entity)
await self.session.commit()
await self.session.refresh(entity)
return entity
async def update(self, entity: T, **kwargs: Any) -> T:
"""Update entity."""
for key, value in kwargs.items():
setattr(entity, key, value)
await self.session.commit()
await self.session.refresh(entity)
return entity
async def delete(self, entity: T) -> None:
"""Delete entity."""
await self.session.delete(entity)
await self.session.commit()
class BaseService:
"""Base service class."""
def __init__(self, repository: BaseRepository):
self.repository = repository