Browse Source

🔊 Add deprecation warnings when using `pydantic.v1` (#14583)

pull/14586/head
Sebastián Ramírez 7 months ago
committed by GitHub
parent
commit
6e42bcd8ce
No known key found for this signature in database GPG Key ID: B5690EEEBB952194
  1. 8
      fastapi/dependencies/utils.py
  2. 16
      fastapi/routing.py
  3. 8
      tests/benchmarks/test_general_performance.py
  4. 33
      tests/test_compat_params_v1.py
  5. 4
      tests/test_datetime_custom_encoder.py
  6. 4
      tests/test_filter_pydantic_sub_model/app_pv1.py
  7. 20
      tests/test_get_model_definitions_formfeed_escape.py
  8. 98
      tests/test_pydantic_v1_deprecation_warnings.py
  9. 6
      tests/test_pydantic_v1_v2_01.py
  10. 9
      tests/test_pydantic_v1_v2_list.py
  11. 35
      tests/test_pydantic_v1_v2_mixed.py
  12. 25
      tests/test_pydantic_v1_v2_multifile/main.py
  13. 17
      tests/test_pydantic_v1_v2_noneable.py
  14. 4
      tests/test_read_with_orm_mode.py
  15. 4
      tests/test_response_model_as_return_annotation.py
  16. 7
      tests/test_tutorial/test_pydantic_v1_in_v2/test_tutorial002.py
  17. 7
      tests/test_tutorial/test_pydantic_v1_in_v2/test_tutorial003.py
  18. 7
      tests/test_tutorial/test_pydantic_v1_in_v2/test_tutorial004.py
  19. 7
      tests/test_tutorial/test_request_form_models/test_tutorial002_pv1.py
  20. 7
      tests/test_tutorial/test_schema_extra_example/test_tutorial001_pv1.py

8
fastapi/dependencies/utils.py

@ -1,6 +1,7 @@
import dataclasses
import inspect
import sys
import warnings
from collections.abc import Coroutine, Mapping, Sequence
from contextlib import AsyncExitStack, contextmanager
from copy import copy, deepcopy
@ -322,6 +323,13 @@ def get_dependant(
)
continue
assert param_details.field is not None
if isinstance(param_details.field, may_v1.ModelField):
warnings.warn(
"pydantic.v1 is deprecated and will soon stop being supported by FastAPI."
f" Please update the param {param_name}: {param_details.type_annotation!r}.",
category=DeprecationWarning,
stacklevel=5,
)
if isinstance(
param_details.field.field_info, (params.Body, temp_pydantic_v1_params.Body)
):

16
fastapi/routing.py

@ -2,6 +2,7 @@ import email.message
import functools
import inspect
import json
import warnings
from collections.abc import (
AsyncIterator,
Awaitable,
@ -28,6 +29,7 @@ from fastapi._compat import (
_get_model_config,
_model_dump,
_normalize_errors,
annotation_is_pydantic_v1,
lenient_issubclass,
may_v1,
)
@ -634,6 +636,13 @@ class APIRoute(routing.Route):
f"Status code {status_code} must not have a response body"
)
response_name = "Response_" + self.unique_id
if annotation_is_pydantic_v1(self.response_model):
warnings.warn(
"pydantic.v1 is deprecated and will soon stop being supported by FastAPI."
f" Please update the response model {self.response_model!r}.",
category=DeprecationWarning,
stacklevel=4,
)
self.response_field = create_model_field(
name=response_name,
type_=self.response_model,
@ -667,6 +676,13 @@ class APIRoute(routing.Route):
f"Status code {additional_status_code} must not have a response body"
)
response_name = f"Response_{additional_status_code}_{self.unique_id}"
if annotation_is_pydantic_v1(model):
warnings.warn(
"pydantic.v1 is deprecated and will soon stop being supported by FastAPI."
f" In responses={{}}, please update {model}.",
category=DeprecationWarning,
stacklevel=4,
)
response_field = create_model_field(
name=response_name, type_=model, mode="serialization"
)

8
tests/benchmarks/test_general_performance.py

@ -1,5 +1,6 @@
import json
import sys
import warnings
from collections.abc import Iterator
from typing import Annotated, Any
@ -84,6 +85,13 @@ def app(basemodel_class: type[Any]) -> FastAPI:
app = FastAPI()
with warnings.catch_warnings(record=True):
warnings.filterwarnings(
"ignore",
message=r"pydantic\.v1 is deprecated and will soon stop being supported by FastAPI\..*",
category=DeprecationWarning,
)
@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)

