munch-ease-backend/common.py
jableader 5be4e89c4e Squashed commit of the following:
commit fcd005b8624023547f28b7b28e59e6099bcfc7d4
Author: jableader <jacobdunk@gmail.com>
Date:   Sun Oct 19 20:24:07 2025 +1100

    Openapi tightening

commit f93bd8f641d561052c7bd075bae321b4ff3b676d
Author: jableader <jacobdunk@gmail.com>
Date:   Sun Oct 19 19:03:52 2025 +1100

    Removed refactor strategy doc

commit 0c5a61092f522be0c47cbbe86917c8a7e4e2d339
Author: jableader <jacobdunk@gmail.com>
Date:   Sun Oct 19 17:48:33 2025 +1100

    mypy & ruff checks

commit 23d66d6b18984127e17c73c3063f6120385935e9
Author: jableader <jacobdunk@gmail.com>
Date:   Sun Oct 19 16:49:35 2025 +1100

    Final removal of db.py files

commit f454aed1ca9783cc558cc203f29a7fe31b62a975
Author: jableader <jacobdunk@gmail.com>
Date:   Sun Oct 19 15:42:31 2025 +1100

    Finalise restructure, remove db.py files

commit 7187f6dd89489521538791c6bdebb426514beb99
Author: jableader <jacobdunk@gmail.com>
Date:   Sun Oct 19 15:34:54 2025 +1100

commit 6fea227ae20d32b8eb1e7a4885006a620fcc7bb1
Author: jableader <jacobdunk@gmail.com>
Date:   Sun Oct 19 15:32:53 2025 +1100

commit 27415e7e02d89195ad514cb017a9dbbf84d7a5e4
Author: jableader <jacobdunk@gmail.com>
Date:   Sun Oct 19 15:31:10 2025 +1100

commit b773428033d855f9ad82005602e049c1a2e3c585
Author: jableader <jacobdunk@gmail.com>
Date:   Sun Oct 19 15:28:58 2025 +1100

commit 116592c95278d995f4c516e87f2cea43cf5b7735
Author: jableader <jacobdunk@gmail.com>
Date:   Sun Oct 19 15:25:21 2025 +1100

commit 03ec565faea088971968ee2f9bb83e2de16b21f3
Author: jableader <jacobdunk@gmail.com>
Date:   Sun Oct 19 15:21:29 2025 +1100

    Plan
2025-10-19 20:24:23 +11:00

58 lines
1.8 KiB
Python

from typing import Any, Dict, Generic, List, Optional, TypeVar
from pydantic import BaseModel, ConfigDict, Field, model_validator
def to_camel(s: str) -> str:
parts = s.split("_")
return parts[0] + "".join(p.title() for p in parts[1:])
class ApiModel(BaseModel):
model_config = ConfigDict(
alias_generator=to_camel,
populate_by_name=True,
ser_json_inf_nan="null",
arbitrary_types_allowed=True,
)
class BaseLinkedModel(ApiModel):
@model_validator(mode="before")
@classmethod
def auto_populate_ids(cls, data: dict[str, Any]) -> dict[str, Any]:
if isinstance(data, dict):
for key, value in data.copy().items():
if not key.endswith("_id") and hasattr(value, "id") and value is not None:
id_key = key + "_id"
if id_key in data:
# If the id_key already exists, ensure it matches the value's id
if data[id_key] != value.id:
raise ValueError(
f"ID mismatch for {key}: {data[id_key]} != {value.id}"
)
else:
# If the id_key does not exist, set it to the value's id
data[id_key] = value.id
return data
class ProblemDetails(ApiModel):
type: str = Field(default="about:blank")
title: str
status: int
detail: Optional[str] = None
instance: Optional[str] = None
errors: Optional[Dict[str, Any]] = None
T = TypeVar("T")
class Page(ApiModel, Generic[T]):
items: List[T]
next_cursor: Optional[str] = Field(default=None, alias="nextCursor")
prev_cursor: Optional[str] = Field(default=None, alias="prevCursor")
total: Optional[int] = Field(default=None, description="Optional total count")