fix: OpenAPI schema missing minItems/maxItems for msgspec Meta on collections#4605
fix: OpenAPI schema missing minItems/maxItems for msgspec Meta on collections#4605worksbyfriday wants to merge 4 commits intolitestar-org:mainfrom
Conversation
litestar/typing.py
Outdated
| kwargs["pattern"] = "[[:ascii:]]" | ||
| elif meta.func == str.isdigit: # pragma: no cover # coverage quirk: It expects a jump here for branch coverage | ||
| kwargs["pattern"] = "[[:digit:]]" | ||
| elif isinstance(meta, msgspec.Meta): |
There was a problem hiding this comment.
This should not be handled here, since it's an implementation specific thing. It should be handled in the plugin. You can check how it's handled for other msgspec constraints / Pydantic, within their respective plugins.
There was a problem hiding this comment.
You're right. Removed the msgspec.Meta handling from _annotated_types_extractor. The plugin's kwarg_definition_from_field now handles collection types — msgspec.inspect already unwraps Meta into ListType(min_length=...), so the plugin just needs to extract those fields.
Codecov Report✅ All modified and coverable lines are covered by tests. Additional details and impacted files@@ Coverage Diff @@
## main #4605 +/- ##
=======================================
Coverage 97.85% 97.85%
=======================================
Files 297 297
Lines 15344 15347 +3
Branches 1722 1723 +1
=======================================
+ Hits 15015 15018 +3
Misses 188 188
Partials 141 141 ☔ View full report in Codecov by Sentry. 🚀 New features to boost your workflow:
|
|
Documentation preview will be available shortly at https://litestar-org.github.io/litestar-docs-preview/4605 |
…ields When using `Annotated[list[T], Meta(min_length=N)]` on a msgspec Struct field, the OpenAPI schema generation did not include `minItems`/`maxItems`, even though runtime validation and msgspec's own schema generation handled them correctly. Two fixes: 1. `litestar/plugins/core/_msgspec.py`: The `kwarg_definition_from_field()` function extracted `min_length`/`max_length` for string/bytes types but not for collection types (ListType, SetType, FrozenSetType, VarTupleType). Added collection type handling that maps `min_length` → `min_items` and `max_length` → `max_items`. 2. `litestar/typing.py`: The `_annotated_types_extractor()` function handled `annotated_types.MinLen`/`MaxLen` but not `msgspec.Meta`. Added a branch for `msgspec.Meta` that extracts all constraint attributes (gt, ge, lt, le, multiple_of, min_length, max_length, pattern), correctly mapping length constraints to items constraints for sequence containers. Fixes litestar-org#4514
Per review: msgspec-specific handling belongs in the plugin, not in the general annotated types extractor. The plugin already extracts min_length/max_length from collection types via msgspec.inspect. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Per review feedback.
Move default_field after required fields to satisfy msgspec's constraint that optional fields must follow required ones. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
019184b to
b834398
Compare
Summary
Fixes #4514.
When using
Annotated[list[T], Meta(min_length=N)]on a msgspec Struct field, the OpenAPI schema generation did not includeminItems/maxItems, even though:msgspec.json.schema()correctly generatedminItemsThe constraint metadata was lost at two boundaries:
litestar/plugins/core/_msgspec.py:kwarg_definition_from_field()extractedmin_length/max_lengthfor string/bytes types (lines 65-77) but not for collection types (ListType,SetType,FrozenSetType,VarTupleType). Added collection type handling that mapsmin_length→min_itemsandmax_length→max_items.litestar/typing.py:_annotated_types_extractor()handledannotated_types.MinLen/MaxLenbut notmsgspec.Meta(which is a separate class, not anannotated_typessubclass). Added a branch formsgspec.Metathat extracts all constraint attributes, correctly mapping length constraints to items constraints for sequence containers.Before
After
Test plan
test_create_schema_from_msgspec_annotated_collection_typeverifyingminItems/maxItemsfor list and set fieldstest_create_schema_from_msgspec_annotated_typestill passes (no regression on int/str/bytes fields)