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

48
tests/test_pydantic_v1_v2_01.py

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

75
tests/test_pydantic_v1_v2_list.py

@ -1,4 +1,5 @@
import sys import sys
import warnings
from typing import Any, Union from typing import Any, Union
from tests.utils import skip_module_if_py_gte_314 from tests.utils import skip_module_if_py_gte_314
@ -27,49 +28,47 @@ class Item(BaseModel):
app = FastAPI() app = FastAPI()
@app.post("/item") with warnings.catch_warnings(record=True):
def handle_item(data: Item) -> list[Item]: warnings.simplefilter("always")
return [data, data]
@app.post("/item")
def handle_item(data: Item) -> list[Item]:
return [data, data]
@app.post("/item-filter", response_model=list[Item]) @app.post("/item-filter", response_model=list[Item])
def handle_item_filter(data: Item) -> Any: def handle_item_filter(data: Item) -> Any:
extended_data = data.dict() 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()
extended_data.update({"secret_data": "classified", "internal_id": 12345}) extended_data.update({"secret_data": "classified", "internal_id": 12345})
extended_data["sub"].update({"internal_id": 67890}) extended_data["sub"].update({"internal_id": 67890})
return [extended_data, extended_data] 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) client = TestClient(app)

315
tests/test_pydantic_v1_v2_mixed.py

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

217
tests/test_pydantic_v1_v2_multifile/main.py

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

123
tests/test_pydantic_v1_v2_noneable.py

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

Loading…
Cancel
Save