33
tests/test_compat_params_v1.py

@ -1,4 +1,5 @@
import sys
import warnings
from typing import Optional
import pytest
@ -33,6 +34,8 @@ class Item(BaseModel):
app = FastAPI()
with warnings.catch_warnings(record=True):
warnings.simplefilter("always")
@app.get("/items/{item_id}")
def get_item_with_path(
@ -40,18 +43,17 @@ def get_item_with_path(
):
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 ]+$")
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,
@ -59,7 +61,6 @@ def get_user_with_header(
):
return {"x_custom": x_custom, "x_token": x_token}
@app.get("/cookies/")
def get_cookies(
session_id: Annotated[Optional[str], Cookie()] = None,
@ -67,24 +68,23 @@ def get_cookies(
):
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"}]),
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)],
@ -93,7 +93,6 @@ def update_item(
):
return {"item": item, "importance": importance}
@app.post("/form-data/")
def submit_form(
username: Annotated[str, Form(min_length=3, max_length=50)],
@ -102,7 +101,6 @@ def submit_form(
):
return {"username": username, "password": password, "email": email}
@app.post("/upload/")
def upload_file(
file: Annotated[bytes, File()],
@ -110,7 +108,6 @@ def upload_file(
):
return {"file_size": len(file), "description": description}
@app.post("/upload-multiple/")
def upload_multiple_files(
files: Annotated[list[bytes], File()],
@ -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(
{

4
tests/test_datetime_custom_encoder.py

@ -1,3 +1,4 @@
import warnings
from datetime import datetime, timezone
from fastapi import FastAPI
@ -48,6 +49,9 @@ def test_pydanticv1():
app = FastAPI()
model = ModelWithDatetimeField(dt_field=datetime(2019, 1, 1, 8))
with warnings.catch_warnings(record=True):
warnings.simplefilter("always")
@app.get("/model", response_model=ModelWithDatetimeField)
def get_model():
return model

4
tests/test_filter_pydantic_sub_model/app_pv1.py

@ -1,3 +1,4 @@
import warnings
from typing import Optional
from fastapi import Depends, FastAPI
@ -31,6 +32,9 @@ async def get_model_c() -> ModelC:
return ModelC(username="test-user", password="test-password")
with warnings.catch_warnings(record=True):
warnings.simplefilter("always")
@app.get("/model/{name}", response_model=ModelA)
async def get_model_a(name: str, model_c=Depends(get_model_c)):
return {

20
tests/test_get_model_definitions_formfeed_escape.py

@ -1,3 +1,5 @@
import warnings
import pytest
from fastapi import FastAPI
from fastapi.testclient import TestClient
@ -36,11 +38,27 @@ def client_fixture(request: pytest.FixtureRequest) -> TestClient:
app = FastAPI()
if request.param == "pydantic-v1":
with warnings.catch_warnings(record=True):
warnings.simplefilter("always")
@app.get("/facilities/{facility_id}")
def get_facility(facility_id: str) -> Facility:
return Facility(
id=facility_id,
address=Address(
line_1="123 Main St", city="Anytown", state_province="CA"
),
)
else:
@app.get("/facilities/{facility_id}")
def get_facility(facility_id: str) -> Facility:
return Facility(
id=facility_id,
address=Address(line_1="123 Main St", city="Anytown", state_province="CA"),
address=Address(
line_1="123 Main St", city="Anytown", state_province="CA"
),
)
client = TestClient(app)

98
tests/test_pydantic_v1_deprecation_warnings.py

@ -0,0 +1,98 @@
import sys
import pytest
from tests.utils import skip_module_if_py_gte_314
if sys.version_info >= (3, 14):
skip_module_if_py_gte_314()
from fastapi import FastAPI
from fastapi._compat.v1 import BaseModel
from fastapi.testclient import TestClient
def test_warns_pydantic_v1_model_in_endpoint_param() -> None:
class ParamModelV1(BaseModel):
name: str
app = FastAPI()
with pytest.warns(
DeprecationWarning,
match=r"pydantic\.v1 is deprecated.*Please update the param data:",
):
@app.post("/param")
def endpoint(data: ParamModelV1):
return data
client = TestClient(app)
response = client.post("/param", json={"name": "test"})
assert response.status_code == 200, response.text
assert response.json() == {"name": "test"}
def test_warns_pydantic_v1_model_in_return_type() -> None:
class ReturnModelV1(BaseModel):
name: str
app = FastAPI()
with pytest.warns(
DeprecationWarning,
match=r"pydantic\.v1 is deprecated.*Please update the response model",
):
@app.get("/return")
def endpoint() -> ReturnModelV1:
return ReturnModelV1(name="test")
client = TestClient(app)
response = client.get("/return")
assert response.status_code == 200, response.text
assert response.json() == {"name": "test"}
def test_warns_pydantic_v1_model_in_response_model() -> None:
class ResponseModelV1(BaseModel):
name: str
app = FastAPI()
with pytest.warns(
DeprecationWarning,
match=r"pydantic\.v1 is deprecated.*Please update the response model",
):
@app.get("/response-model", response_model=ResponseModelV1)
def endpoint():
return {"name": "test"}
client = TestClient(app)
response = client.get("/response-model")
assert response.status_code == 200, response.text
assert response.json() == {"name": "test"}
def test_warns_pydantic_v1_model_in_additional_responses_model() -> None:
class ErrorModelV1(BaseModel):
detail: str
app = FastAPI()
with pytest.warns(
DeprecationWarning,
match=r"pydantic\.v1 is deprecated.*In responses=\{\}, please update",
):
@app.get(
"/responses", response_model=None, responses={400: {"model": ErrorModelV1}}
)
def endpoint():
return {"ok": True}
client = TestClient(app)
response = client.get("/responses")
assert response.status_code == 200, response.text
assert response.json() == {"ok": True}

6
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,24 +27,23 @@ class Item(BaseModel):
app = FastAPI()
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()

9
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,11 +28,13 @@ class Item(BaseModel):
app = FastAPI()
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()
@ -39,14 +42,12 @@ def handle_item_filter(data: Item) -> Any:
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:
@ -56,12 +57,10 @@ def handle_item_list_filter(data: list[Item]) -> Any:
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:

35
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,6 +40,8 @@ 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:
@ -50,22 +53,24 @@ def handle_v1_item_to_v2(data: Item) -> NewItem:
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_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
{"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(
@ -76,7 +81,6 @@ def handle_v2_item_to_v1(data: NewItem) -> Item:
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 = {
@ -85,13 +89,13 @@ def handle_v2_item_to_v1_filter(data: NewItem) -> Any:
"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
{"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(
@ -103,7 +107,6 @@ def handle_v1_item_to_v2_list(data: Item) -> list[NewItem]:
)
return [converted, converted]
@app.post("/v1-to-v2/list-to-list")
def handle_v1_list_to_v2_list(data: list[Item]) -> list[NewItem]:
result = []
@ -119,7 +122,6 @@ def handle_v1_list_to_v2_list(data: list[Item]) -> list[NewItem]:
)
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 = []
@ -128,7 +130,10 @@ def handle_v1_list_to_v2_list_filter(data: list[Item]) -> Any:
"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_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
@ -138,7 +143,6 @@ def handle_v1_list_to_v2_list_filter(data: list[Item]) -> Any:
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:
@ -152,7 +156,6 @@ def handle_v1_list_to_v2_item(data: list[Item]) -> NewItem:
)
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(
@ -164,7 +167,6 @@ def handle_v2_item_to_v1_list(data: NewItem) -> list[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 = []
@ -180,7 +182,6 @@ def handle_v2_list_to_v1_list(data: list[NewItem]) -> list[Item]:
)
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 = []
@ -189,7 +190,10 @@ def handle_v2_list_to_v1_list_filter(data: list[NewItem]) -> Any:
"title": item.new_title,
"size": item.new_size,
"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": [
{"name": s.new_sub_name, "sub_secret": "sub_hidden"}
for s in item.new_multi
@ -199,7 +203,6 @@ def handle_v2_list_to_v1_list_filter(data: list[NewItem]) -> Any:
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:

25
tests/test_pydantic_v1_v2_multifile/main.py

@ -1,9 +1,13 @@
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:
@ -15,7 +19,6 @@ 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],
)
@app.post("/v2-to-v1/item")
def handle_v2_item_to_v1(data: modelsv2.Item) -> modelsv1.Item:
return modelsv1.Item(
@ -26,7 +29,6 @@ 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],
)
@app.post("/v1-to-v2/item-to-list")
def handle_v1_item_to_v2_list(data: modelsv1.Item) -> list[modelsv2.Item]:
converted = modelsv2.Item(
@ -38,7 +40,6 @@ def handle_v1_item_to_v2_list(data: modelsv1.Item) -> list[modelsv2.Item]:
)
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 = []
@ -49,12 +50,13 @@ def handle_v1_list_to_v2_list(data: list[modelsv1.Item]) -> list[modelsv2.Item]:
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_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:
@ -70,7 +72,6 @@ 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="")
)
@app.post("/v2-to-v1/item-to-list")
def handle_v2_item_to_v1_list(data: modelsv2.Item) -> list[modelsv1.Item]:
converted = modelsv1.Item(
@ -82,7 +83,6 @@ def handle_v2_item_to_v1_list(data: modelsv2.Item) -> list[modelsv1.Item]:
)
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 = []
@ -93,12 +93,13 @@ def handle_v2_list_to_v1_list(data: list[modelsv2.Item]) -> list[modelsv1.Item]:
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],
multi=[
modelsv1.SubItem(name=s.new_sub_name) for s in item.new_multi
],
)
)
return result
@app.post("/v2-to-v1/list-to-item")
def handle_v2_list_to_v1_item(data: list[modelsv2.Item]) -> modelsv1.Item:
if data:
@ -112,7 +113,6 @@ def handle_v2_list_to_v1_item(data: list[modelsv2.Item]) -> modelsv1.Item:
)
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
@ -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],
)
@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 = [
return [
modelsv1.ItemInList(name1=item1.name2),
modelsv1.ItemInList(name1=item2.dup_name2),
]
return result

17
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,6 +40,8 @@ class NewItem(NewBaseModel):
app = FastAPI()
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]:
@ -52,7 +55,6 @@ def handle_v1_item_to_v2(data: Item) -> Union[NewItem, None]:
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:
@ -61,15 +63,18 @@ def handle_v1_item_to_v2_filter(data: Item) -> Any:
"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_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
{"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:
@ -82,7 +87,6 @@ def handle_v2_item_to_v1(data: NewItem) -> Union[Item, None]:
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:
@ -93,7 +97,8 @@ def handle_v2_item_to_v1_filter(data: NewItem) -> Any:
"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
{"name": s.new_sub_name, "sub_secret": "sub_hidden"}
for s in data.new_multi
],
"secret": "hidden_v2_to_v1",
}

