from copy import copy
from dataclasses import dataclass, is_dataclass
from enum import Enum
+from functools import lru_cache
from typing import (
Any,
Callable,
is_uploadfile_or_nonable_uploadfile_annotation(sub_annotation)
for sub_annotation in get_args(annotation)
)
+
+
+@lru_cache
+def get_cached_model_fields(model: Type[BaseModel]) -> List[ModelField]:
+ return get_model_fields(model)
evaluate_forwardref,
field_annotation_is_scalar,
get_annotation_from_field_info,
+ get_cached_model_fields,
get_missing_field_error,
- get_model_fields,
is_bytes_field,
is_bytes_sequence_field,
is_scalar_field,
fields_to_extract: List[ModelField] = body_fields
if single_not_embedded_field and lenient_issubclass(first_field.type_, BaseModel):
- fields_to_extract = get_model_fields(first_field.type_)
+ fields_to_extract = get_cached_model_fields(first_field.type_)
if isinstance(received_body, FormData):
body_to_process = await _extract_form_body(fields_to_extract, received_body)
ModelField,
Undefined,
_get_model_config,
+ get_cached_model_fields,
get_model_fields,
is_bytes_sequence_annotation,
is_scalar_field,
fields = get_model_fields(Model)
assert not is_scalar_field(fields[0])
+
+
+def test_get_model_fields_cached():
+ class Model(BaseModel):
+ foo: str
+
+ non_cached_fields = get_model_fields(Model)
+ non_cached_fields2 = get_model_fields(Model)
+ cached_fields = get_cached_model_fields(Model)
+ cached_fields2 = get_cached_model_fields(Model)
+ for f1, f2 in zip(cached_fields, cached_fields2):
+ assert f1 is f2
+
+ assert non_cached_fields is not non_cached_fields2
+ assert cached_fields is cached_fields2