Browse Source

🔇 Filter warnings for tests with Pydantic v1

pull/14583/head
Sebastián Ramírez 7 months ago
parent
commit
b32b4bfefb
  1. 93
      tests/test_compat_params_v1.py
  2. 22
      tests/test_pydantic_v1_v2_01.py
  3. 33
      tests/test_pydantic_v1_v2_list.py
  4. 83
      tests/test_pydantic_v1_v2_mixed.py
  5. 69
      tests/test_pydantic_v1_v2_multifile/main.py
  6. 33
      tests/test_pydantic_v1_v2_noneable.py

93
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,89 +34,85 @@ class Item(BaseModel):
app = FastAPI() app = FastAPI()
with warnings.catch_warnings(record=True):
warnings.simplefilter("always")
@app.get("/items/{item_id}") @app.get("/items/{item_id}")
def get_item_with_path( def get_item_with_path(
item_id: Annotated[int, Path(title="The ID of the item", ge=1, le=1000)], item_id: Annotated[int, Path(title="The ID of the item", ge=1, le=1000)],
): ):
return {"item_id": item_id} return {"item_id": item_id}
@app.get("/items/")
@app.get("/items/") def get_items_with_query(
def get_items_with_query(
q: Annotated[ q: Annotated[
Optional[str], Query(min_length=3, max_length=50, pattern="^[a-zA-Z0-9 ]+$") Optional[str],
Query(min_length=3, max_length=50, pattern="^[a-zA-Z0-9 ]+$"),
] = None, ] = None,
skip: Annotated[int, Query(ge=0)] = 0, skip: Annotated[int, Query(ge=0)] = 0,
limit: Annotated[int, Query(ge=1, le=100, examples=[5])] = 10, limit: Annotated[int, Query(ge=1, le=100, examples=[5])] = 10,
): ):
return {"q": q, "skip": skip, "limit": limit} return {"q": q, "skip": skip, "limit": limit}
@app.get("/users/")
@app.get("/users/") def get_user_with_header(
def get_user_with_header(
x_custom: Annotated[Optional[str], Header()] = None, x_custom: Annotated[Optional[str], Header()] = None,
x_token: Annotated[Optional[str], Header(convert_underscores=True)] = 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(examples=[{"name": "Foo", "price": 35.4, "description": "The Foo item"}]), Body(
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/")
@app.post("/form-data/") def submit_form(
def submit_form(
username: Annotated[str, Form(min_length=3, max_length=50)], username: Annotated[str, Form(min_length=3, max_length=50)],
password: Annotated[str, Form(min_length=8)], password: Annotated[str, Form(min_length=8)],
email: Annotated[Optional[str], Form()] = None, email: Annotated[Optional[str], Form()] = None,
): ):
return {"username": username, "password": password, "email": email} return {"username": username, "password": password, "email": email}
@app.post("/upload/")
@app.post("/upload/") def upload_file(
def upload_file(
file: Annotated[bytes, File()], file: Annotated[bytes, File()],
description: Annotated[Optional[str], Form()] = None, description: Annotated[Optional[str], Form()] = None,
): ):
return {"file_size": len(file), "description": description} return {"file_size": len(file), "description": description}
@app.post("/upload-multiple/")
@app.post("/upload-multiple/") def upload_multiple_files(
def upload_multiple_files(
files: Annotated[list[bytes], File()], files: Annotated[list[bytes], File()],
note: Annotated[str, Form()] = "", note: Annotated[str, Form()] = "",
): ):
return { return {
"file_count": len(files), "file_count": len(files),
"total_size": sum(len(f) for f in files), "total_size": sum(len(f) for f in files),
@ -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(
{ {

22
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,26 +27,25 @@ class Item(BaseModel):
app = FastAPI() app = FastAPI()
with warnings.catch_warnings(record=True):
warnings.simplefilter("always")
@app.post("/simple-model") @app.post("/simple-model")
def handle_simple_model(data: SubItem) -> SubItem: def handle_simple_model(data: SubItem) -> SubItem:
return data return data
@app.post("/simple-model-filter", response_model=SubItem)
@app.post("/simple-model-filter", response_model=SubItem) def handle_simple_model_filter(data: SubItem) -> Any:
def handle_simple_model_filter(data: SubItem) -> Any:
extended_data = data.dict() extended_data = data.dict()
extended_data.update({"secret_price": 42}) extended_data.update({"secret_price": 42})
return extended_data 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})

33
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,28 +28,28 @@ 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.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]
@app.post("/item-list")
@app.post("/item-list") def handle_item_list(data: list[Item]) -> Item:
def handle_item_list(data: list[Item]) -> Item:
if data: if data:
return data[0] return data[0]
return Item(title="", size=0, sub=SubItem(name="")) return Item(title="", size=0, sub=SubItem(name=""))
@app.post("/item-list-filter", response_model=Item)
@app.post("/item-list-filter", response_model=Item) def handle_item_list_filter(data: list[Item]) -> Any:
def handle_item_list_filter(data: list[Item]) -> Any:
if data: if data:
extended_data = data[0].dict() extended_data = data[0].dict()
extended_data.update({"secret_data": "classified", "internal_id": 12345}) extended_data.update({"secret_data": "classified", "internal_id": 12345})
@ -56,14 +57,12 @@ def handle_item_list_filter(data: list[Item]) -> Any:
return extended_data return extended_data
return Item(title="", size=0, sub=SubItem(name="")) return Item(title="", size=0, sub=SubItem(name=""))
@app.post("/item-list-to-list")
@app.post("/item-list-to-list") def handle_item_list_to_list(data: list[Item]) -> list[Item]:
def handle_item_list_to_list(data: list[Item]) -> list[Item]:
return data return data
@app.post("/item-list-to-list-filter", response_model=list[Item])
@app.post("/item-list-to-list-filter", response_model=list[Item]) def handle_item_list_to_list_filter(data: list[Item]) -> Any:
def handle_item_list_to_list_filter(data: list[Item]) -> Any:
if data: if data:
extended_data = data[0].dict() extended_data = data[0].dict()
extended_data.update({"secret_data": "classified", "internal_id": 12345}) extended_data.update({"secret_data": "classified", "internal_id": 12345})

83
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,9 +40,11 @@ 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,
@ -50,24 +53,26 @@ def handle_v1_item_to_v2(data: Item) -> NewItem:
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)
@app.post("/v1-to-v2/item-filter", response_model=NewItem) def handle_v1_item_to_v2_filter(data: Item) -> Any:
def handle_v1_item_to_v2_filter(data: Item) -> Any:
result = { 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": {"new_sub_name": data.sub.name, "new_sub_secret": "sub_hidden"}, "new_sub": {
"new_sub_name": data.sub.name,
"new_sub_secret": "sub_hidden",
},
"new_multi": [ "new_multi": [
{"new_sub_name": s.name, "new_sub_secret": "sub_hidden"} for s in data.multi {"new_sub_name": s.name, "new_sub_secret": "sub_hidden"}
for s in data.multi
], ],
"secret": "hidden_v1_to_v2", "secret": "hidden_v1_to_v2",
} }
return result return result
@app.post("/v2-to-v1/item")
@app.post("/v2-to-v1/item") def handle_v2_item_to_v1(data: NewItem) -> Item:
def handle_v2_item_to_v1(data: NewItem) -> Item:
return Item( return Item(
title=data.new_title, title=data.new_title,
size=data.new_size, size=data.new_size,
@ -76,24 +81,23 @@ def handle_v2_item_to_v1(data: NewItem) -> Item:
multi=[SubItem(name=s.new_sub_name) for s in data.new_multi], multi=[SubItem(name=s.new_sub_name) for s in data.new_multi],
) )
@app.post("/v2-to-v1/item-filter", response_model=Item)
@app.post("/v2-to-v1/item-filter", response_model=Item) def handle_v2_item_to_v1_filter(data: NewItem) -> Any:
def handle_v2_item_to_v1_filter(data: NewItem) -> Any:
result = { result = {
"title": data.new_title, "title": data.new_title,
"size": data.new_size, "size": data.new_size,
"description": data.new_description, "description": data.new_description,
"sub": {"name": data.new_sub.new_sub_name, "sub_secret": "sub_hidden"}, "sub": {"name": data.new_sub.new_sub_name, "sub_secret": "sub_hidden"},
"multi": [ "multi": [
{"name": s.new_sub_name, "sub_secret": "sub_hidden"} for s in data.new_multi {"name": s.new_sub_name, "sub_secret": "sub_hidden"}
for s in data.new_multi
], ],
"secret": "hidden_v2_to_v1", "secret": "hidden_v2_to_v1",
} }
return result return result
@app.post("/v1-to-v2/item-to-list")
@app.post("/v1-to-v2/item-to-list") def handle_v1_item_to_v2_list(data: Item) -> list[NewItem]:
def handle_v1_item_to_v2_list(data: Item) -> list[NewItem]:
converted = NewItem( converted = NewItem(
new_title=data.title, new_title=data.title,
new_size=data.size, new_size=data.size,
@ -103,9 +107,8 @@ def handle_v1_item_to_v2_list(data: Item) -> list[NewItem]:
) )
return [converted, converted] return [converted, converted]
@app.post("/v1-to-v2/list-to-list")
@app.post("/v1-to-v2/list-to-list") def handle_v1_list_to_v2_list(data: list[Item]) -> list[NewItem]:
def handle_v1_list_to_v2_list(data: list[Item]) -> list[NewItem]:
result = [] result = []
for item in data: for item in data:
result.append( result.append(
@ -119,16 +122,18 @@ def handle_v1_list_to_v2_list(data: list[Item]) -> list[NewItem]:
) )
return result return result
@app.post("/v1-to-v2/list-to-list-filter", response_model=list[NewItem])
@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:
def handle_v1_list_to_v2_list_filter(data: list[Item]) -> Any:
result = [] result = []
for item in data: for item in data:
converted = { converted = {
"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": {"new_sub_name": item.sub.name, "new_sub_secret": "sub_hidden"}, "new_sub": {
"new_sub_name": item.sub.name,
"new_sub_secret": "sub_hidden",
},
"new_multi": [ "new_multi": [
{"new_sub_name": s.name, "new_sub_secret": "sub_hidden"} {"new_sub_name": s.name, "new_sub_secret": "sub_hidden"}
for s in item.multi for s in item.multi
@ -138,9 +143,8 @@ def handle_v1_list_to_v2_list_filter(data: list[Item]) -> Any:
result.append(converted) result.append(converted)
return result return result
@app.post("/v1-to-v2/list-to-item")
@app.post("/v1-to-v2/list-to-item") def handle_v1_list_to_v2_item(data: list[Item]) -> NewItem:
def handle_v1_list_to_v2_item(data: list[Item]) -> NewItem:
if data: if data:
item = data[0] item = data[0]
return NewItem( return NewItem(
@ -152,9 +156,8 @@ def handle_v1_list_to_v2_item(data: list[Item]) -> NewItem:
) )
return NewItem(new_title="", new_size=0, new_sub=NewSubItem(new_sub_name="")) return NewItem(new_title="", new_size=0, new_sub=NewSubItem(new_sub_name=""))
@app.post("/v2-to-v1/item-to-list")
@app.post("/v2-to-v1/item-to-list") def handle_v2_item_to_v1_list(data: NewItem) -> list[Item]:
def handle_v2_item_to_v1_list(data: NewItem) -> list[Item]:
converted = Item( converted = Item(
title=data.new_title, title=data.new_title,
size=data.new_size, size=data.new_size,
@ -164,9 +167,8 @@ def handle_v2_item_to_v1_list(data: NewItem) -> list[Item]:
) )
return [converted, converted] return [converted, converted]
@app.post("/v2-to-v1/list-to-list")
@app.post("/v2-to-v1/list-to-list") def handle_v2_list_to_v1_list(data: list[NewItem]) -> list[Item]:
def handle_v2_list_to_v1_list(data: list[NewItem]) -> list[Item]:
result = [] result = []
for item in data: for item in data:
result.append( result.append(
@ -180,16 +182,18 @@ def handle_v2_list_to_v1_list(data: list[NewItem]) -> list[Item]:
) )
return result return result
@app.post("/v2-to-v1/list-to-list-filter", response_model=list[Item])
@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:
def handle_v2_list_to_v1_list_filter(data: list[NewItem]) -> Any:
result = [] result = []
for item in data: for item in data:
converted = { converted = {
"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": {"name": item.new_sub.new_sub_name, "sub_secret": "sub_hidden"}, "sub": {
"name": item.new_sub.new_sub_name,
"sub_secret": "sub_hidden",
},
"multi": [ "multi": [
{"name": s.new_sub_name, "sub_secret": "sub_hidden"} {"name": s.new_sub_name, "sub_secret": "sub_hidden"}
for s in item.new_multi for s in item.new_multi
@ -199,9 +203,8 @@ def handle_v2_list_to_v1_list_filter(data: list[NewItem]) -> Any:
result.append(converted) result.append(converted)
return result return result
@app.post("/v2-to-v1/list-to-item")
@app.post("/v2-to-v1/list-to-item") def handle_v2_list_to_v1_item(data: list[NewItem]) -> Item:
def handle_v2_list_to_v1_item(data: list[NewItem]) -> Item:
if data: if data:
item = data[0] item = data[0]
return Item( return Item(

69
tests/test_pydantic_v1_v2_multifile/main.py

@ -1,12 +1,16 @@
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,
@ -15,9 +19,8 @@ def handle_v1_item_to_v2(data: modelsv1.Item) -> modelsv2.Item:
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")
@app.post("/v2-to-v1/item") def handle_v2_item_to_v1(data: modelsv2.Item) -> modelsv1.Item:
def handle_v2_item_to_v1(data: modelsv2.Item) -> modelsv1.Item:
return modelsv1.Item( return modelsv1.Item(
title=data.new_title, title=data.new_title,
size=data.new_size, size=data.new_size,
@ -26,9 +29,8 @@ def handle_v2_item_to_v1(data: modelsv2.Item) -> modelsv1.Item:
multi=[modelsv1.SubItem(name=s.new_sub_name) for s in data.new_multi], multi=[modelsv1.SubItem(name=s.new_sub_name) for s in data.new_multi],
) )
@app.post("/v1-to-v2/item-to-list")
@app.post("/v1-to-v2/item-to-list") def handle_v1_item_to_v2_list(data: modelsv1.Item) -> list[modelsv2.Item]:
def handle_v1_item_to_v2_list(data: modelsv1.Item) -> list[modelsv2.Item]:
converted = modelsv2.Item( converted = modelsv2.Item(
new_title=data.title, new_title=data.title,
new_size=data.size, new_size=data.size,
@ -38,9 +40,8 @@ def handle_v1_item_to_v2_list(data: modelsv1.Item) -> list[modelsv2.Item]:
) )
return [converted, converted] return [converted, converted]
@app.post("/v1-to-v2/list-to-list")
@app.post("/v1-to-v2/list-to-list") def handle_v1_list_to_v2_list(data: list[modelsv1.Item]) -> list[modelsv2.Item]:
def handle_v1_list_to_v2_list(data: list[modelsv1.Item]) -> list[modelsv2.Item]:
result = [] result = []
for item in data: for item in data:
result.append( result.append(
@ -49,14 +50,15 @@ def handle_v1_list_to_v2_list(data: list[modelsv1.Item]) -> list[modelsv2.Item]:
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 return result
@app.post("/v1-to-v2/list-to-item")
@app.post("/v1-to-v2/list-to-item") def handle_v1_list_to_v2_item(data: list[modelsv1.Item]) -> modelsv2.Item:
def handle_v1_list_to_v2_item(data: list[modelsv1.Item]) -> modelsv2.Item:
if data: if data:
item = data[0] item = data[0]
return modelsv2.Item( return modelsv2.Item(
@ -70,9 +72,8 @@ def handle_v1_list_to_v2_item(data: list[modelsv1.Item]) -> modelsv2.Item:
new_title="", new_size=0, new_sub=modelsv2.SubItem(new_sub_name="") new_title="", new_size=0, new_sub=modelsv2.SubItem(new_sub_name="")
) )
@app.post("/v2-to-v1/item-to-list")
@app.post("/v2-to-v1/item-to-list") def handle_v2_item_to_v1_list(data: modelsv2.Item) -> list[modelsv1.Item]:
def handle_v2_item_to_v1_list(data: modelsv2.Item) -> list[modelsv1.Item]:
converted = modelsv1.Item( converted = modelsv1.Item(
title=data.new_title, title=data.new_title,
size=data.new_size, size=data.new_size,
@ -82,9 +83,8 @@ def handle_v2_item_to_v1_list(data: modelsv2.Item) -> list[modelsv1.Item]:
) )
return [converted, converted] return [converted, converted]
@app.post("/v2-to-v1/list-to-list")
@app.post("/v2-to-v1/list-to-list") def handle_v2_list_to_v1_list(data: list[modelsv2.Item]) -> list[modelsv1.Item]:
def handle_v2_list_to_v1_list(data: list[modelsv2.Item]) -> list[modelsv1.Item]:
result = [] result = []
for item in data: for item in data:
result.append( result.append(
@ -93,14 +93,15 @@ def handle_v2_list_to_v1_list(data: list[modelsv2.Item]) -> list[modelsv1.Item]:
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 result return result
@app.post("/v2-to-v1/list-to-item")
@app.post("/v2-to-v1/list-to-item") def handle_v2_list_to_v1_item(data: list[modelsv2.Item]) -> modelsv1.Item:
def handle_v2_list_to_v1_item(data: list[modelsv2.Item]) -> modelsv1.Item:
if data: if data:
item = data[0] item = data[0]
return modelsv1.Item( return modelsv1.Item(
@ -112,11 +113,10 @@ def handle_v2_list_to_v1_item(data: list[modelsv2.Item]) -> modelsv1.Item:
) )
return modelsv1.Item(title="", size=0, sub=modelsv1.SubItem(name="")) return modelsv1.Item(title="", size=0, sub=modelsv1.SubItem(name=""))
@app.post("/v2-to-v1/same-name")
@app.post("/v2-to-v1/same-name") def handle_v2_same_name_to_v1(
def handle_v2_same_name_to_v1(
item1: modelsv2.Item, item2: modelsv2b.Item item1: modelsv2.Item, item2: modelsv2b.Item
) -> modelsv1.Item: ) -> modelsv1.Item:
return modelsv1.Item( return modelsv1.Item(
title=item1.new_title, title=item1.new_title,
size=item2.dup_size, size=item2.dup_size,
@ -125,16 +125,13 @@ def handle_v2_same_name_to_v1(
multi=[modelsv1.SubItem(name=s.dup_sub_name) for s in item2.dup_multi], 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]
result = [ return [
modelsv1.ItemInList(name1=item1.name2), modelsv1.ItemInList(name1=item1.name2),
modelsv1.ItemInList(name1=item2.dup_name2), modelsv1.ItemInList(name1=item2.dup_name2),
] ]
return result

33
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,9 +40,11 @@ class NewItem(NewBaseModel):
app = FastAPI() app = FastAPI()
with warnings.catch_warnings(record=True):
warnings.simplefilter("always")
@app.post("/v1-to-v2/") @app.post("/v1-to-v2/")
def handle_v1_item_to_v2(data: Item) -> Union[NewItem, None]: def handle_v1_item_to_v2(data: Item) -> Union[NewItem, None]:
if data.size < 0: if data.size < 0:
return None return None
return NewItem( return NewItem(
@ -52,26 +55,28 @@ def handle_v1_item_to_v2(data: Item) -> Union[NewItem, None]:
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=Union[NewItem, None])
@app.post("/v1-to-v2/item-filter", response_model=Union[NewItem, None]) def handle_v1_item_to_v2_filter(data: Item) -> Any:
def handle_v1_item_to_v2_filter(data: Item) -> Any:
if data.size < 0: if data.size < 0:
return None return None
result = { 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": {"new_sub_name": data.sub.name, "new_sub_secret": "sub_hidden"}, "new_sub": {
"new_sub_name": data.sub.name,
"new_sub_secret": "sub_hidden",
},
"new_multi": [ "new_multi": [
{"new_sub_name": s.name, "new_sub_secret": "sub_hidden"} for s in data.multi {"new_sub_name": s.name, "new_sub_secret": "sub_hidden"}
for s in data.multi
], ],
"secret": "hidden_v1_to_v2", "secret": "hidden_v1_to_v2",
} }
return result return result
@app.post("/v2-to-v1/item")
@app.post("/v2-to-v1/item") def handle_v2_item_to_v1(data: NewItem) -> Union[Item, None]:
def handle_v2_item_to_v1(data: NewItem) -> Union[Item, None]:
if data.new_size < 0: if data.new_size < 0:
return None return None
return Item( return Item(
@ -82,9 +87,8 @@ def handle_v2_item_to_v1(data: NewItem) -> Union[Item, None]:
multi=[SubItem(name=s.new_sub_name) for s in data.new_multi], 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])
@app.post("/v2-to-v1/item-filter", response_model=Union[Item, None]) def handle_v2_item_to_v1_filter(data: NewItem) -> Any:
def handle_v2_item_to_v1_filter(data: NewItem) -> Any:
if data.new_size < 0: if data.new_size < 0:
return None return None
result = { result = {
@ -93,7 +97,8 @@ def handle_v2_item_to_v1_filter(data: NewItem) -> Any:
"description": data.new_description, "description": data.new_description,
"sub": {"name": data.new_sub.new_sub_name, "sub_secret": "sub_hidden"}, "sub": {"name": data.new_sub.new_sub_name, "sub_secret": "sub_hidden"},
"multi": [ "multi": [
{"name": s.new_sub_name, "sub_secret": "sub_hidden"} for s in data.new_multi {"name": s.new_sub_name, "sub_secret": "sub_hidden"}
for s in data.new_multi
], ],
"secret": "hidden_v2_to_v1", "secret": "hidden_v2_to_v1",
} }

Loading…
Cancel
Save