4
tests/test_read_with_orm_mode.py

@ -1,3 +1,4 @@
import warnings
from typing import Any
from fastapi import FastAPI
@ -73,6 +74,9 @@ def test_read_with_orm_mode_pv1() -> None:
app = FastAPI()
with warnings.catch_warnings(record=True):
warnings.simplefilter("always")
@app.post("/people/", response_model=PersonRead)
def create_person(person: PersonCreate) -> Any:
db_person = Person.from_orm(person)

4
tests/test_response_model_as_return_annotation.py

@ -1,3 +1,4 @@
import warnings
from typing import Union
import pytest
@ -521,6 +522,9 @@ def test_invalid_response_model_field_pv1():
class Model(v1.BaseModel):
foo: str
with warnings.catch_warnings(record=True):
warnings.simplefilter("always")
with pytest.raises(FastAPIError) as e:
@app.get("/")

7
tests/test_tutorial/test_pydantic_v1_in_v2/test_tutorial002.py

@ -1,4 +1,5 @@
import sys
import warnings
import pytest
from inline_snapshot import snapshot
@ -24,6 +25,12 @@ from ...utils import needs_py310
],
)
def get_client(request: pytest.FixtureRequest):
with warnings.catch_warnings(record=True):
warnings.filterwarnings(
"ignore",
message=r"pydantic\.v1 is deprecated and will soon stop being supported by FastAPI\..*",
category=DeprecationWarning,
)
mod = importlib.import_module(f"docs_src.pydantic_v1_in_v2.{request.param}")
c = TestClient(mod.app)

