Browse Source

🔄 Merge branch 'master' into drop-pv1

pull/14609/head
Sebastián Ramírez 7 months ago
parent
commit
fc50d9d438
  1. 4
      docs/en/docs/release-notes.md
  2. 64
      tests/benchmarks/test_general_performance.py

4
docs/en/docs/release-notes.md

@ -7,6 +7,10 @@ hide:
## Latest Changes
### Internal
* ✅ Run performance tests only on Pydantic v2. PR [#14608](https://github.com/fastapi/fastapi/pull/14608) by [@tiangolo](https://github.com/tiangolo).
## 0.127.1
### Refactors

64
tests/benchmarks/test_general_performance.py

@ -1,13 +1,12 @@
import json
import sys
import warnings
from collections.abc import Iterator
from typing import Annotated, Any
import pytest
from fastapi import Depends, FastAPI
from fastapi.exceptions import FastAPIDeprecationWarning
from fastapi.testclient import TestClient
from pydantic import BaseModel
if "--codspeed" not in sys.argv:
pytest.skip(
@ -47,74 +46,57 @@ def dep_b(a: Annotated[int, Depends(dep_a)]):
return a + 2
@pytest.fixture(
scope="module",
params=[
"pydantic-v2",
"pydantic-v1",
],
)
def basemodel_class(request: pytest.FixtureRequest) -> type[Any]:
if request.param == "pydantic-v2":
from pydantic import BaseModel
return BaseModel
else:
from pydantic.v1 import BaseModel
return BaseModel
@pytest.fixture(scope="module")
def app(basemodel_class: type[Any]) -> FastAPI:
class ItemIn(basemodel_class):
class ItemIn(BaseModel):
name: str
value: int
class ItemOut(basemodel_class):
class ItemOut(BaseModel):
name: str
value: int
dep: int
class LargeIn(basemodel_class):
class LargeIn(BaseModel):
items: list[dict[str, Any]]
metadata: dict[str, Any]
class LargeOut(basemodel_class):
class LargeOut(BaseModel):
items: list[dict[str, Any]]
metadata: dict[str, Any]
app = FastAPI()
with warnings.catch_warnings(record=True):
warnings.filterwarnings(
"ignore",
message=r"pydantic\.v1 is deprecated and will soon stop being supported by FastAPI\..*",
category=FastAPIDeprecationWarning,
)
@app.post("/sync/validated", response_model=ItemOut)
def sync_validated(item: ItemIn, dep: Annotated[int, Depends(dep_b)]):
return ItemOut(name=item.name, value=item.value, dep=dep)
@app.get("/sync/dict-no-response-model")
def sync_dict_no_response_model():
return {"name": "foo", "value": 123}
@app.get("/sync/dict-with-response-model", response_model=ItemOut)
def sync_dict_with_response_model(
dep: Annotated[int, Depends(dep_b)],
):
return {"name": "foo", "value": 123, "dep": dep}
@app.get("/sync/model-no-response-model")
def sync_model_no_response_model(dep: Annotated[int, Depends(dep_b)]):
return ItemOut(name="foo", value=123, dep=dep)
@app.get("/sync/model-with-response-model", response_model=ItemOut)
def sync_model_with_response_model(dep: Annotated[int, Depends(dep_b)]):
return ItemOut(name="foo", value=123, dep=dep)
@app.post("/async/validated", response_model=ItemOut)
async def async_validated(
item: ItemIn,
@ -122,73 +104,85 @@ def app(basemodel_class: type[Any]) -> FastAPI:
):
return ItemOut(name=item.name, value=item.value, dep=dep)
@app.post("/sync/large-receive")
def sync_large_receive(payload: LargeIn):
return {"received": len(payload.items)}
@app.post("/async/large-receive")
async def async_large_receive(payload: LargeIn):
return {"received": len(payload.items)}
@app.get("/sync/large-dict-no-response-model")
def sync_large_dict_no_response_model():
return LARGE_PAYLOAD
@app.get("/sync/large-dict-with-response-model", response_model=LargeOut)
def sync_large_dict_with_response_model():
return LARGE_PAYLOAD
@app.get("/sync/large-model-no-response-model")
def sync_large_model_no_response_model():
return LargeOut(items=LARGE_ITEMS, metadata=LARGE_METADATA)
@app.get("/sync/large-model-with-response-model", response_model=LargeOut)
def sync_large_model_with_response_model():
return LargeOut(items=LARGE_ITEMS, metadata=LARGE_METADATA)
@app.get("/async/large-dict-no-response-model")
async def async_large_dict_no_response_model():
return LARGE_PAYLOAD
@app.get("/async/large-dict-with-response-model", response_model=LargeOut)
async def async_large_dict_with_response_model():
return LARGE_PAYLOAD
@app.get("/async/large-model-no-response-model")
async def async_large_model_no_response_model():
return LargeOut(items=LARGE_ITEMS, metadata=LARGE_METADATA)
@app.get("/async/large-model-with-response-model", response_model=LargeOut)
async def async_large_model_with_response_model():
return LargeOut(items=LARGE_ITEMS, metadata=LARGE_METADATA)
@app.get("/async/dict-no-response-model")
async def async_dict_no_response_model():
return {"name": "foo", "value": 123}
@app.get("/async/dict-with-response-model", response_model=ItemOut)
async def async_dict_with_response_model(
dep: Annotated[int, Depends(dep_b)],
):
return {"name": "foo", "value": 123, "dep": dep}
@app.get("/async/model-no-response-model")
async def async_model_no_response_model(
dep: Annotated[int, Depends(dep_b)],
):
return ItemOut(name="foo", value=123, dep=dep)
@app.get("/async/model-with-response-model", response_model=ItemOut)
async def async_model_with_response_model(
dep: Annotated[int, Depends(dep_b)],
):
return ItemOut(name="foo", value=123, dep=dep)
return app
@pytest.fixture(scope="module")
def client(app: FastAPI) -> Iterator[TestClient]:
def client() -> Iterator[TestClient]:
with TestClient(app) as client:
yield client

Loading…
Cancel
Save