🐛 Fix OpenAPI schema support for computed fields when using `separate_input_output_schemas=False` (#13207)

Co-authored-by: Sofie Van Landeghem <svlandeg@users.noreply.github.com>
Co-authored-by: svlandeg <svlandeg@github.com>
Co-authored-by: pre-commit-ci[bot] <66853113+pre-commit-ci[bot]@users.noreply.github.com>
Co-authored-by: svlandeg <sofie.vanlandeghem@gmail.com>
Co-authored-by: Sebastián Ramírez <tiangolo@gmail.com>
This commit is contained in:
Vincent Grafé 2025-12-02 01:22:08 -08:00 committed by GitHub
parent 5126e099bd
commit f95a174288
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
2 changed files with 17 additions and 4 deletions

View File

@ -180,8 +180,13 @@ def get_schema_from_model_field(
],
separate_input_output_schemas: bool = True,
) -> Dict[str, Any]:
computed_fields = field._type_adapter.core_schema.get("schema", {}).get(
"computed_fields", []
)
override_mode: Union[Literal["validation"], None] = (
None if separate_input_output_schemas else "validation"
None
if (separate_input_output_schemas or len(computed_fields) > 0)
else "validation"
)
# This expects that GenerateJsonSchema was already used to generate the definitions
json_schema = field_mapping[(field, override_mode or field.mode)]
@ -203,9 +208,14 @@ def get_definitions(
Dict[Tuple[ModelField, Literal["validation", "serialization"]], JsonSchemaValue],
Dict[str, Dict[str, Any]],
]:
has_computed_fields: bool = any(
field._type_adapter.core_schema.get("schema", {}).get("computed_fields", [])
for field in fields
)
schema_generator = GenerateJsonSchema(ref_template=REF_TEMPLATE)
override_mode: Union[Literal["validation"], None] = (
None if separate_input_output_schemas else "validation"
None if (separate_input_output_schemas or has_computed_fields) else "validation"
)
validation_fields = [field for field in fields if field.mode == "validation"]
serialization_fields = [field for field in fields if field.mode == "serialization"]

View File

@ -6,8 +6,9 @@ from .utils import needs_pydanticv2
@pytest.fixture(name="client")
def get_client():
app = FastAPI()
def get_client(request):
separate_input_output_schemas = request.param
app = FastAPI(separate_input_output_schemas=separate_input_output_schemas)
from pydantic import BaseModel, computed_field
@ -32,6 +33,7 @@ def get_client():
return client
@pytest.mark.parametrize("client", [True, False], indirect=True)
@pytest.mark.parametrize("path", ["/", "/responses"])
@needs_pydanticv2
def test_get(client: TestClient, path: str):
@ -40,6 +42,7 @@ def test_get(client: TestClient, path: str):
assert response.json() == {"width": 3, "length": 4, "area": 12}
@pytest.mark.parametrize("client", [True, False], indirect=True)
@needs_pydanticv2
def test_openapi_schema(client: TestClient):
response = client.get("/openapi.json")