Complete worked example
python
from typing import Literal, Self
from pydantic import BaseModel, ConfigDict, Field, ValidationError, computed_field, model_validator
class Role(BaseModel):
model_config = ConfigDict(extra="forbid")
id: int = Field(ge=1)
country: Literal["US", "IL", "UA", "CA"]
status: Literal["active", "archived"] = "active"
class Report(BaseModel):
model_config = ConfigDict(extra="forbid")
country: Literal["US", "IL", "UA", "CA"]
rows: list[Role] = Field(max_length=3)
@model_validator(mode="after")
def scoped(self) -> Self:
if any(row.country != self.country for row in self.rows):
raise ValueError("country mismatch")
if len({row.id for row in self.rows}) != len(self.rows):
raise ValueError("duplicate identity")
return self
@computed_field
@property
def observed_count(self) -> int:
return len(self.rows)
def inspect_example(payload):
try:
return {"value": Report.model_validate(payload).model_dump(mode="json")}
except ValidationError as error:
return {"error": sorted({e["type"] for e in error.errors()})}- Reasoning
- The report first validates nested Role objects, then checks that each role belongs to the selected country and that row identities are unique within this report. Only an accepted report computes observed_count from its retained rows. No value supplied by a caller is trusted as that derived count. Trace a report containing one active and one archived role. It has two observed rows. Then compare a duplicated identity and a role from another country: both fail before a successful report is returned. The fixture makes scope and identity rules independently observable rather than assuming a sorted list must already be trustworthy.