msgspec.Meta constraints on collection/mapping members are silently dropped in DTO transfer models (same root cause as #5031)
Description
#5031 reported that a msgspec.Meta constraint on one arm of a heterogeneous
union (e.g. Union[Annotated[str, Meta(min_length=5)], int]) is silently
dropped when the DTO transfer model is built, so MsgspecDTO accepts data
that plain msgspec.json.decode would reject. PR #5045 fixes that for union
arms specifically.
The same root cause also affects collection items and mapping values,
which #5045 does not touch: _create_transfer_model_type_annotation's
SimpleType branch (litestar/dto/_backend.py) always returns the member's
bare .annotation, discarding any Meta that lives in .metadata, for
every caller that recurses into a member type - not just
_create_transfer_model_union_type.
To Reproduce
from typing import Annotated, List
from litestar import Litestar, post
from litestar.dto import MsgspecDTO
from msgspec import Struct, Meta
class ListStruct(Struct):
items: List[Annotated[str, Meta(min_length=5)]]
@post("/list", dto=MsgspecDTO[ListStruct])
async def listy(data: ListStruct) -> ListStruct:
return data
app = Litestar(route_handlers=[listy])curl -d '{"items": ["12"]}' http://localhost:8000/list returns 201 with
{"items":["12"]} instead of a 400 - "12" is 2 characters, violating
min_length=5. The same holds for Dict[str, Annotated[str, Meta(min_length=5)]]
values.
Expected behavior
A Meta constraint on a collection item or mapping value should be enforced
the same way it already is for a plain field or (after #5045) a union arm.
Root cause
litestar/dto/_backend.py, _create_transfer_model_type_annotation's
SimpleType branch returns transfer_type.field_definition.annotation
unconditionally. This function is called recursively by
_create_transfer_model_collection_type, _create_transfer_model_tuple_type,
_create_transfer_model_mapping_type and _create_transfer_model_union_type
alike, so fixing only the union path (as #5045 does) leaves the identical gap
in the other three.
Litestar Version
main @ cbc0c51 (also present as of 2.24.0)
Source: litestar-org/litestar