Browse Source

🔥 Remove test variants for Pydantic v1 with pydantic_snapshot

pull/14575/head
Sebastián Ramírez 7 months ago
parent
commit
cd93507108
  1. 133
      tests/test_compat_params_v1.py
  2. 6
      tests/test_datastructures.py
  3. 46
      tests/test_no_schema_split.py
  4. 78
      tests/test_pydantic_v1_v2_01.py
  5. 40
      tests/test_pydantic_v1_v2_list.py
  6. 216
      tests/test_pydantic_v1_v2_mixed.py
  7. 769
      tests/test_pydantic_v1_v2_multifile/test_multifile.py
  8. 169
      tests/test_pydantic_v1_v2_noneable.py
  9. 57
      tests/test_tutorial/test_cookie_param_models/test_tutorial002.py
  10. 23
      tests/utils.py

133
tests/test_compat_params_v1.py

@ -3,7 +3,7 @@ from typing import Optional
import pytest
from tests.utils import pydantic_snapshot, skip_module_if_py_gte_314
from tests.utils import skip_module_if_py_gte_314
if sys.version_info >= (3, 14):
skip_module_if_py_gte_314()
@ -588,23 +588,14 @@ def test_openapi_schema():
"required": True,
"content": {
"application/json": {
"schema": pydantic_snapshot(
v1=snapshot(
"schema": {
"title": "Body",
"allOf": [
{
"$ref": "#/components/schemas/Body_update_item_items__item_id__put"
}
),
v2=snapshot(
{
"title": "Body",
"allOf": [
{
"$ref": "#/components/schemas/Body_update_item_items__item_id__put"
}
],
}
),
),
],
}
}
},
},
@ -809,23 +800,14 @@ def test_openapi_schema():
"requestBody": {
"content": {
"application/json": {
"schema": pydantic_snapshot(
v1=snapshot(
"schema": {
"allOf": [
{
"$ref": "#/components/schemas/Body_create_item_embed_items_embed__post"
}
),
v2=snapshot(
{
"allOf": [
{
"$ref": "#/components/schemas/Body_create_item_embed_items_embed__post"
}
],
"title": "Body",
}
),
),
],
"title": "Body",
}
}
},
"required": True,
@ -855,23 +837,14 @@ def test_openapi_schema():
"requestBody": {
"content": {
"application/x-www-form-urlencoded": {
"schema": pydantic_snapshot(
v1=snapshot(
"schema": {
"allOf": [
{
"$ref": "#/components/schemas/Body_submit_form_form_data__post"
}
),
v2=snapshot(
{
"allOf": [
{
"$ref": "#/components/schemas/Body_submit_form_form_data__post"
}
],
"title": "Body",
}
),
),
],
"title": "Body",
}
}
},
"required": True,
@ -901,23 +874,14 @@ def test_openapi_schema():
"requestBody": {
"content": {
"multipart/form-data": {
"schema": pydantic_snapshot(
v1=snapshot(
"schema": {
"allOf": [
{
"$ref": "#/components/schemas/Body_upload_file_upload__post"
}
),
v2=snapshot(
{
"allOf": [
{
"$ref": "#/components/schemas/Body_upload_file_upload__post"
}
],
"title": "Body",
}
),
),
],
"title": "Body",
},
}
},
"required": True,
@ -947,23 +911,14 @@ def test_openapi_schema():
"requestBody": {
"content": {
"multipart/form-data": {
"schema": pydantic_snapshot(
v1=snapshot(
"schema": {
"allOf": [
{
"$ref": "#/components/schemas/Body_upload_multiple_files_upload_multiple__post"
}
),
v2=snapshot(
{
"allOf": [
{
"$ref": "#/components/schemas/Body_upload_multiple_files_upload_multiple__post"
}
],
"title": "Body",
}
),
),
],
"title": "Body",
}
}
},
"required": True,
@ -990,21 +945,12 @@ def test_openapi_schema():
"components": {
"schemas": {
"Body_create_item_embed_items_embed__post": {
"properties": pydantic_snapshot(
v1=snapshot(
{"item": {"$ref": "#/components/schemas/Item"}}
),
v2=snapshot(
{
"item": {
"allOf": [
{"$ref": "#/components/schemas/Item"}
],
"title": "Item",
}
}
),
),
"properties": {
"item": {
"allOf": [{"$ref": "#/components/schemas/Item"}],
"title": "Item",
}
},
"type": "object",
"required": ["item"],
"title": "Body_create_item_embed_items_embed__post",
@ -1030,17 +976,10 @@ def test_openapi_schema():
},
"Body_update_item_items__item_id__put": {
"properties": {
"item": pydantic_snapshot(
v1=snapshot({"$ref": "#/components/schemas/Item"}),
v2=snapshot(
{
"allOf": [
{"$ref": "#/components/schemas/Item"}
],
"title": "Item",
}
),
),
"item": {
"allOf": [{"$ref": "#/components/schemas/Item"}],
"title": "Item",
},
"importance": {
"type": "integer",
"maximum": 10.0,

6
tests/test_datastructures.py

@ -7,12 +7,6 @@ from fastapi.datastructures import Default
from fastapi.testclient import TestClient
# TODO: remove when deprecating Pydantic v1
def test_upload_file_invalid():
with pytest.raises(ValueError):
UploadFile.validate("not a Starlette UploadFile")
def test_upload_file_invalid_pydantic_v2():
with pytest.raises(ValueError):
UploadFile._validate("not a Starlette UploadFile", {})

46
tests/test_no_schema_split.py

@ -9,8 +9,6 @@ from fastapi.testclient import TestClient
from inline_snapshot import snapshot
from pydantic import BaseModel, Field
from tests.utils import pydantic_snapshot
class MessageEventType(str, Enum):
alpha = "alpha"
@ -126,47 +124,21 @@ def test_openapi_schema():
},
"MessageEvent": {
"properties": {
"event_type": pydantic_snapshot(
v2=snapshot(
{
"$ref": "#/components/schemas/MessageEventType",
"default": "alpha",
}
),
v1=snapshot(
{
"allOf": [
{
"$ref": "#/components/schemas/MessageEventType"
}
],
"default": "alpha",
}
),
),
"event_type": {
"$ref": "#/components/schemas/MessageEventType",
"default": "alpha",
},
"output": {"type": "string", "title": "Output"},
},
"type": "object",
"required": ["output"],
"title": "MessageEvent",
},
"MessageEventType": pydantic_snapshot(
v2=snapshot(
{
"type": "string",
"enum": ["alpha", "beta"],
"title": "MessageEventType",
}
),
v1=snapshot(
{
"type": "string",
"enum": ["alpha", "beta"],
"title": "MessageEventType",
"description": "An enumeration.",
}
),
),
"MessageEventType": {
"type": "string",
"enum": ["alpha", "beta"],
"title": "MessageEventType",
},
"MessageOutput": {
"properties": {
"body": {"type": "string", "title": "Body", "default": ""},

78
tests/test_pydantic_v1_v2_01.py

@ -1,7 +1,7 @@
import sys
from typing import Any, Union
from tests.utils import pydantic_snapshot, skip_module_if_py_gte_314
from tests.utils import skip_module_if_py_gte_314
if sys.version_info >= (3, 14):
skip_module_if_py_gte_314()
@ -225,21 +225,12 @@ def test_openapi_schema():
"requestBody": {
"content": {
"application/json": {
"schema": pydantic_snapshot(
v2=snapshot(
{
"allOf": [
{
"$ref": "#/components/schemas/SubItem"
}
],
"title": "Data",
}
),
v1=snapshot(
"schema": {
"allOf": [
{"$ref": "#/components/schemas/SubItem"}
),
)
],
"title": "Data",
}
}
},
"required": True,
@ -275,21 +266,12 @@ def test_openapi_schema():
"requestBody": {
"content": {
"application/json": {
"schema": pydantic_snapshot(
v2=snapshot(
{
"allOf": [
{
"$ref": "#/components/schemas/SubItem"
}
],
"title": "Data",
}
),
v1=snapshot(
"schema": {
"allOf": [
{"$ref": "#/components/schemas/SubItem"}
),
)
],
"title": "Data",
}
}
},
"required": True,
@ -325,21 +307,12 @@ def test_openapi_schema():
"requestBody": {
"content": {
"application/json": {
"schema": pydantic_snapshot(
v2=snapshot(
{
"allOf": [
{
"$ref": "#/components/schemas/Item"
}
],
"title": "Data",
}
),
v1=snapshot(
"schema": {
"allOf": [
{"$ref": "#/components/schemas/Item"}
),
)
],
"title": "Data",
}
}
},
"required": True,
@ -373,21 +346,12 @@ def test_openapi_schema():
"requestBody": {
"content": {
"application/json": {
"schema": pydantic_snapshot(
v2=snapshot(
{
"allOf": [
{
"$ref": "#/components/schemas/Item"
}
],
"title": "Data",
}
),
v1=snapshot(
"schema": {
"allOf": [
{"$ref": "#/components/schemas/Item"}
),
)
],
"title": "Data",
}
}
},
"required": True,

40
tests/test_pydantic_v1_v2_list.py

@ -1,7 +1,7 @@
import sys
from typing import Any, Union
from tests.utils import pydantic_snapshot, skip_module_if_py_gte_314
from tests.utils import skip_module_if_py_gte_314
if sys.version_info >= (3, 14):
skip_module_if_py_gte_314()
@ -375,21 +375,12 @@ def test_openapi_schema():
"requestBody": {
"content": {
"application/json": {
"schema": pydantic_snapshot(
v2=snapshot(
{
"allOf": [
{
"$ref": "#/components/schemas/Item"
}
],
"title": "Data",
}
),
v1=snapshot(
"schema": {
"allOf": [
{"$ref": "#/components/schemas/Item"}
),
)
],
"title": "Data",
}
}
},
"required": True,
@ -429,21 +420,12 @@ def test_openapi_schema():
"requestBody": {
"content": {
"application/json": {
"schema": pydantic_snapshot(
v2=snapshot(
{
"allOf": [
{
"$ref": "#/components/schemas/Item"
}
],
"title": "Data",
}
),
v1=snapshot(
"schema": {
"allOf": [
{"$ref": "#/components/schemas/Item"}
),
)
],
"title": "Data",
}
}
},
"required": True,

216
tests/test_pydantic_v1_v2_mixed.py

@ -1,7 +1,7 @@
import sys
from typing import Any, Union
from tests.utils import pydantic_snapshot, skip_module_if_py_gte_314
from tests.utils import skip_module_if_py_gte_314
if sys.version_info >= (3, 14):
skip_module_if_py_gte_314()
@ -668,38 +668,20 @@ def test_v2_to_v1_validation_error():
assert response.status_code == 422, response.text
assert response.json() == snapshot(
{
"detail": pydantic_snapshot(
v2=snapshot(
[
{
"type": "missing",
"loc": ["body", "new_size"],
"msg": "Field required",
"input": {"new_title": "Missing fields"},
},
{
"type": "missing",
"loc": ["body", "new_sub"],
"msg": "Field required",
"input": {"new_title": "Missing fields"},
},
]
),
v1=snapshot(
[
{
"loc": ["body", "new_size"],
"msg": "field required",
"type": "value_error.missing",
},
{
"loc": ["body", "new_sub"],
"msg": "field required",
"type": "value_error.missing",
},
]
),
)
"detail": [
{
"type": "missing",
"loc": ["body", "new_size"],
"msg": "Field required",
"input": {"new_title": "Missing fields"},
},
{
"type": "missing",
"loc": ["body", "new_sub"],
"msg": "Field required",
"input": {"new_title": "Missing fields"},
},
]
}
)
@ -717,23 +699,12 @@ def test_v2_to_v1_nested_validation_error():
assert response.json() == snapshot(
{
"detail": [
pydantic_snapshot(
v2=snapshot(
{
"type": "missing",
"loc": ["body", "new_sub", "new_sub_name"],
"msg": "Field required",
"input": {"wrong_field": "value"},
}
),
v1=snapshot(
{
"loc": ["body", "new_sub", "new_sub_name"],
"msg": "field required",
"type": "value_error.missing",
}
),
)
{
"type": "missing",
"loc": ["body", "new_sub", "new_sub_name"],
"msg": "Field required",
"input": {"wrong_field": "value"},
}
]
}
)
@ -777,38 +748,20 @@ def test_v2_list_validation_error():
assert response.status_code == 422, response.text
assert response.json() == snapshot(
{
"detail": pydantic_snapshot(
v2=snapshot(
[
{
"type": "missing",
"loc": ["body", 1, "new_size"],
"msg": "Field required",
"input": {"new_title": "Invalid"},
},
{
"type": "missing",
"loc": ["body", 1, "new_sub"],
"msg": "Field required",
"input": {"new_title": "Invalid"},
},
]
),
v1=snapshot(
[
{
"loc": ["body", 1, "new_size"],
"msg": "field required",
"type": "value_error.missing",
},
{
"loc": ["body", 1, "new_sub"],
"msg": "field required",
"type": "value_error.missing",
},
]
),
)
"detail": [
{
"type": "missing",
"loc": ["body", 1, "new_size"],
"msg": "Field required",
"input": {"new_title": "Invalid"},
},
{
"type": "missing",
"loc": ["body", 1, "new_sub"],
"msg": "Field required",
"input": {"new_title": "Invalid"},
},
]
}
)
@ -844,31 +797,18 @@ def test_invalid_list_structure_v2():
assert response.status_code == 422, response.text
assert response.json() == snapshot(
{
"detail": pydantic_snapshot(
v2=snapshot(
[
{
"type": "list_type",
"loc": ["body"],
"msg": "Input should be a valid list",
"input": {
"new_title": "Not a list",
"new_size": 100,
"new_sub": {"new_sub_name": "Sub"},
},
}
]
),
v1=snapshot(
[
{
"loc": ["body"],
"msg": "value is not a valid list",
"type": "type_error.list",
}
]
),
)
"detail": [
{
"type": "list_type",
"loc": ["body"],
"msg": "Input should be a valid list",
"input": {
"new_title": "Not a list",
"new_size": 100,
"new_sub": {"new_sub_name": "Sub"},
},
}
]
}
)
@ -888,21 +828,12 @@ def test_openapi_schema():
"requestBody": {
"content": {
"application/json": {
"schema": pydantic_snapshot(
v2=snapshot(
{
"allOf": [
{
"$ref": "#/components/schemas/Item"
}
],
"title": "Data",
}
),
v1=snapshot(
"schema": {
"allOf": [
{"$ref": "#/components/schemas/Item"}
),
)
],
"title": "Data",
}
}
},
"required": True,
@ -938,21 +869,12 @@ def test_openapi_schema():
"requestBody": {
"content": {
"application/json": {
"schema": pydantic_snapshot(
v2=snapshot(
{
"allOf": [
{
"$ref": "#/components/schemas/Item"
}
],
"title": "Data",
}
),
v1=snapshot(
"schema": {
"allOf": [
{"$ref": "#/components/schemas/Item"}
),
)
],
"title": "Data",
}
}
},
"required": True,
@ -1056,9 +978,7 @@ def test_openapi_schema():
"requestBody": {
"content": {
"application/json": {
"schema": pydantic_snapshot(
v2=snapshot(
{
"schema": {
"allOf": [
{
"$ref": "#/components/schemas/Item"
@ -1066,11 +986,6 @@ def test_openapi_schema():
],
"title": "Data",
}
),
v1=snapshot(
{"$ref": "#/components/schemas/Item"}
),
)
}
},
"required": True,
@ -1440,17 +1355,10 @@ def test_openapi_schema():
"properties": {
"new_title": {"type": "string", "title": "New Title"},
"new_size": {"type": "integer", "title": "New Size"},
"new_description": pydantic_snapshot(
v2=snapshot(
{
"anyOf": [{"type": "string"}, {"type": "null"}],
"title": "New Description",
}
),
v1=snapshot(
{"type": "string", "title": "New Description"}
),
),
"new_description": {
"anyOf": [{"type": "string"}, {"type": "null"}],
"title": "New Description",
},
"new_sub": {"$ref": "#/components/schemas/NewSubItem"},
"new_multi": {
"items": {"$ref": "#/components/schemas/NewSubItem"},

769
tests/test_pydantic_v1_v2_multifile/test_multifile.py

@ -1,6 +1,6 @@
import sys
from tests.utils import pydantic_snapshot, skip_module_if_py_gte_314
from tests.utils import skip_module_if_py_gte_314
if sys.version_info >= (3, 14):
skip_module_if_py_gte_314()
@ -292,23 +292,14 @@ def test_openapi_schema():
"requestBody": {
"content": {
"application/json": {
"schema": pydantic_snapshot(
v2=snapshot(
{
"allOf": [
{
"$ref": "#/components/schemas/tests__test_pydantic_v1_v2_multifile__modelsv1__Item"
}
],
"title": "Data",
}
),
v1=snapshot(
"schema": {
"allOf": [
{
"$ref": "#/components/schemas/tests__test_pydantic_v1_v2_multifile__modelsv1__Item"
}
),
)
],
"title": "Data",
}
}
},
"required": True,
@ -344,18 +335,9 @@ def test_openapi_schema():
"requestBody": {
"content": {
"application/json": {
"schema": pydantic_snapshot(
v2=snapshot(
{
"$ref": "#/components/schemas/tests__test_pydantic_v1_v2_multifile__modelsv2__Item-Input"
}
),
v1=snapshot(
{
"$ref": "#/components/schemas/tests__test_pydantic_v1_v2_multifile__modelsv2__Item"
}
),
),
"schema": {
"$ref": "#/components/schemas/tests__test_pydantic_v1_v2_multifile__modelsv2__Item-Input"
},
}
},
"required": True,
@ -391,23 +373,14 @@ def test_openapi_schema():
"requestBody": {
"content": {
"application/json": {
"schema": pydantic_snapshot(
v2=snapshot(
{
"allOf": [
{
"$ref": "#/components/schemas/tests__test_pydantic_v1_v2_multifile__modelsv1__Item"
}
],
"title": "Data",
}
),
v1=snapshot(
"schema": {
"allOf": [
{
"$ref": "#/components/schemas/tests__test_pydantic_v1_v2_multifile__modelsv1__Item"
}
),
)
],
"title": "Data",
}
}
},
"required": True,
@ -535,18 +508,9 @@ def test_openapi_schema():
"requestBody": {
"content": {
"application/json": {
"schema": pydantic_snapshot(
v2=snapshot(
{
"$ref": "#/components/schemas/tests__test_pydantic_v1_v2_multifile__modelsv2__Item-Input"
}
),
v1=snapshot(
{
"$ref": "#/components/schemas/tests__test_pydantic_v1_v2_multifile__modelsv2__Item"
}
),
),
"schema": {
"$ref": "#/components/schemas/tests__test_pydantic_v1_v2_multifile__modelsv2__Item-Input"
},
}
},
"required": True,
@ -587,18 +551,9 @@ def test_openapi_schema():
"content": {
"application/json": {
"schema": {
"items": pydantic_snapshot(
v2=snapshot(
{
"$ref": "#/components/schemas/tests__test_pydantic_v1_v2_multifile__modelsv2__Item-Input"
}
),
v1=snapshot(
{
"$ref": "#/components/schemas/tests__test_pydantic_v1_v2_multifile__modelsv2__Item"
}
),
),
"items": {
"$ref": "#/components/schemas/tests__test_pydantic_v1_v2_multifile__modelsv2__Item-Input"
},
"type": "array",
"title": "Data",
}
@ -642,18 +597,9 @@ def test_openapi_schema():
"content": {
"application/json": {
"schema": {
"items": pydantic_snapshot(
v2=snapshot(
{
"$ref": "#/components/schemas/tests__test_pydantic_v1_v2_multifile__modelsv2__Item-Input"
}
),
v1=snapshot(
{
"$ref": "#/components/schemas/tests__test_pydantic_v1_v2_multifile__modelsv2__Item"
}
),
),
"items": {
"$ref": "#/components/schemas/tests__test_pydantic_v1_v2_multifile__modelsv2__Item-Input"
},
"type": "array",
"title": "Data",
}
@ -767,460 +713,239 @@ def test_openapi_schema():
},
},
"components": {
"schemas": pydantic_snapshot(
v1=snapshot(
{
"Body_handle_v2_items_in_list_to_v1_item_in_list_v2_to_v1_list_of_items_to_list_of_items_post": {
"properties": {
"data1": {
"items": {
"$ref": "#/components/schemas/tests__test_pydantic_v1_v2_multifile__modelsv2__ItemInList"
},
"type": "array",
"title": "Data1",
},
"data2": {
"items": {
"$ref": "#/components/schemas/tests__test_pydantic_v1_v2_multifile__modelsv2b__ItemInList"
},
"type": "array",
"title": "Data2",
},
},
"type": "object",
"required": ["data1", "data2"],
"title": "Body_handle_v2_items_in_list_to_v1_item_in_list_v2_to_v1_list_of_items_to_list_of_items_post",
},
"Body_handle_v2_same_name_to_v1_v2_to_v1_same_name_post": {
"properties": {
"item1": {
"$ref": "#/components/schemas/tests__test_pydantic_v1_v2_multifile__modelsv2__Item"
},
"item2": {
"$ref": "#/components/schemas/tests__test_pydantic_v1_v2_multifile__modelsv2b__Item"
},
},
"type": "object",
"required": ["item1", "item2"],
"title": "Body_handle_v2_same_name_to_v1_v2_to_v1_same_name_post",
},
"HTTPValidationError": {
"properties": {
"detail": {
"items": {
"$ref": "#/components/schemas/ValidationError"
},
"type": "array",
"title": "Detail",
}
},
"type": "object",
"title": "HTTPValidationError",
},
"ValidationError": {
"properties": {
"loc": {
"items": {
"anyOf": [
{"type": "string"},
{"type": "integer"},
]
},
"type": "array",
"title": "Location",
},
"msg": {"type": "string", "title": "Message"},
"type": {"type": "string", "title": "Error Type"},
},
"type": "object",
"required": ["loc", "msg", "type"],
"title": "ValidationError",
},
"tests__test_pydantic_v1_v2_multifile__modelsv1__Item": {
"properties": {
"title": {"type": "string", "title": "Title"},
"size": {"type": "integer", "title": "Size"},
"description": {
"type": "string",
"title": "Description",
},
"sub": {
"$ref": "#/components/schemas/tests__test_pydantic_v1_v2_multifile__modelsv1__SubItem"
},
"multi": {
"items": {
"$ref": "#/components/schemas/tests__test_pydantic_v1_v2_multifile__modelsv1__SubItem"
},
"type": "array",
"title": "Multi",
"default": [],
},
},
"type": "object",
"required": ["title", "size", "sub"],
"title": "Item",
},
"tests__test_pydantic_v1_v2_multifile__modelsv1__ItemInList": {
"properties": {
"name1": {"type": "string", "title": "Name1"}
},
"type": "object",
"required": ["name1"],
"title": "ItemInList",
},
"tests__test_pydantic_v1_v2_multifile__modelsv1__SubItem": {
"properties": {
"name": {"type": "string", "title": "Name"}
},
"type": "object",
"required": ["name"],
"title": "SubItem",
},
"tests__test_pydantic_v1_v2_multifile__modelsv2__Item": {
"properties": {
"new_title": {
"type": "string",
"title": "New Title",
},
"new_size": {
"type": "integer",
"title": "New Size",
},
"new_description": {
"type": "string",
"title": "New Description",
},
"new_sub": {
"$ref": "#/components/schemas/tests__test_pydantic_v1_v2_multifile__modelsv2__SubItem"
},
"new_multi": {
"items": {
"$ref": "#/components/schemas/tests__test_pydantic_v1_v2_multifile__modelsv2__SubItem"
},
"type": "array",
"title": "New Multi",
"default": [],
},
},
"type": "object",
"required": ["new_title", "new_size", "new_sub"],
"title": "Item",
},
"tests__test_pydantic_v1_v2_multifile__modelsv2__ItemInList": {
"properties": {
"name2": {"type": "string", "title": "Name2"}
},
"type": "object",
"required": ["name2"],
"title": "ItemInList",
},
"tests__test_pydantic_v1_v2_multifile__modelsv2__SubItem": {
"properties": {
"new_sub_name": {
"type": "string",
"title": "New Sub Name",
}
},
"type": "object",
"required": ["new_sub_name"],
"title": "SubItem",
},
"tests__test_pydantic_v1_v2_multifile__modelsv2b__Item": {
"properties": {
"dup_title": {
"type": "string",
"title": "Dup Title",
},
"dup_size": {
"type": "integer",
"title": "Dup Size",
},
"dup_description": {
"type": "string",
"title": "Dup Description",
},
"dup_sub": {
"$ref": "#/components/schemas/tests__test_pydantic_v1_v2_multifile__modelsv2b__SubItem"
},
"dup_multi": {
"items": {
"$ref": "#/components/schemas/tests__test_pydantic_v1_v2_multifile__modelsv2b__SubItem"
},
"type": "array",
"title": "Dup Multi",
"default": [],
},
"schemas": {
"Body_handle_v2_items_in_list_to_v1_item_in_list_v2_to_v1_list_of_items_to_list_of_items_post": {
"properties": {
"data1": {
"items": {
"$ref": "#/components/schemas/tests__test_pydantic_v1_v2_multifile__modelsv2__ItemInList"
},
"type": "object",
"required": ["dup_title", "dup_size", "dup_sub"],
"title": "Item",
"type": "array",
"title": "Data1",
},
"tests__test_pydantic_v1_v2_multifile__modelsv2b__ItemInList": {
"properties": {
"dup_name2": {
"type": "string",
"title": "Dup Name2",
}
},
"type": "object",
"required": ["dup_name2"],
"title": "ItemInList",
},
"tests__test_pydantic_v1_v2_multifile__modelsv2b__SubItem": {
"properties": {
"dup_sub_name": {
"type": "string",
"title": "Dup Sub Name",
}
},
"type": "object",
"required": ["dup_sub_name"],
"title": "SubItem",
},
}
),
v2=snapshot(
{
"Body_handle_v2_items_in_list_to_v1_item_in_list_v2_to_v1_list_of_items_to_list_of_items_post": {
"properties": {
"data1": {
"items": {
"$ref": "#/components/schemas/tests__test_pydantic_v1_v2_multifile__modelsv2__ItemInList"
},
"type": "array",
"title": "Data1",
},
"data2": {
"items": {
"$ref": "#/components/schemas/tests__test_pydantic_v1_v2_multifile__modelsv2b__ItemInList"
},
"type": "array",
"title": "Data2",
},
},
"type": "object",
"required": ["data1", "data2"],
"title": "Body_handle_v2_items_in_list_to_v1_item_in_list_v2_to_v1_list_of_items_to_list_of_items_post",
},
"Body_handle_v2_same_name_to_v1_v2_to_v1_same_name_post": {
"properties": {
"item1": {
"$ref": "#/components/schemas/tests__test_pydantic_v1_v2_multifile__modelsv2__Item-Input"
},
"item2": {
"$ref": "#/components/schemas/tests__test_pydantic_v1_v2_multifile__modelsv2b__Item"
},
},
"type": "object",
"required": ["item1", "item2"],
"title": "Body_handle_v2_same_name_to_v1_v2_to_v1_same_name_post",
},
"HTTPValidationError": {
"properties": {
"detail": {
"items": {
"$ref": "#/components/schemas/ValidationError"
},
"type": "array",
"title": "Detail",
}
},
"type": "object",
"title": "HTTPValidationError",
},
"ValidationError": {
"properties": {
"loc": {
"items": {
"anyOf": [
{"type": "string"},
{"type": "integer"},
]
},
"type": "array",
"title": "Location",
},
"msg": {"type": "string", "title": "Message"},
"type": {"type": "string", "title": "Error Type"},
"data2": {
"items": {
"$ref": "#/components/schemas/tests__test_pydantic_v1_v2_multifile__modelsv2b__ItemInList"
},
"type": "object",
"required": ["loc", "msg", "type"],
"title": "ValidationError",
"type": "array",
"title": "Data2",
},
"tests__test_pydantic_v1_v2_multifile__modelsv1__Item": {
"properties": {
"title": {"type": "string", "title": "Title"},
"size": {"type": "integer", "title": "Size"},
"description": {
"type": "string",
"title": "Description",
},
"sub": {
"$ref": "#/components/schemas/tests__test_pydantic_v1_v2_multifile__modelsv1__SubItem"
},
"multi": {
"items": {
"$ref": "#/components/schemas/tests__test_pydantic_v1_v2_multifile__modelsv1__SubItem"
},
"type": "array",
"title": "Multi",
"default": [],
},
},
"type": "object",
"required": ["title", "size", "sub"],
"title": "Item",
},
"tests__test_pydantic_v1_v2_multifile__modelsv1__ItemInList": {
"properties": {
"name1": {"type": "string", "title": "Name1"}
},
"type": "object",
"required": ["name1"],
"title": "ItemInList",
},
"tests__test_pydantic_v1_v2_multifile__modelsv1__SubItem": {
"properties": {
"name": {"type": "string", "title": "Name"}
},
"type": "object",
"required": ["name"],
"title": "SubItem",
},
"tests__test_pydantic_v1_v2_multifile__modelsv2__Item": {
"properties": {
"new_title": {
"type": "string",
"title": "New Title",
},
"new_size": {
"type": "integer",
"title": "New Size",
},
"new_description": {
"anyOf": [{"type": "string"}, {"type": "null"}],
"title": "New Description",
},
"new_sub": {
"$ref": "#/components/schemas/tests__test_pydantic_v1_v2_multifile__modelsv2__SubItem"
},
"new_multi": {
"items": {
"$ref": "#/components/schemas/tests__test_pydantic_v1_v2_multifile__modelsv2__SubItem"
},
"type": "array",
"title": "New Multi",
"default": [],
},
},
"type": "object",
"required": ["new_title", "new_size", "new_sub"],
"title": "Item",
},
"tests__test_pydantic_v1_v2_multifile__modelsv2__Item-Input": {
"properties": {
"new_title": {
"type": "string",
"title": "New Title",
},
"new_size": {
"type": "integer",
"title": "New Size",
},
"new_description": {
"anyOf": [{"type": "string"}, {"type": "null"}],
"title": "New Description",
},
"new_sub": {
"$ref": "#/components/schemas/tests__test_pydantic_v1_v2_multifile__modelsv2__SubItem"
},
"new_multi": {
"items": {
"$ref": "#/components/schemas/tests__test_pydantic_v1_v2_multifile__modelsv2__SubItem"
},
"type": "array",
"title": "New Multi",
"default": [],
},
},
"type": "object",
"required": ["new_title", "new_size", "new_sub"],
"title": "Item",
},
"tests__test_pydantic_v1_v2_multifile__modelsv2__ItemInList": {
"properties": {
"name2": {"type": "string", "title": "Name2"}
},
"type": "object",
"required": ["name2"],
"title": "ItemInList",
},
"type": "object",
"required": ["data1", "data2"],
"title": "Body_handle_v2_items_in_list_to_v1_item_in_list_v2_to_v1_list_of_items_to_list_of_items_post",
},
"Body_handle_v2_same_name_to_v1_v2_to_v1_same_name_post": {
"properties": {
"item1": {
"$ref": "#/components/schemas/tests__test_pydantic_v1_v2_multifile__modelsv2__Item-Input"
},
"item2": {
"$ref": "#/components/schemas/tests__test_pydantic_v1_v2_multifile__modelsv2b__Item"
},
"tests__test_pydantic_v1_v2_multifile__modelsv2__SubItem": {
"properties": {
"new_sub_name": {
"type": "string",
"title": "New Sub Name",
}
},
"type": "object",
"required": ["new_sub_name"],
"title": "SubItem",
},
"type": "object",
"required": ["item1", "item2"],
"title": "Body_handle_v2_same_name_to_v1_v2_to_v1_same_name_post",
},
"HTTPValidationError": {
"properties": {
"detail": {
"items": {
"$ref": "#/components/schemas/ValidationError"
},
"type": "array",
"title": "Detail",
}
},
"type": "object",
"title": "HTTPValidationError",
},
"ValidationError": {
"properties": {
"loc": {
"items": {
"anyOf": [
{"type": "string"},
{"type": "integer"},
]
},
"type": "array",
"title": "Location",
},
"msg": {"type": "string", "title": "Message"},
"type": {"type": "string", "title": "Error Type"},
},
"type": "object",
"required": ["loc", "msg", "type"],
"title": "ValidationError",
},
"tests__test_pydantic_v1_v2_multifile__modelsv1__Item": {
"properties": {
"title": {"type": "string", "title": "Title"},
"size": {"type": "integer", "title": "Size"},
"description": {
"type": "string",
"title": "Description",
},
"sub": {
"$ref": "#/components/schemas/tests__test_pydantic_v1_v2_multifile__modelsv1__SubItem"
},
"multi": {
"items": {
"$ref": "#/components/schemas/tests__test_pydantic_v1_v2_multifile__modelsv1__SubItem"
},
"type": "array",
"title": "Multi",
"default": [],
},
"tests__test_pydantic_v1_v2_multifile__modelsv2b__Item": {
"properties": {
"dup_title": {
"type": "string",
"title": "Dup Title",
},
"dup_size": {
"type": "integer",
"title": "Dup Size",
},
"dup_description": {
"anyOf": [{"type": "string"}, {"type": "null"}],
"title": "Dup Description",
},
"dup_sub": {
"$ref": "#/components/schemas/tests__test_pydantic_v1_v2_multifile__modelsv2b__SubItem"
},
"dup_multi": {
"items": {
"$ref": "#/components/schemas/tests__test_pydantic_v1_v2_multifile__modelsv2b__SubItem"
},
"type": "array",
"title": "Dup Multi",
"default": [],
},
},
"type": "object",
"required": ["dup_title", "dup_size", "dup_sub"],
"title": "Item",
},
"type": "object",
"required": ["title", "size", "sub"],
"title": "Item",
},
"tests__test_pydantic_v1_v2_multifile__modelsv1__ItemInList": {
"properties": {"name1": {"type": "string", "title": "Name1"}},
"type": "object",
"required": ["name1"],
"title": "ItemInList",
},
"tests__test_pydantic_v1_v2_multifile__modelsv1__SubItem": {
"properties": {"name": {"type": "string", "title": "Name"}},
"type": "object",
"required": ["name"],
"title": "SubItem",
},
"tests__test_pydantic_v1_v2_multifile__modelsv2__Item": {
"properties": {
"new_title": {
"type": "string",
"title": "New Title",
},
"new_size": {
"type": "integer",
"title": "New Size",
},
"new_description": {
"anyOf": [{"type": "string"}, {"type": "null"}],
"title": "New Description",
},
"new_sub": {
"$ref": "#/components/schemas/tests__test_pydantic_v1_v2_multifile__modelsv2__SubItem"
},
"new_multi": {
"items": {
"$ref": "#/components/schemas/tests__test_pydantic_v1_v2_multifile__modelsv2__SubItem"
},
"type": "array",
"title": "New Multi",
"default": [],
},
"tests__test_pydantic_v1_v2_multifile__modelsv2b__ItemInList": {
"properties": {
"dup_name2": {
"type": "string",
"title": "Dup Name2",
}
},
"type": "object",
"required": ["dup_name2"],
"title": "ItemInList",
},
"type": "object",
"required": ["new_title", "new_size", "new_sub"],
"title": "Item",
},
"tests__test_pydantic_v1_v2_multifile__modelsv2__Item-Input": {
"properties": {
"new_title": {
"type": "string",
"title": "New Title",
},
"new_size": {
"type": "integer",
"title": "New Size",
},
"new_description": {
"anyOf": [{"type": "string"}, {"type": "null"}],
"title": "New Description",
},
"new_sub": {
"$ref": "#/components/schemas/tests__test_pydantic_v1_v2_multifile__modelsv2__SubItem"
},
"new_multi": {
"items": {
"$ref": "#/components/schemas/tests__test_pydantic_v1_v2_multifile__modelsv2__SubItem"
},
"type": "array",
"title": "New Multi",
"default": [],
},
"tests__test_pydantic_v1_v2_multifile__modelsv2b__SubItem": {
"properties": {
"dup_sub_name": {
"type": "string",
"title": "Dup Sub Name",
}
},
"type": "object",
"required": ["dup_sub_name"],
"title": "SubItem",
},
"type": "object",
"required": ["new_title", "new_size", "new_sub"],
"title": "Item",
},
"tests__test_pydantic_v1_v2_multifile__modelsv2__ItemInList": {
"properties": {"name2": {"type": "string", "title": "Name2"}},
"type": "object",
"required": ["name2"],
"title": "ItemInList",
},
"tests__test_pydantic_v1_v2_multifile__modelsv2__SubItem": {
"properties": {
"new_sub_name": {
"type": "string",
"title": "New Sub Name",
}
},
"type": "object",
"required": ["new_sub_name"],
"title": "SubItem",
},
"tests__test_pydantic_v1_v2_multifile__modelsv2b__Item": {
"properties": {
"dup_title": {
"type": "string",
"title": "Dup Title",
},
"dup_size": {
"type": "integer",
"title": "Dup Size",
},
"dup_description": {
"anyOf": [{"type": "string"}, {"type": "null"}],
"title": "Dup Description",
},
"dup_sub": {
"$ref": "#/components/schemas/tests__test_pydantic_v1_v2_multifile__modelsv2b__SubItem"
},
"dup_multi": {
"items": {
"$ref": "#/components/schemas/tests__test_pydantic_v1_v2_multifile__modelsv2b__SubItem"
},
"type": "array",
"title": "Dup Multi",
"default": [],
},
}
),
),
},
"type": "object",
"required": ["dup_title", "dup_size", "dup_sub"],
"title": "Item",
},
"tests__test_pydantic_v1_v2_multifile__modelsv2b__ItemInList": {
"properties": {
"dup_name2": {
"type": "string",
"title": "Dup Name2",
}
},
"type": "object",
"required": ["dup_name2"],
"title": "ItemInList",
},
"tests__test_pydantic_v1_v2_multifile__modelsv2b__SubItem": {
"properties": {
"dup_sub_name": {
"type": "string",
"title": "Dup Sub Name",
}
},
"type": "object",
"required": ["dup_sub_name"],
"title": "SubItem",
},
},
},
}
)

169
tests/test_pydantic_v1_v2_noneable.py

@ -1,7 +1,7 @@
import sys
from typing import Any, Union
from tests.utils import pydantic_snapshot, skip_module_if_py_gte_314
from tests.utils import skip_module_if_py_gte_314
if sys.version_info >= (3, 14):
skip_module_if_py_gte_314()
@ -312,38 +312,20 @@ def test_v2_to_v1_validation_error():
assert response.status_code == 422, response.text
assert response.json() == snapshot(
{
"detail": pydantic_snapshot(
v2=snapshot(
[
{
"type": "missing",
"loc": ["body", "new_size"],
"msg": "Field required",
"input": {"new_title": "Missing fields"},
},
{
"type": "missing",
"loc": ["body", "new_sub"],
"msg": "Field required",
"input": {"new_title": "Missing fields"},
},
]
),
v1=snapshot(
[
{
"loc": ["body", "new_size"],
"msg": "field required",
"type": "value_error.missing",
},
{
"loc": ["body", "new_sub"],
"msg": "field required",
"type": "value_error.missing",
},
]
),
)
"detail": [
{
"type": "missing",
"loc": ["body", "new_size"],
"msg": "Field required",
"input": {"new_title": "Missing fields"},
},
{
"type": "missing",
"loc": ["body", "new_sub"],
"msg": "Field required",
"input": {"new_title": "Missing fields"},
},
]
}
)
@ -361,23 +343,12 @@ def test_v2_to_v1_nested_validation_error():
assert response.json() == snapshot(
{
"detail": [
pydantic_snapshot(
v2=snapshot(
{
{
"type": "missing",
"loc": ["body", "new_sub", "new_sub_name"],
"msg": "Field required",
"input": {"wrong_field": "value"},
}
),
v1=snapshot(
{
"loc": ["body", "new_sub", "new_sub_name"],
"msg": "field required",
"type": "value_error.missing",
}
),
)
]
}
)
@ -396,23 +367,12 @@ def test_v2_to_v1_type_validation_error():
assert response.json() == snapshot(
{
"detail": [
pydantic_snapshot(
v2=snapshot(
{
"type": "int_parsing",
"loc": ["body", "new_size"],
"msg": "Input should be a valid integer, unable to parse string as an integer",
"input": "not_a_number",
}
),
v1=snapshot(
{
"loc": ["body", "new_size"],
"msg": "value is not a valid integer",
"type": "type_error.integer",
}
),
)
{
"type": "int_parsing",
"loc": ["body", "new_size"],
"msg": "Input should be a valid integer, unable to parse string as an integer",
"input": "not_a_number",
}
]
}
)
@ -483,9 +443,7 @@ def test_openapi_schema():
"requestBody": {
"content": {
"application/json": {
"schema": pydantic_snapshot(
v2=snapshot(
{
"schema": {
"allOf": [
{
"$ref": "#/components/schemas/Item"
@ -493,11 +451,6 @@ def test_openapi_schema():
],
"title": "Data",
}
),
v1=snapshot(
{"$ref": "#/components/schemas/Item"}
),
)
}
},
"required": True,
@ -507,22 +460,15 @@ def test_openapi_schema():
"description": "Successful Response",
"content": {
"application/json": {
"schema": pydantic_snapshot(
v2=snapshot(
"schema": {
"anyOf": [
{
"anyOf": [
{
"$ref": "#/components/schemas/NewItem"
},
{"type": "null"},
],
"title": "Response Handle V1 Item To V2 V1 To V2 Post",
}
),
v1=snapshot(
{"$ref": "#/components/schemas/NewItem"}
),
)
"$ref": "#/components/schemas/NewItem"
},
{"type": "null"},
],
"title": "Response Handle V1 Item To V2 V1 To V2 Post",
}
}
},
},
@ -546,21 +492,12 @@ def test_openapi_schema():
"requestBody": {
"content": {
"application/json": {
"schema": pydantic_snapshot(
v2=snapshot(
{
"allOf": [
{
"$ref": "#/components/schemas/Item"
}
],
"title": "Data",
}
),
v1=snapshot(
"schema": {
"allOf": [
{"$ref": "#/components/schemas/Item"}
),
)
],
"title": "Data",
}
}
},
"required": True,
@ -570,22 +507,15 @@ def test_openapi_schema():
"description": "Successful Response",
"content": {
"application/json": {
"schema": pydantic_snapshot(
v2=snapshot(
"schema": {
"anyOf": [
{
"anyOf": [
{
"$ref": "#/components/schemas/NewItem"
},
{"type": "null"},
],
"title": "Response Handle V1 Item To V2 Filter V1 To V2 Item Filter Post",
}
),
v1=snapshot(
{"$ref": "#/components/schemas/NewItem"}
),
)
"$ref": "#/components/schemas/NewItem"
},
{"type": "null"},
],
"title": "Response Handle V1 Item To V2 Filter V1 To V2 Item Filter Post",
}
}
},
},
@ -707,17 +637,10 @@ def test_openapi_schema():
"properties": {
"new_title": {"type": "string", "title": "New Title"},
"new_size": {"type": "integer", "title": "New Size"},
"new_description": pydantic_snapshot(
v2=snapshot(
{
"new_description": {
"anyOf": [{"type": "string"}, {"type": "null"}],
"title": "New Description",
}
),
v1=snapshot(
{"type": "string", "title": "New Description"}
),
),
},
"new_sub": {"$ref": "#/components/schemas/NewSubItem"},
"new_multi": {
"items": {"$ref": "#/components/schemas/NewSubItem"},

57
tests/test_tutorial/test_cookie_param_models/test_tutorial002.py

@ -8,7 +8,6 @@ from inline_snapshot import snapshot
from tests.utils import (
needs_py310,
needs_pydanticv2,
pydantic_snapshot,
)
@ -57,31 +56,16 @@ def test_cookie_param_model_defaults(client: TestClient):
def test_cookie_param_model_invalid(client: TestClient):
response = client.get("/items/")
assert response.status_code == 422
assert response.json() == pydantic_snapshot(
v2=snapshot(
assert response.json() == {
"detail": [
{
"detail": [
{
"type": "missing",
"loc": ["cookie", "session_id"],
"msg": "Field required",
"input": {},
}
]
"type": "missing",
"loc": ["cookie", "session_id"],
"msg": "Field required",
"input": {},
}
),
v1=snapshot(
{
"detail": [
{
"type": "value_error.missing",
"loc": ["cookie", "session_id"],
"msg": "field required",
}
]
}
),
)
]
}
def test_cookie_param_model_extra(client: TestClient):
@ -141,24 +125,13 @@ def test_openapi_schema(client: TestClient):
"name": "fatebook_tracker",
"in": "cookie",
"required": False,
"schema": pydantic_snapshot(
v2=snapshot(
{
"anyOf": [
{"type": "string"},
{"type": "null"},
],
"title": "Fatebook Tracker",
}
),
v1=snapshot(
# TODO: remove when deprecating Pydantic v1
{
"type": "string",
"title": "Fatebook Tracker",
}
),
),
"schema": {
"anyOf": [
{"type": "string"},
{"type": "null"},
],
"title": "Fatebook Tracker",
},
},
{
"name": "googall_tracker",

23
tests/utils.py

@ -2,7 +2,6 @@ import sys
import pytest
from fastapi._compat import PYDANTIC_V2
from inline_snapshot import Snapshot
needs_py39 = pytest.mark.skipif(sys.version_info < (3, 9), reason="requires python3.9+")
needs_py310 = pytest.mark.skipif(
@ -19,25 +18,3 @@ def skip_module_if_py_gte_314():
"""Skip entire module on Python 3.14+ at import time."""
if sys.version_info >= (3, 14):
pytest.skip("requires python3.13-", allow_module_level=True)
def pydantic_snapshot(
*,
v2: Snapshot,
v1: Snapshot, # TODO: remove v1 argument when deprecating Pydantic v1
):
"""
This function should be used like this:
>>> assert value == pydantic_snapshot(v2=snapshot(),v1=snapshot())
inline-snapshot will create the snapshots when pytest is executed for each versions of pydantic.
It is also possible to use the function inside snapshots for version-specific values.
>>> assert value == snapshot({
"data": "some data",
"version_specific": pydantic_snapshot(v2=snapshot(),v1=snapshot()),
})
"""
return v2 if PYDANTIC_V2 else v1

Loading…
Cancel
Save