refactor, body

# What does this PR do?


## Test Plan
# What does this PR do?


## Test Plan
This commit is contained in:
Eric Huang 2025-10-10 13:47:36 -07:00
parent 6954fe2274
commit cb7fb0705b
33 changed files with 599 additions and 890 deletions

View file

@ -50,6 +50,10 @@ if sys.version_info >= (3, 10):
else:
from typing_extensions import TypeGuard
from pydantic import BaseModel
from pydantic.fields import FieldInfo
S = TypeVar("S")
T = TypeVar("T")
K = TypeVar("K")
@ -570,7 +574,8 @@ def get_class_properties(typ: type) -> Iterable[Tuple[str, type | str]]:
elif hasattr(typ, "model_fields"):
# Pydantic BaseModel - use model_fields to exclude ClassVar and other non-field attributes
# Reconstruct Annotated type if discriminator exists to preserve metadata
from typing import Annotated, Any, cast
from typing import Annotated, Any
from pydantic.fields import FieldInfo
def get_field_type(name: str, field: Any) -> type | str:
@ -1049,3 +1054,32 @@ def check_recursive(
pred = lambda typ, obj: True # noqa: E731
return RecursiveChecker(pred).check(type(obj), obj)
def is_unwrapped_body_param(param_type: Any) -> bool:
"""
Check if a parameter type represents an unwrapped body parameter.
An unwrapped body parameter is an Annotated type with Body(embed=False)
This is used to determine whether request parameters should be flattened
in OpenAPI specs and client libraries (matching FastAPI's embed=False behavior).
Args:
param_type: The parameter type annotation to check
Returns:
True if the parameter should be treated as an unwrapped body parameter
"""
# Check if it's Annotated with Body(embed=False)
if typing.get_origin(param_type) is Annotated:
args = typing.get_args(param_type)
base_type = args[0]
metadata = args[1:]
# Look for Body annotation with embed=False
# Body() returns a FieldInfo object, so we check for that type and the embed attribute
for item in metadata:
if isinstance(item, FieldInfo) and hasattr(item, "embed") and not item.embed:
return inspect.isclass(base_type) and issubclass(base_type, BaseModel)
return False