]> git.ipfire.org Git - thirdparty/fastapi/fastapi.git/commitdiff
🐛 Avoid accessing non-existing "$ref" key for Pydantic v2 compat remapping (#14361)
authorSofie Van Landeghem <svlandeg@users.noreply.github.com>
Tue, 2 Dec 2025 04:04:13 +0000 (09:34 +0530)
committerGitHub <noreply@github.com>
Tue, 2 Dec 2025 04:04:13 +0000 (05:04 +0100)
Co-authored-by: pre-commit-ci[bot] <66853113+pre-commit-ci[bot]@users.noreply.github.com>
fastapi/_compat/v2.py
tests/test_schema_compat_pydantic_v2.py [new file with mode: 0644]

index 5cd49343b66fcfb40ee3910195be4641a3d696fc..7196a6190feae3d40ca2553088a041bec7ad3103 100644 (file)
@@ -304,7 +304,7 @@ def _remap_definitions_and_field_mappings(
     old_name_to_new_name_map = {}
     for field_key, schema in field_mapping.items():
         model = field_key[0].type_
-        if model not in model_name_map:
+        if model not in model_name_map or "$ref" not in schema:
             continue
         new_name = model_name_map[model]
         old_name = schema["$ref"].split("/")[-1]
diff --git a/tests/test_schema_compat_pydantic_v2.py b/tests/test_schema_compat_pydantic_v2.py
new file mode 100644 (file)
index 0000000..39626c0
--- /dev/null
@@ -0,0 +1,92 @@
+import pytest
+from fastapi import FastAPI
+from fastapi.testclient import TestClient
+from inline_snapshot import snapshot
+from pydantic import BaseModel
+
+from tests.utils import needs_py310, needs_pydanticv2
+
+
+@pytest.fixture(name="client")
+def get_client():
+    from enum import Enum
+
+    app = FastAPI()
+
+    class PlatformRole(str, Enum):
+        admin = "admin"
+        user = "user"
+
+    class OtherRole(str, Enum): ...
+
+    class User(BaseModel):
+        username: str
+        role: PlatformRole | OtherRole
+
+    @app.get("/users")
+    async def get_user() -> User:
+        return {"username": "alice", "role": "admin"}
+
+    client = TestClient(app)
+    return client
+
+
+@needs_py310
+@needs_pydanticv2
+def test_get(client: TestClient):
+    response = client.get("/users")
+    assert response.json() == {"username": "alice", "role": "admin"}
+
+
+@needs_py310
+@needs_pydanticv2
+def test_openapi_schema(client: TestClient):
+    response = client.get("openapi.json")
+    assert response.json() == snapshot(
+        {
+            "openapi": "3.1.0",
+            "info": {"title": "FastAPI", "version": "0.1.0"},
+            "paths": {
+                "/users": {
+                    "get": {
+                        "summary": "Get User",
+                        "operationId": "get_user_users_get",
+                        "responses": {
+                            "200": {
+                                "description": "Successful Response",
+                                "content": {
+                                    "application/json": {
+                                        "schema": {"$ref": "#/components/schemas/User"}
+                                    }
+                                },
+                            }
+                        },
+                    }
+                }
+            },
+            "components": {
+                "schemas": {
+                    "PlatformRole": {
+                        "type": "string",
+                        "enum": ["admin", "user"],
+                        "title": "PlatformRole",
+                    },
+                    "User": {
+                        "properties": {
+                            "username": {"type": "string", "title": "Username"},
+                            "role": {
+                                "anyOf": [
+                                    {"$ref": "#/components/schemas/PlatformRole"},
+                                    {"enum": [], "title": "OtherRole"},
+                                ],
+                                "title": "Role",
+                            },
+                        },
+                        "type": "object",
+                        "required": ["username", "role"],
+                        "title": "User",
+                    },
+                }
+            },
+        }
+    )