mirror of https://github.com/tiangolo/fastapi.git
🏗️ Fix same function names in different modules with composite bodies (#347)
* 🏗️ Implement unique IDs for dynamic models like those used for composite bodies and responses. IDs based on path (not only on function name, as it can be duplicated in a different module). * ✅ Add tests for same function name and composite body * ✅ Update OpenAPI in tests with new dynamic model ID generation
This commit is contained in:
parent
b30cca8e9e
commit
687065509b
|
|
@ -8,7 +8,11 @@ from fastapi.encoders import jsonable_encoder
|
|||
from fastapi.openapi.constants import METHODS_WITH_BODY, REF_PREFIX
|
||||
from fastapi.openapi.models import OpenAPI
|
||||
from fastapi.params import Body, Param
|
||||
from fastapi.utils import get_flat_models_from_routes, get_model_definitions
|
||||
from fastapi.utils import (
|
||||
generate_operation_id_for_path,
|
||||
get_flat_models_from_routes,
|
||||
get_model_definitions,
|
||||
)
|
||||
from pydantic.fields import Field
|
||||
from pydantic.schema import field_schema, get_model_name_map
|
||||
from pydantic.utils import lenient_issubclass
|
||||
|
|
@ -113,10 +117,7 @@ def generate_operation_id(*, route: routing.APIRoute, method: str) -> str:
|
|||
if route.operation_id:
|
||||
return route.operation_id
|
||||
path: str = route.path_format
|
||||
operation_id = route.name + path
|
||||
operation_id = operation_id.replace("{", "_").replace("}", "_").replace("/", "_")
|
||||
operation_id = operation_id + "_" + method.lower()
|
||||
return operation_id
|
||||
return generate_operation_id_for_path(name=route.name, path=path, method=method)
|
||||
|
||||
|
||||
def generate_operation_summary(*, route: routing.APIRoute, method: str) -> str:
|
||||
|
|
|
|||
|
|
@ -13,7 +13,7 @@ from fastapi.dependencies.utils import (
|
|||
)
|
||||
from fastapi.encoders import jsonable_encoder
|
||||
from fastapi.exceptions import RequestValidationError, WebSocketRequestValidationError
|
||||
from fastapi.utils import create_cloned_field
|
||||
from fastapi.utils import create_cloned_field, generate_operation_id_for_path
|
||||
from pydantic import BaseConfig, BaseModel, Schema
|
||||
from pydantic.error_wrappers import ErrorWrapper, ValidationError
|
||||
from pydantic.fields import Field
|
||||
|
|
@ -205,12 +205,19 @@ class APIRoute(routing.Route):
|
|||
self.path = path
|
||||
self.endpoint = endpoint
|
||||
self.name = get_name(endpoint) if name is None else name
|
||||
self.path_regex, self.path_format, self.param_convertors = compile_path(path)
|
||||
if methods is None:
|
||||
methods = ["GET"]
|
||||
self.methods = set([method.upper() for method in methods])
|
||||
self.unique_id = generate_operation_id_for_path(
|
||||
name=self.name, path=self.path_format, method=list(methods)[0]
|
||||
)
|
||||
self.response_model = response_model
|
||||
if self.response_model:
|
||||
assert lenient_issubclass(
|
||||
response_class, JSONResponse
|
||||
), "To declare a type the response must be a JSON response"
|
||||
response_name = "Response_" + self.name
|
||||
response_name = "Response_" + self.unique_id
|
||||
self.response_field: Optional[Field] = Field(
|
||||
name=response_name,
|
||||
type_=self.response_model,
|
||||
|
|
@ -251,7 +258,7 @@ class APIRoute(routing.Route):
|
|||
assert lenient_issubclass(
|
||||
model, BaseModel
|
||||
), "A response model must be a Pydantic model"
|
||||
response_name = f"Response_{additional_status_code}_{self.name}"
|
||||
response_name = f"Response_{additional_status_code}_{self.unique_id}"
|
||||
response_field = Field(
|
||||
name=response_name,
|
||||
type_=model,
|
||||
|
|
@ -267,9 +274,6 @@ class APIRoute(routing.Route):
|
|||
else:
|
||||
self.response_fields = {}
|
||||
self.deprecated = deprecated
|
||||
if methods is None:
|
||||
methods = ["GET"]
|
||||
self.methods = set([method.upper() for method in methods])
|
||||
self.operation_id = operation_id
|
||||
self.response_model_include = response_model_include
|
||||
self.response_model_exclude = response_model_exclude
|
||||
|
|
@ -278,7 +282,6 @@ class APIRoute(routing.Route):
|
|||
self.include_in_schema = include_in_schema
|
||||
self.response_class = response_class
|
||||
|
||||
self.path_regex, self.path_format, self.param_convertors = compile_path(path)
|
||||
assert inspect.isfunction(endpoint) or inspect.ismethod(
|
||||
endpoint
|
||||
), f"An endpoint must be a function or method"
|
||||
|
|
@ -288,7 +291,7 @@ class APIRoute(routing.Route):
|
|||
0,
|
||||
get_parameterless_sub_dependant(depends=depends, path=self.path_format),
|
||||
)
|
||||
self.body_field = get_body_field(dependant=self.dependant, name=self.name)
|
||||
self.body_field = get_body_field(dependant=self.dependant, name=self.unique_id)
|
||||
self.dependency_overrides_provider = dependency_overrides_provider
|
||||
self.app = request_response(
|
||||
get_app(
|
||||
|
|
|
|||
|
|
@ -93,3 +93,10 @@ def create_cloned_field(field: Field) -> Field:
|
|||
new_field.shape = field.shape
|
||||
new_field._populate_validators()
|
||||
return new_field
|
||||
|
||||
|
||||
def generate_operation_id_for_path(*, name: str, path: str, method: str) -> str:
|
||||
operation_id = name + path
|
||||
operation_id = operation_id.replace("{", "_").replace("}", "_").replace("/", "_")
|
||||
operation_id = operation_id + "_" + method.lower()
|
||||
return operation_id
|
||||
|
|
|
|||
|
|
@ -0,0 +1,8 @@
|
|||
from fastapi import APIRouter, Body
|
||||
|
||||
router = APIRouter()
|
||||
|
||||
|
||||
@router.post("/compute")
|
||||
def compute(a: int = Body(...), b: str = Body(...)):
|
||||
return {"a": a, "b": b}
|
||||
|
|
@ -0,0 +1,8 @@
|
|||
from fastapi import APIRouter, Body
|
||||
|
||||
router = APIRouter()
|
||||
|
||||
|
||||
@router.post("/compute/")
|
||||
def compute(a: int = Body(...), b: str = Body(...)):
|
||||
return {"a": a, "b": b}
|
||||
|
|
@ -0,0 +1,8 @@
|
|||
from fastapi import FastAPI
|
||||
|
||||
from . import a, b
|
||||
|
||||
app = FastAPI()
|
||||
|
||||
app.include_router(a.router, prefix="/a")
|
||||
app.include_router(b.router, prefix="/b")
|
||||
|
|
@ -0,0 +1,155 @@
|
|||
from starlette.testclient import TestClient
|
||||
|
||||
from .app.main import app
|
||||
|
||||
client = TestClient(app)
|
||||
|
||||
openapi_schema = {
|
||||
"openapi": "3.0.2",
|
||||
"info": {"title": "Fast API", "version": "0.1.0"},
|
||||
"paths": {
|
||||
"/a/compute": {
|
||||
"post": {
|
||||
"responses": {
|
||||
"200": {
|
||||
"description": "Successful Response",
|
||||
"content": {"application/json": {"schema": {}}},
|
||||
},
|
||||
"422": {
|
||||
"description": "Validation Error",
|
||||
"content": {
|
||||
"application/json": {
|
||||
"schema": {
|
||||
"$ref": "#/components/schemas/HTTPValidationError"
|
||||
}
|
||||
}
|
||||
},
|
||||
},
|
||||
},
|
||||
"summary": "Compute",
|
||||
"operationId": "compute_a_compute_post",
|
||||
"requestBody": {
|
||||
"content": {
|
||||
"application/json": {
|
||||
"schema": {
|
||||
"$ref": "#/components/schemas/Body_compute_a_compute_post"
|
||||
}
|
||||
}
|
||||
},
|
||||
"required": True,
|
||||
},
|
||||
}
|
||||
},
|
||||
"/b/compute/": {
|
||||
"post": {
|
||||
"responses": {
|
||||
"200": {
|
||||
"description": "Successful Response",
|
||||
"content": {"application/json": {"schema": {}}},
|
||||
},
|
||||
"422": {
|
||||
"description": "Validation Error",
|
||||
"content": {
|
||||
"application/json": {
|
||||
"schema": {
|
||||
"$ref": "#/components/schemas/HTTPValidationError"
|
||||
}
|
||||
}
|
||||
},
|
||||
},
|
||||
},
|
||||
"summary": "Compute",
|
||||
"operationId": "compute_b_compute__post",
|
||||
"requestBody": {
|
||||
"content": {
|
||||
"application/json": {
|
||||
"schema": {
|
||||
"$ref": "#/components/schemas/Body_compute_b_compute__post"
|
||||
}
|
||||
}
|
||||
},
|
||||
"required": True,
|
||||
},
|
||||
}
|
||||
},
|
||||
},
|
||||
"components": {
|
||||
"schemas": {
|
||||
"Body_compute_b_compute__post": {
|
||||
"title": "Body_compute_b_compute__post",
|
||||
"required": ["a", "b"],
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"a": {"title": "A", "type": "integer"},
|
||||
"b": {"title": "B", "type": "string"},
|
||||
},
|
||||
},
|
||||
"Body_compute_a_compute_post": {
|
||||
"title": "Body_compute_a_compute_post",
|
||||
"required": ["a", "b"],
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"a": {"title": "A", "type": "integer"},
|
||||
"b": {"title": "B", "type": "string"},
|
||||
},
|
||||
},
|
||||
"ValidationError": {
|
||||
"title": "ValidationError",
|
||||
"required": ["loc", "msg", "type"],
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"loc": {
|
||||
"title": "Location",
|
||||
"type": "array",
|
||||
"items": {"type": "string"},
|
||||
},
|
||||
"msg": {"title": "Message", "type": "string"},
|
||||
"type": {"title": "Error Type", "type": "string"},
|
||||
},
|
||||
},
|
||||
"HTTPValidationError": {
|
||||
"title": "HTTPValidationError",
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"detail": {
|
||||
"title": "Detail",
|
||||
"type": "array",
|
||||
"items": {"$ref": "#/components/schemas/ValidationError"},
|
||||
}
|
||||
},
|
||||
},
|
||||
}
|
||||
},
|
||||
}
|
||||
|
||||
|
||||
def test_openapi_schema():
|
||||
response = client.get("/openapi.json")
|
||||
assert response.status_code == 200
|
||||
assert response.json() == openapi_schema
|
||||
|
||||
|
||||
def test_post_a():
|
||||
data = {"a": 2, "b": "foo"}
|
||||
response = client.post("/a/compute", json=data)
|
||||
assert response.status_code == 200
|
||||
data = response.json()
|
||||
|
||||
|
||||
def test_post_a_invalid():
|
||||
data = {"a": "bar", "b": "foo"}
|
||||
response = client.post("/a/compute", json=data)
|
||||
assert response.status_code == 422
|
||||
|
||||
|
||||
def test_post_b():
|
||||
data = {"a": 2, "b": "foo"}
|
||||
response = client.post("/b/compute/", json=data)
|
||||
assert response.status_code == 200
|
||||
data = response.json()
|
||||
|
||||
|
||||
def test_post_b_invalid():
|
||||
data = {"a": "bar", "b": "foo"}
|
||||
response = client.post("/b/compute/", json=data)
|
||||
assert response.status_code == 422
|
||||
|
|
@ -66,7 +66,7 @@ openapi_schema = {
|
|||
"content": {
|
||||
"application/x-www-form-urlencoded": {
|
||||
"schema": {
|
||||
"$ref": "#/components/schemas/Body_read_current_user"
|
||||
"$ref": "#/components/schemas/Body_read_current_user_login_post"
|
||||
}
|
||||
}
|
||||
},
|
||||
|
|
@ -90,8 +90,8 @@ openapi_schema = {
|
|||
},
|
||||
"components": {
|
||||
"schemas": {
|
||||
"Body_read_current_user": {
|
||||
"title": "Body_read_current_user",
|
||||
"Body_read_current_user_login_post": {
|
||||
"title": "Body_read_current_user_login_post",
|
||||
"required": ["grant_type", "username", "password"],
|
||||
"type": "object",
|
||||
"properties": {
|
||||
|
|
|
|||
|
|
@ -73,7 +73,7 @@ openapi_schema = {
|
|||
"content": {
|
||||
"application/x-www-form-urlencoded": {
|
||||
"schema": {
|
||||
"$ref": "#/components/schemas/Body_read_current_user"
|
||||
"$ref": "#/components/schemas/Body_read_current_user_login_post"
|
||||
}
|
||||
}
|
||||
},
|
||||
|
|
@ -97,8 +97,8 @@ openapi_schema = {
|
|||
},
|
||||
"components": {
|
||||
"schemas": {
|
||||
"Body_read_current_user": {
|
||||
"title": "Body_read_current_user",
|
||||
"Body_read_current_user_login_post": {
|
||||
"title": "Body_read_current_user_login_post",
|
||||
"required": ["grant_type", "username", "password"],
|
||||
"type": "object",
|
||||
"properties": {
|
||||
|
|
|
|||
|
|
@ -14,7 +14,7 @@ openapi_schema = {
|
|||
"content": {
|
||||
"application/json": {
|
||||
"schema": {
|
||||
"title": "Response_Read_Notes",
|
||||
"title": "Response_Read_Notes_Notes__Get",
|
||||
"type": "array",
|
||||
"items": {"$ref": "#/components/schemas/Note"},
|
||||
}
|
||||
|
|
|
|||
|
|
@ -40,7 +40,9 @@ openapi_schema = {
|
|||
"requestBody": {
|
||||
"content": {
|
||||
"application/json": {
|
||||
"schema": {"$ref": "#/components/schemas/Body_update_item"}
|
||||
"schema": {
|
||||
"$ref": "#/components/schemas/Body_update_item_items__item_id__put"
|
||||
}
|
||||
}
|
||||
},
|
||||
"required": True,
|
||||
|
|
@ -70,8 +72,8 @@ openapi_schema = {
|
|||
"full_name": {"title": "Full_Name", "type": "string"},
|
||||
},
|
||||
},
|
||||
"Body_update_item": {
|
||||
"title": "Body_update_item",
|
||||
"Body_update_item_items__item_id__put": {
|
||||
"title": "Body_update_item_items__item_id__put",
|
||||
"required": ["item", "user", "importance"],
|
||||
"type": "object",
|
||||
"properties": {
|
||||
|
|
|
|||
|
|
@ -41,7 +41,9 @@ openapi_schema = {
|
|||
"requestBody": {
|
||||
"content": {
|
||||
"application/json": {
|
||||
"schema": {"$ref": "#/components/schemas/Body_update_item"}
|
||||
"schema": {
|
||||
"$ref": "#/components/schemas/Body_update_item_items__item_id__put"
|
||||
}
|
||||
}
|
||||
},
|
||||
"required": True,
|
||||
|
|
@ -71,8 +73,8 @@ openapi_schema = {
|
|||
"tax": {"title": "Tax", "type": "number"},
|
||||
},
|
||||
},
|
||||
"Body_update_item": {
|
||||
"title": "Body_update_item",
|
||||
"Body_update_item_items__item_id__put": {
|
||||
"title": "Body_update_item_items__item_id__put",
|
||||
"required": ["item"],
|
||||
"type": "object",
|
||||
"properties": {"item": {"$ref": "#/components/schemas/Item"}},
|
||||
|
|
|
|||
|
|
@ -44,7 +44,9 @@ openapi_schema = {
|
|||
"requestBody": {
|
||||
"content": {
|
||||
"application/json": {
|
||||
"schema": {"$ref": "#/components/schemas/Body_read_items"}
|
||||
"schema": {
|
||||
"$ref": "#/components/schemas/Body_read_items_items__item_id__put"
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
|
|
@ -53,8 +55,8 @@ openapi_schema = {
|
|||
},
|
||||
"components": {
|
||||
"schemas": {
|
||||
"Body_read_items": {
|
||||
"title": "Body_read_items",
|
||||
"Body_read_items_items__item_id__put": {
|
||||
"title": "Body_read_items_items__item_id__put",
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"start_datetime": {
|
||||
|
|
|
|||
|
|
@ -16,7 +16,7 @@ openapi_schema = {
|
|||
"content": {
|
||||
"application/json": {
|
||||
"schema": {
|
||||
"title": "Response_Read_Item",
|
||||
"title": "Response_Read_Item_Items__Item_Id__Get",
|
||||
"anyOf": [
|
||||
{"$ref": "#/components/schemas/PlaneItem"},
|
||||
{"$ref": "#/components/schemas/CarItem"},
|
||||
|
|
|
|||
|
|
@ -16,7 +16,7 @@ openapi_schema = {
|
|||
"content": {
|
||||
"application/json": {
|
||||
"schema": {
|
||||
"title": "Response_Read_Items",
|
||||
"title": "Response_Read_Items_Items__Get",
|
||||
"type": "array",
|
||||
"items": {"$ref": "#/components/schemas/Item"},
|
||||
}
|
||||
|
|
|
|||
|
|
@ -16,7 +16,7 @@ openapi_schema = {
|
|||
"content": {
|
||||
"application/json": {
|
||||
"schema": {
|
||||
"title": "Response_Read_Keyword_Weights",
|
||||
"title": "Response_Read_Keyword_Weights_Keyword-Weights__Get",
|
||||
"type": "object",
|
||||
"additionalProperties": {"type": "number"},
|
||||
}
|
||||
|
|
|
|||
|
|
@ -33,7 +33,9 @@ openapi_schema = {
|
|||
"requestBody": {
|
||||
"content": {
|
||||
"multipart/form-data": {
|
||||
"schema": {"$ref": "#/components/schemas/Body_create_file"}
|
||||
"schema": {
|
||||
"$ref": "#/components/schemas/Body_create_file_files__post"
|
||||
}
|
||||
}
|
||||
},
|
||||
"required": True,
|
||||
|
|
@ -64,7 +66,7 @@ openapi_schema = {
|
|||
"content": {
|
||||
"multipart/form-data": {
|
||||
"schema": {
|
||||
"$ref": "#/components/schemas/Body_create_upload_file"
|
||||
"$ref": "#/components/schemas/Body_create_upload_file_uploadfile__post"
|
||||
}
|
||||
}
|
||||
},
|
||||
|
|
@ -75,16 +77,16 @@ openapi_schema = {
|
|||
},
|
||||
"components": {
|
||||
"schemas": {
|
||||
"Body_create_file": {
|
||||
"title": "Body_create_file",
|
||||
"Body_create_upload_file_uploadfile__post": {
|
||||
"title": "Body_create_upload_file_uploadfile__post",
|
||||
"required": ["file"],
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"file": {"title": "File", "type": "string", "format": "binary"}
|
||||
},
|
||||
},
|
||||
"Body_create_upload_file": {
|
||||
"title": "Body_create_upload_file",
|
||||
"Body_create_file_files__post": {
|
||||
"title": "Body_create_file_files__post",
|
||||
"required": ["file"],
|
||||
"type": "object",
|
||||
"properties": {
|
||||
|
|
|
|||
|
|
@ -33,7 +33,9 @@ openapi_schema = {
|
|||
"requestBody": {
|
||||
"content": {
|
||||
"multipart/form-data": {
|
||||
"schema": {"$ref": "#/components/schemas/Body_create_files"}
|
||||
"schema": {
|
||||
"$ref": "#/components/schemas/Body_create_files_files__post"
|
||||
}
|
||||
}
|
||||
},
|
||||
"required": True,
|
||||
|
|
@ -64,7 +66,7 @@ openapi_schema = {
|
|||
"content": {
|
||||
"multipart/form-data": {
|
||||
"schema": {
|
||||
"$ref": "#/components/schemas/Body_create_upload_files"
|
||||
"$ref": "#/components/schemas/Body_create_upload_files_uploadfiles__post"
|
||||
}
|
||||
}
|
||||
},
|
||||
|
|
@ -87,8 +89,8 @@ openapi_schema = {
|
|||
},
|
||||
"components": {
|
||||
"schemas": {
|
||||
"Body_create_files": {
|
||||
"title": "Body_create_files",
|
||||
"Body_create_upload_files_uploadfiles__post": {
|
||||
"title": "Body_create_upload_files_uploadfiles__post",
|
||||
"required": ["files"],
|
||||
"type": "object",
|
||||
"properties": {
|
||||
|
|
@ -99,8 +101,8 @@ openapi_schema = {
|
|||
}
|
||||
},
|
||||
},
|
||||
"Body_create_upload_files": {
|
||||
"title": "Body_create_upload_files",
|
||||
"Body_create_files_files__post": {
|
||||
"title": "Body_create_files_files__post",
|
||||
"required": ["files"],
|
||||
"type": "object",
|
||||
"properties": {
|
||||
|
|
|
|||
|
|
@ -32,7 +32,9 @@ openapi_schema = {
|
|||
"requestBody": {
|
||||
"content": {
|
||||
"application/x-www-form-urlencoded": {
|
||||
"schema": {"$ref": "#/components/schemas/Body_login"}
|
||||
"schema": {
|
||||
"$ref": "#/components/schemas/Body_login_login__post"
|
||||
}
|
||||
}
|
||||
},
|
||||
"required": True,
|
||||
|
|
@ -42,8 +44,8 @@ openapi_schema = {
|
|||
},
|
||||
"components": {
|
||||
"schemas": {
|
||||
"Body_login": {
|
||||
"title": "Body_login",
|
||||
"Body_login_login__post": {
|
||||
"title": "Body_login_login__post",
|
||||
"required": ["username", "password"],
|
||||
"type": "object",
|
||||
"properties": {
|
||||
|
|
|
|||
|
|
@ -34,7 +34,9 @@ openapi_schema = {
|
|||
"requestBody": {
|
||||
"content": {
|
||||
"multipart/form-data": {
|
||||
"schema": {"$ref": "#/components/schemas/Body_create_file"}
|
||||
"schema": {
|
||||
"$ref": "#/components/schemas/Body_create_file_files__post"
|
||||
}
|
||||
}
|
||||
},
|
||||
"required": True,
|
||||
|
|
@ -44,8 +46,8 @@ openapi_schema = {
|
|||
},
|
||||
"components": {
|
||||
"schemas": {
|
||||
"Body_create_file": {
|
||||
"title": "Body_create_file",
|
||||
"Body_create_file_files__post": {
|
||||
"title": "Body_create_file_files__post",
|
||||
"required": ["file", "fileb", "token"],
|
||||
"type": "object",
|
||||
"properties": {
|
||||
|
|
|
|||
|
|
@ -31,7 +31,9 @@ openapi_schema = {
|
|||
"requestBody": {
|
||||
"content": {
|
||||
"application/x-www-form-urlencoded": {
|
||||
"schema": {"$ref": "#/components/schemas/Body_login"}
|
||||
"schema": {
|
||||
"$ref": "#/components/schemas/Body_login_token_post"
|
||||
}
|
||||
}
|
||||
},
|
||||
"required": True,
|
||||
|
|
@ -54,8 +56,8 @@ openapi_schema = {
|
|||
},
|
||||
"components": {
|
||||
"schemas": {
|
||||
"Body_login": {
|
||||
"title": "Body_login",
|
||||
"Body_login_token_post": {
|
||||
"title": "Body_login_token_post",
|
||||
"required": ["username", "password"],
|
||||
"type": "object",
|
||||
"properties": {
|
||||
|
|
|
|||
|
|
@ -42,7 +42,7 @@ openapi_schema = {
|
|||
"content": {
|
||||
"application/x-www-form-urlencoded": {
|
||||
"schema": {
|
||||
"$ref": "#/components/schemas/Body_login_for_access_token"
|
||||
"$ref": "#/components/schemas/Body_login_for_access_token_token_post"
|
||||
}
|
||||
}
|
||||
},
|
||||
|
|
@ -116,8 +116,8 @@ openapi_schema = {
|
|||
"token_type": {"title": "Token_Type", "type": "string"},
|
||||
},
|
||||
},
|
||||
"Body_login_for_access_token": {
|
||||
"title": "Body_login_for_access_token",
|
||||
"Body_login_for_access_token_token_post": {
|
||||
"title": "Body_login_for_access_token_token_post",
|
||||
"required": ["username", "password"],
|
||||
"type": "object",
|
||||
"properties": {
|
||||
|
|
@ -177,6 +177,12 @@ openapi_schema = {
|
|||
}
|
||||
|
||||
|
||||
def test_openapi_schema():
|
||||
response = client.get("/openapi.json")
|
||||
assert response.status_code == 200
|
||||
assert response.json() == openapi_schema
|
||||
|
||||
|
||||
def get_access_token(username="johndoe", password="secret", scope=None):
|
||||
data = {"username": username, "password": password}
|
||||
if scope:
|
||||
|
|
@ -187,12 +193,6 @@ def get_access_token(username="johndoe", password="secret", scope=None):
|
|||
return access_token
|
||||
|
||||
|
||||
def test_openapi_schema():
|
||||
response = client.get("/openapi.json")
|
||||
assert response.status_code == 200
|
||||
assert response.json() == openapi_schema
|
||||
|
||||
|
||||
def test_login():
|
||||
response = client.post("/token", data={"username": "johndoe", "password": "secret"})
|
||||
assert response.status_code == 200
|
||||
|
|
|
|||
|
|
@ -16,7 +16,7 @@ openapi_schema = {
|
|||
"content": {
|
||||
"application/json": {
|
||||
"schema": {
|
||||
"title": "Response_Read_Users",
|
||||
"title": "Response_Read_Users_Users__Get",
|
||||
"type": "array",
|
||||
"items": {"$ref": "#/components/schemas/User"},
|
||||
}
|
||||
|
|
@ -168,7 +168,7 @@ openapi_schema = {
|
|||
"content": {
|
||||
"application/json": {
|
||||
"schema": {
|
||||
"title": "Response_Read_Items",
|
||||
"title": "Response_Read_Items_Items__Get",
|
||||
"type": "array",
|
||||
"items": {"$ref": "#/components/schemas/Item"},
|
||||
}
|
||||
|
|
|
|||
Loading…
Reference in New Issue