from typing import Self, Optional, Literal from pydantic import BaseModel from pydantic.alias_generators import to_camel class CustomConfig: populate_by_name = True from_attributes = True class BaseSchema(BaseModel): class Config: from_attributes = True alias_generator = to_camel populate_by_name = True arbitrary_types_allowed = True @classmethod def from_sql_model(cls, model, fields: dict): model_dict = {c.name: getattr(model, c.name) for c in model.__table__.columns} model_dict.update(fields) return cls(**model_dict) def model_dump_parent(self): parent_class: BaseModel = self.__class__.__bases__[0] parent_fields = set(parent_class.model_fields.keys()) return self.model_dump(include=parent_fields) @classmethod def from_orm_list(cls, sql_models) -> list[Self]: return [cls.model_validate(model) for model in sql_models] class BaseResponse(BaseSchema): message: str class PaginationSchema(BaseSchema): page: Optional[int] = None items_per_page: Optional[int] = None class PaginationInfoSchema(BaseSchema): total_pages: int total_items: int type SortDir = Literal["asc", "desc"] class SortingSchema(BaseSchema): field: Optional[str] = None direction: Optional[SortDir] = None class BaseEnumSchema(BaseSchema): id: int name: str class BaseEnumListSchema(BaseSchema): items: list[BaseEnumSchema] class BasePdfResponse(BaseSchema): base64_string: str filename: str mime_type: str