Browse Source
v0.128.0 introduced non-deterministic openapi spec schema naming in the case of multiple pydantic models with the same name. Commit [pull/14797/heade300630](e300630551 (diff-1086603fdd56511aafd1d279396b142b803e48164327148e6de26cef4cdaed81L504))removed the check for conflicting names. The component names two classes named `User` would randomly be either ``` User tests__test_duplicate_model_names_openapi__b__model__User ``` ``` tests__test_duplicate_model_names_openapi__a__model__User User ``` With this change, we reintroduce the conflict check to always use a hash of the fully qualified names in case of conflict.
10 changed files with 155 additions and 1 deletions
@ -0,0 +1,5 @@ |
|||
from pydantic import BaseModel |
|||
|
|||
|
|||
class User(BaseModel): |
|||
a: int |
|||
@ -0,0 +1,19 @@ |
|||
from fastapi import FastAPI |
|||
|
|||
from tests.test_duplicate_model_names_openapi.a.model import User as UserA |
|||
from tests.test_duplicate_model_names_openapi.b.model import User as UserB |
|||
from tests.test_duplicate_model_names_openapi.c.model import User as UserC |
|||
|
|||
app = FastAPI() |
|||
|
|||
|
|||
@app.get("/a", response_model=UserA) |
|||
def user_a(): ... |
|||
|
|||
|
|||
@app.get("/b", response_model=UserB) |
|||
def user_b(): ... |
|||
|
|||
|
|||
@app.get("/c", response_model=UserC) |
|||
def user_c(): ... |
|||
@ -0,0 +1,5 @@ |
|||
from pydantic import BaseModel |
|||
|
|||
|
|||
class User(BaseModel): |
|||
b: int |
|||
@ -0,0 +1,5 @@ |
|||
from pydantic import BaseModel |
|||
|
|||
|
|||
class User(BaseModel): |
|||
c: int |
|||
@ -0,0 +1,105 @@ |
|||
import json |
|||
|
|||
from fastapi.testclient import TestClient |
|||
|
|||
from .app import app |
|||
|
|||
client = TestClient(app) |
|||
|
|||
|
|||
def test_openapi_schema(): |
|||
response = client.get("/openapi.json") |
|||
assert response.status_code == 200, response.text |
|||
|
|||
schema = response.json() |
|||
component_names = schema["components"]["schemas"].keys() |
|||
|
|||
# Hashed fully qualified names due to conflict |
|||
assert set(component_names) == { |
|||
"User_46cbb9d5ba5400ba253a3caa105ccc482d1388ff", |
|||
"User_42908c96f764fbf5360c1ae9d3a2a96d90d97bef", |
|||
"User_3c4b81c0ed34bf97eb9b4ac8ced9dc17e0dccbb7", |
|||
} |
|||
|
|||
assert schema == { |
|||
"openapi": "3.1.0", |
|||
"info": {"title": "FastAPI", "version": "0.1.0"}, |
|||
"paths": { |
|||
"/a": { |
|||
"get": { |
|||
"summary": "User A", |
|||
"operationId": "user_a_a_get", |
|||
"responses": { |
|||
"200": { |
|||
"description": "Successful Response", |
|||
"content": { |
|||
"application/json": { |
|||
"schema": { |
|||
"$ref": "#/components/schemas/User_42908c96f764fbf5360c1ae9d3a2a96d90d97bef" |
|||
} |
|||
} |
|||
}, |
|||
} |
|||
}, |
|||
} |
|||
}, |
|||
"/b": { |
|||
"get": { |
|||
"summary": "User B", |
|||
"operationId": "user_b_b_get", |
|||
"responses": { |
|||
"200": { |
|||
"description": "Successful Response", |
|||
"content": { |
|||
"application/json": { |
|||
"schema": { |
|||
"$ref": "#/components/schemas/User_3c4b81c0ed34bf97eb9b4ac8ced9dc17e0dccbb7" |
|||
} |
|||
} |
|||
}, |
|||
} |
|||
}, |
|||
} |
|||
}, |
|||
"/c": { |
|||
"get": { |
|||
"summary": "User C", |
|||
"operationId": "user_c_c_get", |
|||
"responses": { |
|||
"200": { |
|||
"description": "Successful Response", |
|||
"content": { |
|||
"application/json": { |
|||
"schema": { |
|||
"$ref": "#/components/schemas/User_46cbb9d5ba5400ba253a3caa105ccc482d1388ff" |
|||
} |
|||
} |
|||
}, |
|||
} |
|||
}, |
|||
} |
|||
}, |
|||
}, |
|||
"components": { |
|||
"schemas": { |
|||
"User_3c4b81c0ed34bf97eb9b4ac8ced9dc17e0dccbb7": { |
|||
"properties": {"b": {"type": "integer", "title": "B"}}, |
|||
"type": "object", |
|||
"required": ["b"], |
|||
"title": "User", |
|||
}, |
|||
"User_42908c96f764fbf5360c1ae9d3a2a96d90d97bef": { |
|||
"properties": {"a": {"type": "integer", "title": "A"}}, |
|||
"type": "object", |
|||
"required": ["a"], |
|||
"title": "User", |
|||
}, |
|||
"User_46cbb9d5ba5400ba253a3caa105ccc482d1388ff": { |
|||
"properties": {"c": {"type": "integer", "title": "C"}}, |
|||
"type": "object", |
|||
"required": ["c"], |
|||
"title": "User", |
|||
}, |
|||
} |
|||
}, |
|||
} |
|||
Loading…
Reference in new issue