7
tests/test_tutorial/test_pydantic_v1_in_v2/test_tutorial003.py

@ -1,4 +1,5 @@
import sys
import warnings
import pytest
from inline_snapshot import snapshot
@ -24,6 +25,12 @@ from ...utils import needs_py310
],
)
def get_client(request: pytest.FixtureRequest):
with warnings.catch_warnings(record=True):
warnings.filterwarnings(
"ignore",
message=r"pydantic\.v1 is deprecated and will soon stop being supported by FastAPI\..*",
category=DeprecationWarning,
)
mod = importlib.import_module(f"docs_src.pydantic_v1_in_v2.{request.param}")
c = TestClient(mod.app)

7
tests/test_tutorial/test_pydantic_v1_in_v2/test_tutorial004.py

@ -1,4 +1,5 @@
import sys
import warnings
import pytest
from inline_snapshot import snapshot
@ -24,6 +25,12 @@ from ...utils import needs_py310
],
)
def get_client(request: pytest.FixtureRequest):
with warnings.catch_warnings(record=True):
warnings.filterwarnings(
"ignore",
message=r"pydantic\.v1 is deprecated and will soon stop being supported by FastAPI\..*",
category=DeprecationWarning,
)
mod = importlib.import_module(f"docs_src.pydantic_v1_in_v2.{request.param}")
c = TestClient(mod.app)

