From 699cd287cbc21f6dcdd615a2dd652e2e59a73fd3 Mon Sep 17 00:00:00 2001 From: Yurii Motov Date: Thu, 27 Nov 2025 09:38:29 +0100 Subject: [PATCH] Add variants for `path-operation-advanced-configuration/tutorial007` --- .../path-operation-advanced-configuration.md | 4 +-- .../tutorial007_py39.py | 32 +++++++++++++++++++ .../test_tutorial007.py | 20 +++++++++--- 3 files changed, 49 insertions(+), 7 deletions(-) create mode 100644 docs_src/path_operation_advanced_configuration/tutorial007_py39.py diff --git a/docs/en/docs/advanced/path-operation-advanced-configuration.md b/docs/en/docs/advanced/path-operation-advanced-configuration.md index f88beefc4..5879bc5c7 100644 --- a/docs/en/docs/advanced/path-operation-advanced-configuration.md +++ b/docs/en/docs/advanced/path-operation-advanced-configuration.md @@ -155,7 +155,7 @@ For example, in this application we don't use FastAPI's integrated functionality //// tab | Pydantic v2 -{* ../../docs_src/path_operation_advanced_configuration/tutorial007.py hl[17:22, 24] *} +{* ../../docs_src/path_operation_advanced_configuration/tutorial007_py39.py hl[15:20, 22] *} //// @@ -179,7 +179,7 @@ And then in our code, we parse that YAML content directly, and then we are again //// tab | Pydantic v2 -{* ../../docs_src/path_operation_advanced_configuration/tutorial007.py hl[26:33] *} +{* ../../docs_src/path_operation_advanced_configuration/tutorial007_py39.py hl[24:31] *} //// diff --git a/docs_src/path_operation_advanced_configuration/tutorial007_py39.py b/docs_src/path_operation_advanced_configuration/tutorial007_py39.py new file mode 100644 index 000000000..ff64ef792 --- /dev/null +++ b/docs_src/path_operation_advanced_configuration/tutorial007_py39.py @@ -0,0 +1,32 @@ +import yaml +from fastapi import FastAPI, HTTPException, Request +from pydantic import BaseModel, ValidationError + +app = FastAPI() + + +class Item(BaseModel): + name: str + tags: list[str] + + +@app.post( + "/items/", + openapi_extra={ + "requestBody": { + "content": {"application/x-yaml": {"schema": Item.model_json_schema()}}, + "required": True, + }, + }, +) +async def create_item(request: Request): + raw_body = await request.body() + try: + data = yaml.safe_load(raw_body) + except yaml.YAMLError: + raise HTTPException(status_code=422, detail="Invalid YAML") + try: + item = Item.model_validate(data) + except ValidationError as e: + raise HTTPException(status_code=422, detail=e.errors(include_url=False)) + return item diff --git a/tests/test_tutorial/test_path_operation_advanced_configurations/test_tutorial007.py b/tests/test_tutorial/test_path_operation_advanced_configurations/test_tutorial007.py index 8240b60a6..a90337a63 100644 --- a/tests/test_tutorial/test_path_operation_advanced_configurations/test_tutorial007.py +++ b/tests/test_tutorial/test_path_operation_advanced_configurations/test_tutorial007.py @@ -1,14 +1,24 @@ +import importlib + import pytest from fastapi.testclient import TestClient -from ...utils import needs_pydanticv2 +from ...utils import needs_py39, needs_pydanticv2 -@pytest.fixture(name="client") -def get_client(): - from docs_src.path_operation_advanced_configuration.tutorial007 import app +@pytest.fixture( + name="client", + params=[ + pytest.param("tutorial007"), + pytest.param("tutorial007_py39", marks=needs_py39), + ], +) +def get_client(request: pytest.FixtureRequest): + mod = importlib.import_module( + f"docs_src.path_operation_advanced_configuration.{request.param}" + ) - client = TestClient(app) + client = TestClient(mod.app) return client