pythonasyncioapiasyncfastapiframeworkjsonjson-schemaopenapiopenapi3pydanticpython-typespython3redocreststarletteswaggerswagger-uiuvicornweb
You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
57 lines
1.5 KiB
57 lines
1.5 KiB
from typing import Any, Dict, Union
|
|
|
|
import pytest
|
|
from fastapi import FastAPI
|
|
from fastapi.testclient import TestClient
|
|
from typing_extensions import Annotated
|
|
|
|
from .utils import needs_pydanticv2
|
|
|
|
|
|
@pytest.fixture(name="client")
|
|
def get_client() -> TestClient:
|
|
from pydantic import BaseModel, Discriminator, Tag
|
|
|
|
app = FastAPI()
|
|
|
|
class FirstItem(BaseModel):
|
|
value: str
|
|
price: int
|
|
|
|
class OtherItem(BaseModel):
|
|
value: str
|
|
price: float
|
|
|
|
def get_discriminator_value(v: Any) -> str:
|
|
if isinstance(v, dict):
|
|
return v.get("value")
|
|
return v.value
|
|
|
|
Item = Annotated[
|
|
Union[
|
|
Annotated[FirstItem, Tag("first")],
|
|
Annotated[OtherItem, Tag("other")],
|
|
],
|
|
Discriminator(get_discriminator_value),
|
|
]
|
|
|
|
@app.post("/items/")
|
|
def save_union_body_discriminator(item: Item) -> Dict[str, Any]:
|
|
return {"item": item}
|
|
|
|
client = TestClient(app)
|
|
return client
|
|
|
|
|
|
@needs_pydanticv2
|
|
def test_post_item(client: TestClient) -> None:
|
|
response = client.post("/items/", json={"value": "first", "price": 100})
|
|
assert response.status_code == 200, response.text
|
|
assert response.json() == {"item": {"value": "first", "price": 100}}
|
|
|
|
|
|
@needs_pydanticv2
|
|
def test_post_other_item(client: TestClient) -> None:
|
|
response = client.post("/items/", json={"value": "other", "price": 100.5})
|
|
assert response.status_code == 200, response.text
|
|
assert response.json() == {"item": {"value": "other", "price": 100.5}}
|
|
|