Browse Source

Run performance tests only on Pydantic v2 (#14608)

pull/13988/merge
Sebastián Ramírez 5 months ago
committed by GitHub
parent
commit
34e884156f
No known key found for this signature in database GPG Key ID: B5690EEEBB952194
  1. 268
      tests/benchmarks/test_general_performance.py

268
tests/benchmarks/test_general_performance.py

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

Loading…
Cancel
Save