Browse Source

🔇 Filter warnings for tests with Pydantic v1

pull/14583/head
Sebastián Ramírez 7 months ago
parent
commit
b32b4bfefb
  1. 187
      tests/test_compat_params_v1.py
  2. 48
      tests/test_pydantic_v1_v2_01.py
  3. 75
      tests/test_pydantic_v1_v2_list.py
  4. 315
      tests/test_pydantic_v1_v2_mixed.py
  5. 217
      tests/test_pydantic_v1_v2_multifile/main.py
  6. 123
      tests/test_pydantic_v1_v2_noneable.py

187
tests/test_compat_params_v1.py

@ -1,4 +1,5 @@
import sys
import warnings
from typing import Optional
import pytest
@ -33,94 +34,90 @@ class Item(BaseModel):
app = FastAPI()
@app.get("/items/{item_id}")
def get_item_with_path(
item_id: Annotated[int, Path(title="The ID of the item", ge=1, le=1000)],
):
return {"item_id": item_id}
@app.get("/items/")
def get_items_with_query(
q: Annotated[
Optional[str], Query(min_length=3, max_length=50, pattern="^[a-zA-Z0-9 ]+$")
] = None,
skip: Annotated[int, Query(ge=0)] = 0,
limit: Annotated[int, Query(ge=1, le=100, examples=[5])] = 10,
):
return {"q": q, "skip": skip, "limit": limit}
@app.get("/users/")
def get_user_with_header(
x_custom: Annotated[Optional[str], Header()] = None,
x_token: Annotated[Optional[str], Header(convert_underscores=True)] = None,
):
return {"x_custom": x_custom, "x_token": x_token}
@app.get("/cookies/")
def get_cookies(
session_id: Annotated[Optional[str], Cookie()] = None,
tracking_id: Annotated[Optional[str], Cookie(min_length=10)] = None,
):
return {"session_id": session_id, "tracking_id": tracking_id}
@app.post("/items/")
def create_item(
item: Annotated[
Item,
Body(examples=[{"name": "Foo", "price": 35.4, "description": "The Foo item"}]),
],
):
return {"item": item}
@app.post("/items-embed/")
def create_item_embed(
item: Annotated[Item, Body(embed=True)],
):
return {"item": item}
@app.put("/items/{item_id}")
def update_item(
item_id: Annotated[int, Path(ge=1)],
item: Annotated[Item, Body()],
importance: Annotated[int, Body(gt=0, le=10)],
):
return {"item": item, "importance": importance}
@app.post("/form-data/")
def submit_form(
username: Annotated[str, Form(min_length=3, max_length=50)],
password: Annotated[str, Form(min_length=8)],
email: Annotated[Optional[str], Form()] = None,
):
return {"username": username, "password": password, "email": email}
@app.post("/upload/")
def upload_file(
file: Annotated[bytes, File()],
description: Annotated[Optional[str], Form()] = None,
):
return {"file_size": len(file), "description": description}
@app.post("/upload-multiple/")
def upload_multiple_files(
files: Annotated[list[bytes], File()],
note: Annotated[str, Form()] = "",
):
return {
"file_count": len(files),
"total_size": sum(len(f) for f in files),
"note": note,
}
with warnings.catch_warnings(record=True):
warnings.simplefilter("always")
@app.get("/items/{item_id}")
def get_item_with_path(
item_id: Annotated[int, Path(title="The ID of the item", ge=1, le=1000)],
):
return {"item_id": item_id}
@app.get("/items/")
def get_items_with_query(
q: Annotated[
Optional[str],
Query(min_length=3, max_length=50, pattern="^[a-zA-Z0-9 ]+$"),
] = None,
skip: Annotated[int, Query(ge=0)] = 0,
limit: Annotated[int, Query(ge=1, le=100, examples=[5])] = 10,
):
return {"q": q, "skip": skip, "limit": limit}
@app.get("/users/")
def get_user_with_header(
x_custom: Annotated[Optional[str], Header()] = None,
x_token: Annotated[Optional[str], Header(convert_underscores=True)] = None,
):
return {"x_custom": x_custom, "x_token": x_token}
@app.get("/cookies/")
def get_cookies(
session_id: Annotated[Optional[str], Cookie()] = None,
tracking_id: Annotated[Optional[str], Cookie(min_length=10)] = None,
):
return {"session_id": session_id, "tracking_id": tracking_id}
@app.post("/items/")
def create_item(
item: Annotated[
Item,
Body(
examples=[{"name": "Foo", "price": 35.4, "description": "The Foo item"}]
),
],
):
return {"item": item}
@app.post("/items-embed/")
def create_item_embed(
item: Annotated[Item, Body(embed=True)],
):
return {"item": item}
@app.put("/items/{item_id}")
def update_item(
item_id: Annotated[int, Path(ge=1)],
item: Annotated[Item, Body()],
importance: Annotated[int, Body(gt=0, le=10)],
):
return {"item": item, "importance": importance}
@app.post("/form-data/")
def submit_form(
username: Annotated[str, Form(min_length=3, max_length=50)],
password: Annotated[str, Form(min_length=8)],
email: Annotated[Optional[str], Form()] = None,
):
return {"username": username, "password": password, "email": email}
@app.post("/upload/")
def upload_file(
file: Annotated[bytes, File()],
description: Annotated[Optional[str], Form()] = None,
):
return {"file_size": len(file), "description": description}
@app.post("/upload-multiple/")
def upload_multiple_files(
files: Annotated[list[bytes], File()],
note: Annotated[str, Form()] = "",
):
return {
"file_count": len(files),
"total_size": sum(len(f) for f in files),
"note": note,
}
client = TestClient(app)
@ -211,10 +208,10 @@ def test_header_params_none():
# Cookie parameter tests
def test_cookie_params():
with TestClient(app) as client:
client.cookies.set("session_id", "abc123")
client.cookies.set("tracking_id", "1234567890abcdef")
response = client.get("/cookies/")
with TestClient(app) as test_client:
test_client.cookies.set("session_id", "abc123")
test_client.cookies.set("tracking_id", "1234567890abcdef")
response = test_client.get("/cookies/")
assert response.status_code == 200
assert response.json() == {
"session_id": "abc123",
@ -223,9 +220,9 @@ def test_cookie_params():
def test_cookie_tracking_id_too_short():
with TestClient(app) as client:
client.cookies.set("tracking_id", "short")
response = client.get("/cookies/")
with TestClient(app) as test_client:
test_client.cookies.set("tracking_id", "short")
response = test_client.get("/cookies/")
assert response.status_code == 422
assert response.json() == snapshot(
{

48
tests/test_pydantic_v1_v2_01.py

@ -1,4 +1,5 @@
import sys
import warnings
from typing import Any, Union
from tests.utils import skip_module_if_py_gte_314
@ -26,30 +27,29 @@ class Item(BaseModel):
app = FastAPI()
@app.post("/simple-model")
def handle_simple_model(data: SubItem) -> SubItem:
return data
@app.post("/simple-model-filter", response_model=SubItem)
def handle_simple_model_filter(data: SubItem) -> Any:
extended_data = data.dict()
extended_data.update({"secret_price": 42})
return extended_data
@app.post("/item")
def handle_item(data: Item) -> Item:
return data
@app.post("/item-filter", response_model=Item)
def handle_item_filter(data: Item) -> Any:
extended_data = data.dict()
extended_data.update({"secret_data": "classified", "internal_id": 12345})
extended_data["sub"].update({"internal_id": 67890})
return extended_data
with warnings.catch_warnings(record=True):
warnings.simplefilter("always")
@app.post("/simple-model")
def handle_simple_model(data: SubItem) -> SubItem:
return data
@app.post("/simple-model-filter", response_model=SubItem)
def handle_simple_model_filter(data: SubItem) -> Any:
extended_data = data.dict()
extended_data.update({"secret_price": 42})
return extended_data
@app.post("/item")
def handle_item(data: Item) -> Item:
return data
@app.post("/item-filter", response_model=Item)
def handle_item_filter(data: Item) -> Any:
extended_data = data.dict()
extended_data.update({"secret_data": "classified", "internal_id": 12345})
extended_data["sub"].update({"internal_id": 67890})
return extended_data
client = TestClient(app)

75
tests/test_pydantic_v1_v2_list.py

@ -1,4 +1,5 @@
import sys
import warnings
from typing import Any, Union
from tests.utils import skip_module_if_py_gte_314
@ -27,49 +28,47 @@ class Item(BaseModel):
app = FastAPI()
@app.post("/item")
def handle_item(data: Item) -> list[Item]:
return [data, data]
with warnings.catch_warnings(record=True):
warnings.simplefilter("always")
@app.post("/item")
def handle_item(data: Item) -> list[Item]:
return [data, data]
@app.post("/item-filter", response_model=list[Item])
def handle_item_filter(data: Item) -> Any:
extended_data = data.dict()
extended_data.update({"secret_data": "classified", "internal_id": 12345})
extended_data["sub"].update({"internal_id": 67890})
return [extended_data, extended_data]
@app.post("/item-list")
def handle_item_list(data: list[Item]) -> Item:
if data:
return data[0]
return Item(title="", size=0, sub=SubItem(name=""))
@app.post("/item-list-filter", response_model=Item)
def handle_item_list_filter(data: list[Item]) -> Any:
if data:
extended_data = data[0].dict()
extended_data.update({"secret_data": "classified", "internal_id": 12345})
extended_data["sub"].update({"internal_id": 67890})
return extended_data
return Item(title="", size=0, sub=SubItem(name=""))
@app.post("/item-list-to-list")
def handle_item_list_to_list(data: list[Item]) -> list[Item]:
return data
@app.post("/item-list-to-list-filter", response_model=list[Item])
def handle_item_list_to_list_filter(data: list[Item]) -> Any:
if data:
extended_data = data[0].dict()
@app.post("/item-filter", response_model=list[Item])
def handle_item_filter(data: Item) -> Any:
extended_data = data.dict()
extended_data.update({"secret_data": "classified", "internal_id": 12345})
extended_data["sub"].update({"internal_id": 67890})
return [extended_data, extended_data]
return []
@app.post("/item-list")
def handle_item_list(data: list[Item]) -> Item:
if data:
return data[0]
return Item(title="", size=0, sub=SubItem(name=""))
@app.post("/item-list-filter", response_model=Item)
def handle_item_list_filter(data: list[Item]) -> Any:
if data:
extended_data = data[0].dict()
extended_data.update({"secret_data": "classified", "internal_id": 12345})
extended_data["sub"].update({"internal_id": 67890})
return extended_data
return Item(title="", size=0, sub=SubItem(name=""))
@app.post("/item-list-to-list")
def handle_item_list_to_list(data: list[Item]) -> list[Item]:
return data
@app.post("/item-list-to-list-filter", response_model=list[Item])
def handle_item_list_to_list_filter(data: list[Item]) -> Any:
if data:
extended_data = data[0].dict()
extended_data.update({"secret_data": "classified", "internal_id": 12345})
extended_data["sub"].update({"internal_id": 67890})
return [extended_data, extended_data]
return []
client = TestClient(app)

315
tests/test_pydantic_v1_v2_mixed.py

@ -1,4 +1,5 @@
import sys
import warnings
from typing import Any, Union
from tests.utils import skip_module_if_py_gte_314
@ -39,179 +40,181 @@ class NewItem(NewBaseModel):
app = FastAPI()
with warnings.catch_warnings(record=True):
warnings.simplefilter("always")
@app.post("/v1-to-v2/item")
def handle_v1_item_to_v2(data: Item) -> NewItem:
return NewItem(
new_title=data.title,
new_size=data.size,
new_description=data.description,
new_sub=NewSubItem(new_sub_name=data.sub.name),
new_multi=[NewSubItem(new_sub_name=s.name) for s in data.multi],
)
@app.post("/v1-to-v2/item-filter", response_model=NewItem)
def handle_v1_item_to_v2_filter(data: Item) -> Any:
result = {
"new_title": data.title,
"new_size": data.size,
"new_description": data.description,
"new_sub": {"new_sub_name": data.sub.name, "new_sub_secret": "sub_hidden"},
"new_multi": [
{"new_sub_name": s.name, "new_sub_secret": "sub_hidden"} for s in data.multi
],
"secret": "hidden_v1_to_v2",
}
return result
@app.post("/v2-to-v1/item")
def handle_v2_item_to_v1(data: NewItem) -> Item:
return Item(
title=data.new_title,
size=data.new_size,
description=data.new_description,
sub=SubItem(name=data.new_sub.new_sub_name),
multi=[SubItem(name=s.new_sub_name) for s in data.new_multi],
)
@app.post("/v2-to-v1/item-filter", response_model=Item)
def handle_v2_item_to_v1_filter(data: NewItem) -> Any:
result = {
"title": data.new_title,
"size": data.new_size,
"description": data.new_description,
"sub": {"name": data.new_sub.new_sub_name, "sub_secret": "sub_hidden"},
"multi": [
{"name": s.new_sub_name, "sub_secret": "sub_hidden"} for s in data.new_multi
],
"secret": "hidden_v2_to_v1",
}
return result
@app.post("/v1-to-v2/item")
def handle_v1_item_to_v2(data: Item) -> NewItem:
return NewItem(
new_title=data.title,
new_size=data.size,
new_description=data.description,
new_sub=NewSubItem(new_sub_name=data.sub.name),
new_multi=[NewSubItem(new_sub_name=s.name) for s in data.multi],
)
@app.post("/v1-to-v2/item-to-list")
def handle_v1_item_to_v2_list(data: Item) -> list[NewItem]:
converted = NewItem(
new_title=data.title,
new_size=data.size,
new_description=data.description,
new_sub=NewSubItem(new_sub_name=data.sub.name),
new_multi=[NewSubItem(new_sub_name=s.name) for s in data.multi],
)
return [converted, converted]
@app.post("/v1-to-v2/item-filter", response_model=NewItem)
def handle_v1_item_to_v2_filter(data: Item) -> Any:
result = {
"new_title": data.title,
"new_size": data.size,
"new_description": data.description,
"new_sub": {
"new_sub_name": data.sub.name,
"new_sub_secret": "sub_hidden",
},
"new_multi": [
{"new_sub_name": s.name, "new_sub_secret": "sub_hidden"}
for s in data.multi
],
"secret": "hidden_v1_to_v2",
}
return result
@app.post("/v2-to-v1/item")
def handle_v2_item_to_v1(data: NewItem) -> Item:
return Item(
title=data.new_title,
size=data.new_size,
description=data.new_description,
sub=SubItem(name=data.new_sub.new_sub_name),
multi=[SubItem(name=s.new_sub_name) for s in data.new_multi],
)
@app.post("/v1-to-v2/list-to-list")
def handle_v1_list_to_v2_list(data: list[Item]) -> list[NewItem]:
result = []
for item in data:
result.append(
NewItem(
@app.post("/v2-to-v1/item-filter", response_model=Item)
def handle_v2_item_to_v1_filter(data: NewItem) -> Any:
result = {
"title": data.new_title,
"size": data.new_size,
"description": data.new_description,
"sub": {"name": data.new_sub.new_sub_name, "sub_secret": "sub_hidden"},
"multi": [
{"name": s.new_sub_name, "sub_secret": "sub_hidden"}
for s in data.new_multi
],
"secret": "hidden_v2_to_v1",
}
return result
@app.post("/v1-to-v2/item-to-list")
def handle_v1_item_to_v2_list(data: Item) -> list[NewItem]:
converted = NewItem(
new_title=data.title,
new_size=data.size,
new_description=data.description,
new_sub=NewSubItem(new_sub_name=data.sub.name),
new_multi=[NewSubItem(new_sub_name=s.name) for s in data.multi],
)
return [converted, converted]
@app.post("/v1-to-v2/list-to-list")
def handle_v1_list_to_v2_list(data: list[Item]) -> list[NewItem]:
result = []
for item in data:
result.append(
NewItem(
new_title=item.title,
new_size=item.size,
new_description=item.description,
new_sub=NewSubItem(new_sub_name=item.sub.name),
new_multi=[NewSubItem(new_sub_name=s.name) for s in item.multi],
)
)
return result
@app.post("/v1-to-v2/list-to-list-filter", response_model=list[NewItem])
def handle_v1_list_to_v2_list_filter(data: list[Item]) -> Any:
result = []
for item in data:
converted = {
"new_title": item.title,
"new_size": item.size,
"new_description": item.description,
"new_sub": {
"new_sub_name": item.sub.name,
"new_sub_secret": "sub_hidden",
},
"new_multi": [
{"new_sub_name": s.name, "new_sub_secret": "sub_hidden"}
for s in item.multi
],
"secret": "hidden_v2_to_v1",
}
result.append(converted)
return result
@app.post("/v1-to-v2/list-to-item")
def handle_v1_list_to_v2_item(data: list[Item]) -> NewItem:
if data:
item = data[0]
return NewItem(
new_title=item.title,
new_size=item.size,
new_description=item.description,
new_sub=NewSubItem(new_sub_name=item.sub.name),
new_multi=[NewSubItem(new_sub_name=s.name) for s in item.multi],
)
return NewItem(new_title="", new_size=0, new_sub=NewSubItem(new_sub_name=""))
@app.post("/v2-to-v1/item-to-list")
def handle_v2_item_to_v1_list(data: NewItem) -> list[Item]:
converted = Item(
title=data.new_title,
size=data.new_size,
description=data.new_description,
sub=SubItem(name=data.new_sub.new_sub_name),
multi=[SubItem(name=s.new_sub_name) for s in data.new_multi],
)
return result
@app.post("/v1-to-v2/list-to-list-filter", response_model=list[NewItem])
def handle_v1_list_to_v2_list_filter(data: list[Item]) -> Any:
result = []
for item in data:
converted = {
"new_title": item.title,
"new_size": item.size,
"new_description": item.description,
"new_sub": {"new_sub_name": item.sub.name, "new_sub_secret": "sub_hidden"},
"new_multi": [
{"new_sub_name": s.name, "new_sub_secret": "sub_hidden"}
for s in item.multi
],
"secret": "hidden_v2_to_v1",
}
result.append(converted)
return result
@app.post("/v1-to-v2/list-to-item")
def handle_v1_list_to_v2_item(data: list[Item]) -> NewItem:
if data:
item = data[0]
return NewItem(
new_title=item.title,
new_size=item.size,
new_description=item.description,
new_sub=NewSubItem(new_sub_name=item.sub.name),
new_multi=[NewSubItem(new_sub_name=s.name) for s in item.multi],
)
return NewItem(new_title="", new_size=0, new_sub=NewSubItem(new_sub_name=""))
@app.post("/v2-to-v1/item-to-list")
def handle_v2_item_to_v1_list(data: NewItem) -> list[Item]:
converted = Item(
title=data.new_title,
size=data.new_size,
description=data.new_description,
sub=SubItem(name=data.new_sub.new_sub_name),
multi=[SubItem(name=s.new_sub_name) for s in data.new_multi],
)
return [converted, converted]
@app.post("/v2-to-v1/list-to-list")
def handle_v2_list_to_v1_list(data: list[NewItem]) -> list[Item]:
result = []
for item in data:
result.append(
Item(
return [converted, converted]
@app.post("/v2-to-v1/list-to-list")
def handle_v2_list_to_v1_list(data: list[NewItem]) -> list[Item]:
result = []
for item in data:
result.append(
Item(
title=item.new_title,
size=item.new_size,
description=item.new_description,
sub=SubItem(name=item.new_sub.new_sub_name),
multi=[SubItem(name=s.new_sub_name) for s in item.new_multi],
)
)
return result
@app.post("/v2-to-v1/list-to-list-filter", response_model=list[Item])
def handle_v2_list_to_v1_list_filter(data: list[NewItem]) -> Any:
result = []
for item in data:
converted = {
"title": item.new_title,
"size": item.new_size,
"description": item.new_description,
"sub": {
"name": item.new_sub.new_sub_name,
"sub_secret": "sub_hidden",
},
"multi": [
{"name": s.new_sub_name, "sub_secret": "sub_hidden"}
for s in item.new_multi
],
"secret": "hidden_v2_to_v1",
}
result.append(converted)
return result
@app.post("/v2-to-v1/list-to-item")
def handle_v2_list_to_v1_item(data: list[NewItem]) -> Item:
if data:
item = data[0]
return Item(
title=item.new_title,
size=item.new_size,
description=item.new_description,
sub=SubItem(name=item.new_sub.new_sub_name),
multi=[SubItem(name=s.new_sub_name) for s in item.new_multi],
)
)
return result
@app.post("/v2-to-v1/list-to-list-filter", response_model=list[Item])
def handle_v2_list_to_v1_list_filter(data: list[NewItem]) -> Any:
result = []
for item in data:
converted = {
"title": item.new_title,
"size": item.new_size,
"description": item.new_description,
"sub": {"name": item.new_sub.new_sub_name, "sub_secret": "sub_hidden"},
"multi": [
{"name": s.new_sub_name, "sub_secret": "sub_hidden"}
for s in item.new_multi
],
"secret": "hidden_v2_to_v1",
}
result.append(converted)
return result
@app.post("/v2-to-v1/list-to-item")
def handle_v2_list_to_v1_item(data: list[NewItem]) -> Item:
if data:
item = data[0]
return Item(
title=item.new_title,
size=item.new_size,
description=item.new_description,
sub=SubItem(name=item.new_sub.new_sub_name),
multi=[SubItem(name=s.new_sub_name) for s in item.new_multi],
)
return Item(title="", size=0, sub=SubItem(name=""))
return Item(title="", size=0, sub=SubItem(name=""))
client = TestClient(app)

217
tests/test_pydantic_v1_v2_multifile/main.py

@ -1,140 +1,137 @@
import warnings
from fastapi import FastAPI
from . import modelsv1, modelsv2, modelsv2b
app = FastAPI()
with warnings.catch_warnings(record=True):
warnings.simplefilter("always")
@app.post("/v1-to-v2/item")
def handle_v1_item_to_v2(data: modelsv1.Item) -> modelsv2.Item:
return modelsv2.Item(
new_title=data.title,
new_size=data.size,
new_description=data.description,
new_sub=modelsv2.SubItem(new_sub_name=data.sub.name),
new_multi=[modelsv2.SubItem(new_sub_name=s.name) for s in data.multi],
)
@app.post("/v2-to-v1/item")
def handle_v2_item_to_v1(data: modelsv2.Item) -> modelsv1.Item:
return modelsv1.Item(
title=data.new_title,
size=data.new_size,
description=data.new_description,
sub=modelsv1.SubItem(name=data.new_sub.new_sub_name),
multi=[modelsv1.SubItem(name=s.new_sub_name) for s in data.new_multi],
)
@app.post("/v1-to-v2/item")
def handle_v1_item_to_v2(data: modelsv1.Item) -> modelsv2.Item:
return modelsv2.Item(
new_title=data.title,
new_size=data.size,
new_description=data.description,
new_sub=modelsv2.SubItem(new_sub_name=data.sub.name),
new_multi=[modelsv2.SubItem(new_sub_name=s.name) for s in data.multi],
)
@app.post("/v1-to-v2/item-to-list")
def handle_v1_item_to_v2_list(data: modelsv1.Item) -> list[modelsv2.Item]:
converted = modelsv2.Item(
new_title=data.title,
new_size=data.size,
new_description=data.description,
new_sub=modelsv2.SubItem(new_sub_name=data.sub.name),
new_multi=[modelsv2.SubItem(new_sub_name=s.name) for s in data.multi],
)
return [converted, converted]
@app.post("/v2-to-v1/item")
def handle_v2_item_to_v1(data: modelsv2.Item) -> modelsv1.Item:
return modelsv1.Item(
title=data.new_title,
size=data.new_size,
description=data.new_description,
sub=modelsv1.SubItem(name=data.new_sub.new_sub_name),
multi=[modelsv1.SubItem(name=s.new_sub_name) for s in data.new_multi],
)
@app.post("/v1-to-v2/item-to-list")
def handle_v1_item_to_v2_list(data: modelsv1.Item) -> list[modelsv2.Item]:
converted = modelsv2.Item(
new_title=data.title,
new_size=data.size,
new_description=data.description,
new_sub=modelsv2.SubItem(new_sub_name=data.sub.name),
new_multi=[modelsv2.SubItem(new_sub_name=s.name) for s in data.multi],
)
return [converted, converted]
@app.post("/v1-to-v2/list-to-list")
def handle_v1_list_to_v2_list(data: list[modelsv1.Item]) -> list[modelsv2.Item]:
result = []
for item in data:
result.append(
modelsv2.Item(
new_title=item.title,
new_size=item.size,
new_description=item.description,
new_sub=modelsv2.SubItem(new_sub_name=item.sub.name),
new_multi=[
modelsv2.SubItem(new_sub_name=s.name) for s in item.multi
],
)
)
return result
@app.post("/v1-to-v2/list-to-list")
def handle_v1_list_to_v2_list(data: list[modelsv1.Item]) -> list[modelsv2.Item]:
result = []
for item in data:
result.append(
modelsv2.Item(
@app.post("/v1-to-v2/list-to-item")
def handle_v1_list_to_v2_item(data: list[modelsv1.Item]) -> modelsv2.Item:
if data:
item = data[0]
return modelsv2.Item(
new_title=item.title,
new_size=item.size,
new_description=item.description,
new_sub=modelsv2.SubItem(new_sub_name=item.sub.name),
new_multi=[modelsv2.SubItem(new_sub_name=s.name) for s in item.multi],
)
)
return result
@app.post("/v1-to-v2/list-to-item")
def handle_v1_list_to_v2_item(data: list[modelsv1.Item]) -> modelsv2.Item:
if data:
item = data[0]
return modelsv2.Item(
new_title=item.title,
new_size=item.size,
new_description=item.description,
new_sub=modelsv2.SubItem(new_sub_name=item.sub.name),
new_multi=[modelsv2.SubItem(new_sub_name=s.name) for s in item.multi],
new_title="", new_size=0, new_sub=modelsv2.SubItem(new_sub_name="")
)
return modelsv2.Item(
new_title="", new_size=0, new_sub=modelsv2.SubItem(new_sub_name="")
)
@app.post("/v2-to-v1/item-to-list")
def handle_v2_item_to_v1_list(data: modelsv2.Item) -> list[modelsv1.Item]:
converted = modelsv1.Item(
title=data.new_title,
size=data.new_size,
description=data.new_description,
sub=modelsv1.SubItem(name=data.new_sub.new_sub_name),
multi=[modelsv1.SubItem(name=s.new_sub_name) for s in data.new_multi],
)
return [converted, converted]
@app.post("/v2-to-v1/item-to-list")
def handle_v2_item_to_v1_list(data: modelsv2.Item) -> list[modelsv1.Item]:
converted = modelsv1.Item(
title=data.new_title,
size=data.new_size,
description=data.new_description,
sub=modelsv1.SubItem(name=data.new_sub.new_sub_name),
multi=[modelsv1.SubItem(name=s.new_sub_name) for s in data.new_multi],
)
return [converted, converted]
@app.post("/v2-to-v1/list-to-list")
def handle_v2_list_to_v1_list(data: list[modelsv2.Item]) -> list[modelsv1.Item]:
result = []
for item in data:
result.append(
modelsv1.Item(
title=item.new_title,
size=item.new_size,
description=item.new_description,
sub=modelsv1.SubItem(name=item.new_sub.new_sub_name),
multi=[
modelsv1.SubItem(name=s.new_sub_name) for s in item.new_multi
],
)
)
return result
@app.post("/v2-to-v1/list-to-list")
def handle_v2_list_to_v1_list(data: list[modelsv2.Item]) -> list[modelsv1.Item]:
result = []
for item in data:
result.append(
modelsv1.Item(
@app.post("/v2-to-v1/list-to-item")
def handle_v2_list_to_v1_item(data: list[modelsv2.Item]) -> modelsv1.Item:
if data:
item = data[0]
return modelsv1.Item(
title=item.new_title,
size=item.new_size,
description=item.new_description,
sub=modelsv1.SubItem(name=item.new_sub.new_sub_name),
multi=[modelsv1.SubItem(name=s.new_sub_name) for s in item.new_multi],
)
)
return result
return modelsv1.Item(title="", size=0, sub=modelsv1.SubItem(name=""))
@app.post("/v2-to-v1/list-to-item")
def handle_v2_list_to_v1_item(data: list[modelsv2.Item]) -> modelsv1.Item:
if data:
item = data[0]
@app.post("/v2-to-v1/same-name")
def handle_v2_same_name_to_v1(
item1: modelsv2.Item, item2: modelsv2b.Item
) -> modelsv1.Item:
return modelsv1.Item(
title=item.new_title,
size=item.new_size,
description=item.new_description,
sub=modelsv1.SubItem(name=item.new_sub.new_sub_name),
multi=[modelsv1.SubItem(name=s.new_sub_name) for s in item.new_multi],
title=item1.new_title,
size=item2.dup_size,
description=item1.new_description,
sub=modelsv1.SubItem(name=item1.new_sub.new_sub_name),
multi=[modelsv1.SubItem(name=s.dup_sub_name) for s in item2.dup_multi],
)
return modelsv1.Item(title="", size=0, sub=modelsv1.SubItem(name=""))
@app.post("/v2-to-v1/same-name")
def handle_v2_same_name_to_v1(
item1: modelsv2.Item, item2: modelsv2b.Item
) -> modelsv1.Item:
return modelsv1.Item(
title=item1.new_title,
size=item2.dup_size,
description=item1.new_description,
sub=modelsv1.SubItem(name=item1.new_sub.new_sub_name),
multi=[modelsv1.SubItem(name=s.dup_sub_name) for s in item2.dup_multi],
)
@app.post("/v2-to-v1/list-of-items-to-list-of-items")
def handle_v2_items_in_list_to_v1_item_in_list(
data1: list[modelsv2.ItemInList], data2: list[modelsv2b.ItemInList]
) -> list[modelsv1.ItemInList]:
result = []
item1 = data1[0]
item2 = data2[0]
result = [
modelsv1.ItemInList(name1=item1.name2),
modelsv1.ItemInList(name1=item2.dup_name2),
]
return result
@app.post("/v2-to-v1/list-of-items-to-list-of-items")
def handle_v2_items_in_list_to_v1_item_in_list(
data1: list[modelsv2.ItemInList], data2: list[modelsv2b.ItemInList]
) -> list[modelsv1.ItemInList]:
item1 = data1[0]
item2 = data2[0]
return [
modelsv1.ItemInList(name1=item1.name2),
modelsv1.ItemInList(name1=item2.dup_name2),
]

123
tests/test_pydantic_v1_v2_noneable.py

@ -1,4 +1,5 @@
import sys
import warnings
from typing import Any, Union
from tests.utils import skip_module_if_py_gte_314
@ -39,65 +40,69 @@ class NewItem(NewBaseModel):
app = FastAPI()
@app.post("/v1-to-v2/")
def handle_v1_item_to_v2(data: Item) -> Union[NewItem, None]:
if data.size < 0:
return None
return NewItem(
new_title=data.title,
new_size=data.size,
new_description=data.description,
new_sub=NewSubItem(new_sub_name=data.sub.name),
new_multi=[NewSubItem(new_sub_name=s.name) for s in data.multi],
)
@app.post("/v1-to-v2/item-filter", response_model=Union[NewItem, None])
def handle_v1_item_to_v2_filter(data: Item) -> Any:
if data.size < 0:
return None
result = {
"new_title": data.title,
"new_size": data.size,
"new_description": data.description,
"new_sub": {"new_sub_name": data.sub.name, "new_sub_secret": "sub_hidden"},
"new_multi": [
{"new_sub_name": s.name, "new_sub_secret": "sub_hidden"} for s in data.multi
],
"secret": "hidden_v1_to_v2",
}
return result
@app.post("/v2-to-v1/item")
def handle_v2_item_to_v1(data: NewItem) -> Union[Item, None]:
if data.new_size < 0:
return None
return Item(
title=data.new_title,
size=data.new_size,
description=data.new_description,
sub=SubItem(name=data.new_sub.new_sub_name),
multi=[SubItem(name=s.new_sub_name) for s in data.new_multi],
)
@app.post("/v2-to-v1/item-filter", response_model=Union[Item, None])
def handle_v2_item_to_v1_filter(data: NewItem) -> Any:
if data.new_size < 0:
return None
result = {
"title": data.new_title,
"size": data.new_size,
"description": data.new_description,
"sub": {"name": data.new_sub.new_sub_name, "sub_secret": "sub_hidden"},
"multi": [
{"name": s.new_sub_name, "sub_secret": "sub_hidden"} for s in data.new_multi
],
"secret": "hidden_v2_to_v1",
}
return result
with warnings.catch_warnings(record=True):
warnings.simplefilter("always")
@app.post("/v1-to-v2/")
def handle_v1_item_to_v2(data: Item) -> Union[NewItem, None]:
if data.size < 0:
return None
return NewItem(
new_title=data.title,
new_size=data.size,
new_description=data.description,
new_sub=NewSubItem(new_sub_name=data.sub.name),
new_multi=[NewSubItem(new_sub_name=s.name) for s in data.multi],
)
@app.post("/v1-to-v2/item-filter", response_model=Union[NewItem, None])
def handle_v1_item_to_v2_filter(data: Item) -> Any:
if data.size < 0:
return None
result = {
"new_title": data.title,
"new_size": data.size,
"new_description": data.description,
"new_sub": {
"new_sub_name": data.sub.name,
"new_sub_secret": "sub_hidden",
},
"new_multi": [
{"new_sub_name": s.name, "new_sub_secret": "sub_hidden"}
for s in data.multi
],
"secret": "hidden_v1_to_v2",
}
return result
@app.post("/v2-to-v1/item")
def handle_v2_item_to_v1(data: NewItem) -> Union[Item, None]:
if data.new_size < 0:
return None
return Item(
title=data.new_title,
size=data.new_size,
description=data.new_description,
sub=SubItem(name=data.new_sub.new_sub_name),
multi=[SubItem(name=s.new_sub_name) for s in data.new_multi],
)
@app.post("/v2-to-v1/item-filter", response_model=Union[Item, None])
def handle_v2_item_to_v1_filter(data: NewItem) -> Any:
if data.new_size < 0:
return None
result = {
"title": data.new_title,
"size": data.new_size,
"description": data.new_description,
"sub": {"name": data.new_sub.new_sub_name, "sub_secret": "sub_hidden"},
"multi": [
{"name": s.new_sub_name, "sub_secret": "sub_hidden"}
for s in data.new_multi
],
"secret": "hidden_v2_to_v1",
}
return result
client = TestClient(app)

Loading…
Cancel
Save