|
3 | 3 | import sys |
4 | 4 | from dataclasses import fields, is_dataclass |
5 | 5 | from inspect import isclass |
6 | | -from typing import Any, Literal, TypeGuard, TypeVar |
| 6 | +from typing import Any, get_origin, Literal, TypeGuard, TypeVar |
7 | 7 |
|
8 | 8 | import humps |
9 | 9 | from quart import current_app |
@@ -255,31 +255,34 @@ def _is_list_or_dict(type_: type) -> bool: |
255 | 255 | return origin in (dict, dict, list, list) |
256 | 256 |
|
257 | 257 |
|
| 258 | +def _valid_model_class(model_class: type) -> bool: |
| 259 | + """Validate if a type can be used as a schema class. |
| 260 | +
|
| 261 | + Returns True for types that don't require conversion: |
| 262 | + - TypedDict, dataclasses, and attrs classes |
| 263 | + - Built-in dict/list and their generic aliases (e.g., dict[str, int]) |
| 264 | + """ |
| 265 | + if ( |
| 266 | + _is_list_or_dict(model_class) |
| 267 | + or is_dataclass(model_class) |
| 268 | + or is_typeddict(model_class) |
| 269 | + or dict in getattr(get_origin(model_class), "__mro__", ()) |
| 270 | + ): |
| 271 | + return True |
| 272 | + return False |
| 273 | + |
| 274 | + |
258 | 275 | def _use_pydantic(model_class: type, preference: str | None) -> bool: |
259 | 276 | return PYDANTIC_INSTALLED and ( |
260 | 277 | is_pydantic_dataclass(model_class) |
261 | 278 | or (isclass(model_class) and issubclass(model_class, BaseModel)) |
262 | | - or ( |
263 | | - ( |
264 | | - _is_list_or_dict(model_class) |
265 | | - or is_dataclass(model_class) |
266 | | - or is_typeddict(model_class) |
267 | | - ) |
268 | | - and preference != "msgspec" |
269 | | - ) |
| 279 | + or (_valid_model_class(model_class) and preference != "msgspec") |
270 | 280 | ) |
271 | 281 |
|
272 | 282 |
|
273 | 283 | def _use_msgspec(model_class: type, preference: str | None) -> bool: |
274 | 284 | return MSGSPEC_INSTALLED and ( |
275 | 285 | (isclass(model_class) and issubclass(model_class, Struct)) |
276 | 286 | or is_attrs(model_class) |
277 | | - or ( |
278 | | - ( |
279 | | - _is_list_or_dict(model_class) |
280 | | - or is_dataclass(model_class) |
281 | | - or is_typeddict(model_class) |
282 | | - ) |
283 | | - and preference != "pydantic" |
284 | | - ) |
| 287 | + or (_valid_model_class(model_class) and preference != "pydantic") |
285 | 288 | ) |
0 commit comments