You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
## Problem
Service model conversion currently hardcodes partial-update dump
behavior for schema-like inputs. Pydantic models are dumped with
`exclude_unset=True`, msgspec structs drop `UNSET`, and attrs instances
drop `attrs.NOTHING`. That preserves partial-update semantics, but it
gives callers no supported way to intentionally include unset/default
values for update-like schemas.
A common case is a schema where an unset field should still be applied
with its schema default:
```python
class InviteUpdate(BaseModel):
name: str | None = None
is_admin: bool = False
await invite_service.update(data, item_id=invite_id)
```
With the previous hardcoded behavior, `is_admin=False` is excluded
unless the caller explicitly sets it on the Pydantic model.
## Changes
### `feat(service): add configurable schema dump behavior`
Adds `SchemaDumpConfig` and exposes it as a class-level service default
plus a per-call override on write operations that convert schema-like
input through `to_model()`.
```python
class InviteService(SQLAlchemyAsyncRepositoryService[Invite]):
schema_dump_config = SchemaDumpConfig(exclude_unset=False)
await invite_service.update(
data,
item_id=invite_id,
schema_dump_config=SchemaDumpConfig(exclude_unset=False),
)
```
The per-call override is scoped to that operation only and does not
mutate the service default or affect later calls.
### `feat(serialization): centralize schema dumping`
Routes Pydantic, msgspec, attrs, and dataclass inputs through
`schema_dump(..., config=...)` instead of duplicating hardcoded
conversion logic inside sync and async services.
`SchemaDumpConfig` supports:
- `exclude_unset`, for Pydantic field-set behavior
- `exclude_none`, for dropping `None` values
- `exclude_defaults`, for dropping values equal to schema defaults where
supported
- `exclude_sentinels`, for dropping sentinel values such as Pydantic
`MISSING`, msgspec `UNSET`, attrs `NOTHING`, and Advanced Alchemy
`Empty`
### `fix(fixtures): align service overrides with the new conversion
contract`
Updates test fixture services that override `to_model()` so they accept
and forward `schema_dump_config`. This keeps custom service conversion
hooks compatible with the new base method signature and preserves the
selected dump behavior in the inline slug-generation path.
## Compatibility Notes
- Existing defaults preserve current partial-update behavior:
`SchemaDumpConfig()` keeps `exclude_unset=True` and
`exclude_sentinels=True`.
- The existing `schema_dump(..., exclude_unset=...)` argument remains
supported for callers using the standalone utility.
- Optional schema libraries remain guarded. Advanced Alchemy should not
fail to import when Pydantic, msgspec, attrs, or cattrs are absent.
- `to_schema()` is not changed by this PR; the configurable behavior
applies to service input conversion through `to_model()`.
0 commit comments