Skip to content

Commit

Permalink
🎉 Use function return type annotation as response_model
Browse files Browse the repository at this point in the history
  • Loading branch information
uriyyo committed May 20, 2020
1 parent 601d8eb commit 17e4878
Show file tree
Hide file tree
Showing 2 changed files with 130 additions and 1 deletion.
13 changes: 12 additions & 1 deletion fastapi/routing.py
Expand Up @@ -91,6 +91,13 @@ def _prepare_response_content(
return res


def _get_return_annotation(func: Callable) -> Optional[Type[Any]]:
try:
return func.__annotations__["return"]
except (AttributeError, KeyError):
return None


async def serialize_response(
*,
field: ModelField = None,
Expand Down Expand Up @@ -305,7 +312,11 @@ def __init__(
self.unique_id = generate_operation_id_for_path(
name=self.name, path=self.path_format, method=list(methods)[0]
)
self.response_model = response_model
self.response_model = (
_get_return_annotation(endpoint)
if response_model is None
else response_model
)
if self.response_model:
assert (
status_code not in STATUS_CODES_WITH_NO_BODY
Expand Down
118 changes: 118 additions & 0 deletions tests/test_response_model_as_return_annotation.py
@@ -0,0 +1,118 @@
from fastapi import FastAPI
from fastapi.testclient import TestClient
from pydantic import BaseModel


class ModelOne(BaseModel):
name: str


class ModelTwo(BaseModel):
surname: str


app = FastAPI()


@app.get("/valid1")
def valid1() -> ModelOne:
pass


@app.get("/valid2", response_model=ModelTwo)
def valid2():
pass


@app.get("/valid3", response_model=ModelTwo)
def valid3() -> ModelOne:
pass


openapi_schema = {
"openapi": "3.0.2",
"info": {"title": "FastAPI", "version": "0.1.0"},
"paths": {
"/valid1": {
"get": {
"summary": "Valid1",
"operationId": "valid1_valid1_get",
"responses": {
"200": {
"description": "Successful Response",
"content": {
"application/json": {
"schema": {"$ref": "#/components/schemas/ModelOne"}
}
},
}
},
}
},
"/valid2": {
"get": {
"summary": "Valid2",
"operationId": "valid2_valid2_get",
"responses": {
"200": {
"description": "Successful Response",
"content": {
"application/json": {
"schema": {"$ref": "#/components/schemas/ModelTwo"}
}
},
}
},
}
},
"/valid3": {
"get": {
"summary": "Valid3",
"operationId": "valid3_valid3_get",
"responses": {
"200": {
"description": "Successful Response",
"content": {
"application/json": {
"schema": {"$ref": "#/components/schemas/ModelTwo"}
}
},
}
},
}
},
},
"components": {
"schemas": {
"ModelOne": {
"title": "ModelOne",
"required": ["name"],
"type": "object",
"properties": {"name": {"title": "Name", "type": "string"}},
},
"ModelTwo": {
"title": "ModelTwo",
"required": ["surname"],
"type": "object",
"properties": {"surname": {"title": "Surname", "type": "string"}},
},
}
},
}

client = TestClient(app)


def test_openapi_schema():
response = client.get("/openapi.json")
assert response.status_code == 200, response.text
assert response.json() == openapi_schema


def test_path_operations():
response = client.get("/valid1")
assert response.status_code == 200, response.text
response = client.get("/valid2")
assert response.status_code == 200, response.text
response = client.get("/valid3")
assert response.status_code == 200, response.text

0 comments on commit 17e4878

Please sign in to comment.