7
tests/test_tutorial/test_request_form_models/test_tutorial002_pv1.py

@ -1,4 +1,5 @@
import importlib
import warnings
import pytest
from fastapi.testclient import TestClient
@ -14,6 +15,12 @@ from ...utils import needs_pydanticv1
],
)
def get_client(request: pytest.FixtureRequest):
with warnings.catch_warnings(record=True):
warnings.filterwarnings(
"ignore",
message=r"pydantic\.v1 is deprecated and will soon stop being supported by FastAPI\..*",
category=DeprecationWarning,
)
mod = importlib.import_module(f"docs_src.request_form_models.{request.param}")
client = TestClient(mod.app)

7
tests/test_tutorial/test_schema_extra_example/test_tutorial001_pv1.py

@ -1,4 +1,5 @@
import importlib
import warnings
import pytest
from fastapi.testclient import TestClient
@ -15,6 +16,12 @@ from ...utils import needs_py310, needs_pydanticv1
],
)
def get_client(request: pytest.FixtureRequest):
with warnings.catch_warnings(record=True):
warnings.filterwarnings(
"ignore",
message=r"pydantic\.v1 is deprecated and will soon stop being supported by FastAPI\..*",
category=DeprecationWarning,
)
mod = importlib.import_module(f"docs_src.schema_extra_example.{request.param}")
client = TestClient(mod.app)

Loading…
Cancel
Save