🔥 Remove Pydantic v1 specific test variants (#14611)

This commit is contained in:
Sebastián Ramírez 2025-12-27 10:19:10 -08:00 committed by GitHub
parent 8322a4445a
commit 44c849c4fc
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
104 changed files with 4139 additions and 8074 deletions

View File

@ -1,6 +1,5 @@
from typing import Union from typing import Union
from dirty_equals import IsDict
from fastapi import FastAPI from fastapi import FastAPI
from fastapi.testclient import TestClient from fastapi.testclient import TestClient
from pydantic import BaseModel, ConfigDict from pydantic import BaseModel, ConfigDict
@ -52,19 +51,13 @@ def test_openapi_schema():
"requestBody": { "requestBody": {
"content": { "content": {
"application/json": { "application/json": {
"schema": IsDict( "schema": {
{ "anyOf": [
"anyOf": [ {"$ref": "#/components/schemas/Foo"},
{"$ref": "#/components/schemas/Foo"}, {"type": "null"},
{"type": "null"}, ],
], "title": "Foo",
"title": "Foo", }
}
)
| IsDict(
# TODO: remove when deprecating Pydantic v1
{"$ref": "#/components/schemas/Foo"}
)
} }
} }
}, },

View File

@ -1,6 +1,6 @@
from dirty_equals import IsDict
from fastapi import APIRouter, FastAPI from fastapi import APIRouter, FastAPI
from fastapi.testclient import TestClient from fastapi.testclient import TestClient
from inline_snapshot import snapshot
from pydantic import BaseModel, HttpUrl from pydantic import BaseModel, HttpUrl
from starlette.responses import JSONResponse from starlette.responses import JSONResponse
@ -32,121 +32,114 @@ client = TestClient(app)
def test_openapi_schema(): def test_openapi_schema():
response = client.get("/openapi.json") response = client.get("/openapi.json")
assert response.status_code == 200, response.text assert response.status_code == 200, response.text
assert response.json() == { assert response.json() == snapshot(
"openapi": "3.1.0", {
"info": {"title": "FastAPI", "version": "0.1.0"}, "openapi": "3.1.0",
"paths": { "info": {"title": "FastAPI", "version": "0.1.0"},
"/": { "paths": {
"post": { "/": {
"summary": "Main Route", "post": {
"operationId": "main_route__post", "summary": "Main Route",
"parameters": [ "operationId": "main_route__post",
{ "parameters": [
"required": True, {
"schema": IsDict( "required": True,
{ "schema": {
"title": "Callback Url",
"minLength": 1,
"type": "string",
"format": "uri",
}
)
# TODO: remove when deprecating Pydantic v1
| IsDict(
{
"title": "Callback Url", "title": "Callback Url",
"maxLength": 2083, "maxLength": 2083,
"minLength": 1, "minLength": 1,
"type": "string", "type": "string",
"format": "uri", "format": "uri",
} },
), "name": "callback_url",
"name": "callback_url", "in": "query",
"in": "query", }
} ],
], "responses": {
"responses": { "200": {
"200": { "description": "Successful Response",
"description": "Successful Response", "content": {"application/json": {"schema": {}}},
"content": {"application/json": {"schema": {}}}, },
"422": {
"description": "Validation Error",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/HTTPValidationError"
}
}
},
},
}, },
"422": { "callbacks": {
"description": "Validation Error", "callback_route": {
"content": { "{$callback_url}/callback/": {
"application/json": { "get": {
"schema": { "summary": "Callback Route",
"$ref": "#/components/schemas/HTTPValidationError" "operationId": "callback_route__callback_url__callback__get",
"responses": {
"400": {
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/CustomModel"
}
}
},
"description": "Bad Request",
},
"200": {
"description": "Successful Response",
"content": {
"application/json": {"schema": {}}
},
},
},
} }
} }
}, }
},
}
}
},
"components": {
"schemas": {
"CustomModel": {
"title": "CustomModel",
"required": ["a"],
"type": "object",
"properties": {"a": {"title": "A", "type": "integer"}},
},
"HTTPValidationError": {
"title": "HTTPValidationError",
"type": "object",
"properties": {
"detail": {
"title": "Detail",
"type": "array",
"items": {
"$ref": "#/components/schemas/ValidationError"
},
}
}, },
}, },
"callbacks": { "ValidationError": {
"callback_route": { "title": "ValidationError",
"{$callback_url}/callback/": { "required": ["loc", "msg", "type"],
"get": { "type": "object",
"summary": "Callback Route", "properties": {
"operationId": "callback_route__callback_url__callback__get", "loc": {
"responses": { "title": "Location",
"400": { "type": "array",
"content": { "items": {
"application/json": { "anyOf": [{"type": "string"}, {"type": "integer"}]
"schema": { },
"$ref": "#/components/schemas/CustomModel" },
} "msg": {"title": "Message", "type": "string"},
} "type": {"title": "Error Type", "type": "string"},
}, },
"description": "Bad Request",
},
"200": {
"description": "Successful Response",
"content": {
"application/json": {"schema": {}}
},
},
},
}
}
}
}, },
} }
} },
}, }
"components": { )
"schemas": {
"CustomModel": {
"title": "CustomModel",
"required": ["a"],
"type": "object",
"properties": {"a": {"title": "A", "type": "integer"}},
},
"HTTPValidationError": {
"title": "HTTPValidationError",
"type": "object",
"properties": {
"detail": {
"title": "Detail",
"type": "array",
"items": {"$ref": "#/components/schemas/ValidationError"},
}
},
},
"ValidationError": {
"title": "ValidationError",
"required": ["loc", "msg", "type"],
"type": "object",
"properties": {
"loc": {
"title": "Location",
"type": "array",
"items": {
"anyOf": [{"type": "string"}, {"type": "integer"}]
},
},
"msg": {"title": "Message", "type": "string"},
"type": {"title": "Error Type", "type": "string"},
},
},
}
},
}

View File

@ -1,7 +1,6 @@
from typing import Annotated from typing import Annotated
import pytest import pytest
from dirty_equals import IsDict
from fastapi import APIRouter, FastAPI, Query from fastapi import APIRouter, FastAPI, Query
from fastapi.testclient import TestClient from fastapi.testclient import TestClient
@ -32,44 +31,23 @@ client = TestClient(app)
foo_is_missing = { foo_is_missing = {
"detail": [ "detail": [
IsDict( {
{ "loc": ["query", "foo"],
"loc": ["query", "foo"], "msg": "Field required",
"msg": "Field required", "type": "missing",
"type": "missing", "input": None,
"input": None, }
}
)
# TODO: remove when deprecating Pydantic v1
| IsDict(
{
"loc": ["query", "foo"],
"msg": "field required",
"type": "value_error.missing",
}
)
] ]
} }
foo_is_short = { foo_is_short = {
"detail": [ "detail": [
IsDict( {
{ "ctx": {"min_length": 1},
"ctx": {"min_length": 1}, "loc": ["query", "foo"],
"loc": ["query", "foo"], "msg": "String should have at least 1 character",
"msg": "String should have at least 1 character", "type": "string_too_short",
"type": "string_too_short", "input": "",
"input": "", }
}
)
# TODO: remove when deprecating Pydantic v1
| IsDict(
{
"ctx": {"limit_value": 1},
"loc": ["query", "foo"],
"msg": "ensure this value has at least 1 characters",
"type": "value_error.any_str.min_length",
}
)
] ]
} }

View File

@ -1,5 +1,4 @@
import pytest import pytest
from dirty_equals import IsDict
from fastapi.testclient import TestClient from fastapi.testclient import TestClient
from .main import app from .main import app
@ -274,14 +273,10 @@ def test_openapi_schema():
"name": "item_id", "name": "item_id",
"in": "path", "in": "path",
"required": True, "required": True,
"schema": IsDict( "schema": {
{ "anyOf": [{"type": "string"}, {"type": "null"}],
"anyOf": [{"type": "string"}, {"type": "null"}], "title": "Item Id",
"title": "Item Id", },
}
)
# TODO: remove when deprecating Pydantic v1
| IsDict({"title": "Item Id", "type": "string"}),
} }
], ],
} }
@ -984,14 +979,10 @@ def test_openapi_schema():
"name": "query", "name": "query",
"in": "query", "in": "query",
"required": False, "required": False,
"schema": IsDict( "schema": {
{ "anyOf": [{"type": "integer"}, {"type": "null"}],
"anyOf": [{"type": "integer"}, {"type": "null"}], "title": "Query",
"title": "Query", },
}
)
# TODO: remove when deprecating Pydantic v1
| IsDict({"title": "Query", "type": "integer"}),
} }
], ],
} }

View File

@ -1,4 +1,3 @@
from dirty_equals import IsDict
from fastapi import Depends, FastAPI from fastapi import Depends, FastAPI
from fastapi.testclient import TestClient from fastapi.testclient import TestClient
from pydantic import BaseModel from pydantic import BaseModel
@ -46,29 +45,16 @@ async def no_duplicates_sub(
def test_no_duplicates_invalid(): def test_no_duplicates_invalid():
response = client.post("/no-duplicates", json={"item": {"data": "myitem"}}) response = client.post("/no-duplicates", json={"item": {"data": "myitem"}})
assert response.status_code == 422, response.text assert response.status_code == 422, response.text
assert response.json() == IsDict( assert response.json() == {
{ "detail": [
"detail": [ {
{ "type": "missing",
"type": "missing", "loc": ["body", "item2"],
"loc": ["body", "item2"], "msg": "Field required",
"msg": "Field required", "input": None,
"input": None, }
} ]
] }
}
) | IsDict(
# TODO: remove when deprecating Pydantic v1
{
"detail": [
{
"loc": ["body", "item2"],
"msg": "field required",
"type": "value_error.missing",
}
]
}
)
def test_no_duplicates(): def test_no_duplicates():

View File

@ -1,7 +1,6 @@
from typing import Optional from typing import Optional
import pytest import pytest
from dirty_equals import IsDict
from fastapi import APIRouter, Depends, FastAPI from fastapi import APIRouter, Depends, FastAPI
from fastapi.testclient import TestClient from fastapi.testclient import TestClient
@ -54,29 +53,16 @@ async def overrider_dependency_with_sub(msg: dict = Depends(overrider_sub_depend
def test_main_depends(): def test_main_depends():
response = client.get("/main-depends/") response = client.get("/main-depends/")
assert response.status_code == 422 assert response.status_code == 422
assert response.json() == IsDict( assert response.json() == {
{ "detail": [
"detail": [ {
{ "type": "missing",
"type": "missing", "loc": ["query", "q"],
"loc": ["query", "q"], "msg": "Field required",
"msg": "Field required", "input": None,
"input": None, }
} ]
] }
}
) | IsDict(
# TODO: remove when deprecating Pydantic v1
{
"detail": [
{
"loc": ["query", "q"],
"msg": "field required",
"type": "value_error.missing",
}
]
}
)
def test_main_depends_q_foo(): def test_main_depends_q_foo():
@ -100,29 +86,16 @@ def test_main_depends_q_foo_skip_100_limit_200():
def test_decorator_depends(): def test_decorator_depends():
response = client.get("/decorator-depends/") response = client.get("/decorator-depends/")
assert response.status_code == 422 assert response.status_code == 422
assert response.json() == IsDict( assert response.json() == {
{ "detail": [
"detail": [ {
{ "type": "missing",
"type": "missing", "loc": ["query", "q"],
"loc": ["query", "q"], "msg": "Field required",
"msg": "Field required", "input": None,
"input": None, }
} ]
] }
}
) | IsDict(
# TODO: remove when deprecating Pydantic v1
{
"detail": [
{
"loc": ["query", "q"],
"msg": "field required",
"type": "value_error.missing",
}
]
}
)
def test_decorator_depends_q_foo(): def test_decorator_depends_q_foo():
@ -140,29 +113,16 @@ def test_decorator_depends_q_foo_skip_100_limit_200():
def test_router_depends(): def test_router_depends():
response = client.get("/router-depends/") response = client.get("/router-depends/")
assert response.status_code == 422 assert response.status_code == 422
assert response.json() == IsDict( assert response.json() == {
{ "detail": [
"detail": [ {
{ "type": "missing",
"type": "missing", "loc": ["query", "q"],
"loc": ["query", "q"], "msg": "Field required",
"msg": "Field required", "input": None,
"input": None, }
} ]
] }
}
) | IsDict(
# TODO: remove when deprecating Pydantic v1
{
"detail": [
{
"loc": ["query", "q"],
"msg": "field required",
"type": "value_error.missing",
}
]
}
)
def test_router_depends_q_foo(): def test_router_depends_q_foo():
@ -186,29 +146,16 @@ def test_router_depends_q_foo_skip_100_limit_200():
def test_router_decorator_depends(): def test_router_decorator_depends():
response = client.get("/router-decorator-depends/") response = client.get("/router-decorator-depends/")
assert response.status_code == 422 assert response.status_code == 422
assert response.json() == IsDict( assert response.json() == {
{ "detail": [
"detail": [ {
{ "type": "missing",
"type": "missing", "loc": ["query", "q"],
"loc": ["query", "q"], "msg": "Field required",
"msg": "Field required", "input": None,
"input": None, }
} ]
] }
}
) | IsDict(
# TODO remove when deprecating Pydantic v1
{
"detail": [
{
"loc": ["query", "q"],
"msg": "field required",
"type": "value_error.missing",
}
]
}
)
def test_router_decorator_depends_q_foo(): def test_router_decorator_depends_q_foo():
@ -272,29 +219,17 @@ def test_override_with_sub_main_depends():
app.dependency_overrides[common_parameters] = overrider_dependency_with_sub app.dependency_overrides[common_parameters] = overrider_dependency_with_sub
response = client.get("/main-depends/") response = client.get("/main-depends/")
assert response.status_code == 422 assert response.status_code == 422
assert response.json() == IsDict( assert response.json() == {
{ "detail": [
"detail": [ {
{ "type": "missing",
"type": "missing", "loc": ["query", "k"],
"loc": ["query", "k"], "msg": "Field required",
"msg": "Field required", "input": None,
"input": None, }
} ]
] }
}
) | IsDict(
# TODO: remove when deprecating Pydantic v1
{
"detail": [
{
"loc": ["query", "k"],
"msg": "field required",
"type": "value_error.missing",
}
]
}
)
app.dependency_overrides = {} app.dependency_overrides = {}
@ -302,29 +237,17 @@ def test_override_with_sub__main_depends_q_foo():
app.dependency_overrides[common_parameters] = overrider_dependency_with_sub app.dependency_overrides[common_parameters] = overrider_dependency_with_sub
response = client.get("/main-depends/?q=foo") response = client.get("/main-depends/?q=foo")
assert response.status_code == 422 assert response.status_code == 422
assert response.json() == IsDict( assert response.json() == {
{ "detail": [
"detail": [ {
{ "type": "missing",
"type": "missing", "loc": ["query", "k"],
"loc": ["query", "k"], "msg": "Field required",
"msg": "Field required", "input": None,
"input": None, }
} ]
] }
}
) | IsDict(
# TODO: remove when deprecating Pydantic v1
{
"detail": [
{
"loc": ["query", "k"],
"msg": "field required",
"type": "value_error.missing",
}
]
}
)
app.dependency_overrides = {} app.dependency_overrides = {}
@ -340,29 +263,17 @@ def test_override_with_sub_decorator_depends():
app.dependency_overrides[common_parameters] = overrider_dependency_with_sub app.dependency_overrides[common_parameters] = overrider_dependency_with_sub
response = client.get("/decorator-depends/") response = client.get("/decorator-depends/")
assert response.status_code == 422 assert response.status_code == 422
assert response.json() == IsDict( assert response.json() == {
{ "detail": [
"detail": [ {
{ "type": "missing",
"type": "missing", "loc": ["query", "k"],
"loc": ["query", "k"], "msg": "Field required",
"msg": "Field required", "input": None,
"input": None, }
} ]
] }
}
) | IsDict(
# TODO: remove when deprecating Pydantic v1
{
"detail": [
{
"loc": ["query", "k"],
"msg": "field required",
"type": "value_error.missing",
}
]
}
)
app.dependency_overrides = {} app.dependency_overrides = {}
@ -370,29 +281,17 @@ def test_override_with_sub_decorator_depends_q_foo():
app.dependency_overrides[common_parameters] = overrider_dependency_with_sub app.dependency_overrides[common_parameters] = overrider_dependency_with_sub
response = client.get("/decorator-depends/?q=foo") response = client.get("/decorator-depends/?q=foo")
assert response.status_code == 422 assert response.status_code == 422
assert response.json() == IsDict( assert response.json() == {
{ "detail": [
"detail": [ {
{ "type": "missing",
"type": "missing", "loc": ["query", "k"],
"loc": ["query", "k"], "msg": "Field required",
"msg": "Field required", "input": None,
"input": None, }
} ]
] }
}
) | IsDict(
# TODO: remove when deprecating Pydantic v1
{
"detail": [
{
"loc": ["query", "k"],
"msg": "field required",
"type": "value_error.missing",
}
]
}
)
app.dependency_overrides = {} app.dependency_overrides = {}
@ -408,29 +307,17 @@ def test_override_with_sub_router_depends():
app.dependency_overrides[common_parameters] = overrider_dependency_with_sub app.dependency_overrides[common_parameters] = overrider_dependency_with_sub
response = client.get("/router-depends/") response = client.get("/router-depends/")
assert response.status_code == 422 assert response.status_code == 422
assert response.json() == IsDict( assert response.json() == {
{ "detail": [
"detail": [ {
{ "type": "missing",
"type": "missing", "loc": ["query", "k"],
"loc": ["query", "k"], "msg": "Field required",
"msg": "Field required", "input": None,
"input": None, }
} ]
] }
}
) | IsDict(
# TODO remove when deprecating Pydantic v1
{
"detail": [
{
"loc": ["query", "k"],
"msg": "field required",
"type": "value_error.missing",
}
]
}
)
app.dependency_overrides = {} app.dependency_overrides = {}
@ -438,29 +325,17 @@ def test_override_with_sub_router_depends_q_foo():
app.dependency_overrides[common_parameters] = overrider_dependency_with_sub app.dependency_overrides[common_parameters] = overrider_dependency_with_sub
response = client.get("/router-depends/?q=foo") response = client.get("/router-depends/?q=foo")
assert response.status_code == 422 assert response.status_code == 422
assert response.json() == IsDict( assert response.json() == {
{ "detail": [
"detail": [ {
{ "type": "missing",
"type": "missing", "loc": ["query", "k"],
"loc": ["query", "k"], "msg": "Field required",
"msg": "Field required", "input": None,
"input": None, }
} ]
] }
}
) | IsDict(
# TODO remove when deprecating Pydantic v1
{
"detail": [
{
"loc": ["query", "k"],
"msg": "field required",
"type": "value_error.missing",
}
]
}
)
app.dependency_overrides = {} app.dependency_overrides = {}
@ -476,29 +351,17 @@ def test_override_with_sub_router_decorator_depends():
app.dependency_overrides[common_parameters] = overrider_dependency_with_sub app.dependency_overrides[common_parameters] = overrider_dependency_with_sub
response = client.get("/router-decorator-depends/") response = client.get("/router-decorator-depends/")
assert response.status_code == 422 assert response.status_code == 422
assert response.json() == IsDict( assert response.json() == {
{ "detail": [
"detail": [ {
{ "type": "missing",
"type": "missing", "loc": ["query", "k"],
"loc": ["query", "k"], "msg": "Field required",
"msg": "Field required", "input": None,
"input": None, }
} ]
] }
}
) | IsDict(
# TODO remove when deprecating Pydantic v1
{
"detail": [
{
"loc": ["query", "k"],
"msg": "field required",
"type": "value_error.missing",
}
]
}
)
app.dependency_overrides = {} app.dependency_overrides = {}
@ -506,29 +369,17 @@ def test_override_with_sub_router_decorator_depends_q_foo():
app.dependency_overrides[common_parameters] = overrider_dependency_with_sub app.dependency_overrides[common_parameters] = overrider_dependency_with_sub
response = client.get("/router-decorator-depends/?q=foo") response = client.get("/router-decorator-depends/?q=foo")
assert response.status_code == 422 assert response.status_code == 422
assert response.json() == IsDict( assert response.json() == {
{ "detail": [
"detail": [ {
{ "type": "missing",
"type": "missing", "loc": ["query", "k"],
"loc": ["query", "k"], "msg": "Field required",
"msg": "Field required", "input": None,
"input": None, }
} ]
] }
}
) | IsDict(
# TODO remove when deprecating Pydantic v1
{
"detail": [
{
"loc": ["query", "k"],
"msg": "field required",
"type": "value_error.missing",
}
]
}
)
app.dependency_overrides = {} app.dependency_overrides = {}

View File

@ -1,6 +1,5 @@
from typing import Optional from typing import Optional
from dirty_equals import IsDict
from fastapi import FastAPI from fastapi import FastAPI
from fastapi.responses import JSONResponse from fastapi.responses import JSONResponse
from fastapi.testclient import TestClient from fastapi.testclient import TestClient
@ -328,14 +327,10 @@ def test_openapi_schema():
"type": "object", "type": "object",
"properties": { "properties": {
"name": {"title": "Name", "type": "string"}, "name": {"title": "Name", "type": "string"},
"price": IsDict( "price": {
{ "title": "Price",
"title": "Price", "anyOf": [{"type": "number"}, {"type": "null"}],
"anyOf": [{"type": "number"}, {"type": "null"}], },
}
)
# TODO: remove when deprecating Pydantic v1
| IsDict({"title": "Price", "type": "number"}),
}, },
}, },
"ValidationError": { "ValidationError": {

View File

@ -1,7 +1,7 @@
from typing import Optional from typing import Optional
import pytest import pytest
from dirty_equals import HasRepr, IsDict, IsOneOf from dirty_equals import HasRepr
from fastapi import Depends, FastAPI from fastapi import Depends, FastAPI
from fastapi.exceptions import ResponseValidationError from fastapi.exceptions import ResponseValidationError
from fastapi.testclient import TestClient from fastapi.testclient import TestClient
@ -63,23 +63,13 @@ def test_validator_is_cloned(client: TestClient):
with pytest.raises(ResponseValidationError) as err: with pytest.raises(ResponseValidationError) as err:
client.get("/model/modelX") client.get("/model/modelX")
assert err.value.errors() == [ assert err.value.errors() == [
IsDict( {
{ "type": "value_error",
"type": "value_error", "loc": ("response", "name"),
"loc": ("response", "name"), "msg": "Value error, name must end in A",
"msg": "Value error, name must end in A", "input": "modelX",
"input": "modelX", "ctx": {"error": HasRepr("ValueError('name must end in A')")},
"ctx": {"error": HasRepr("ValueError('name must end in A')")}, }
}
)
| IsDict(
# TODO remove when deprecating Pydantic v1
{
"loc": ("response", "name"),
"msg": "name must end in A",
"type": "value_error",
}
)
] ]
@ -145,23 +135,14 @@ def test_openapi_schema(client: TestClient):
}, },
"ModelA": { "ModelA": {
"title": "ModelA", "title": "ModelA",
"required": IsOneOf( "required": ["name", "foo"],
["name", "description", "foo"],
# TODO remove when deprecating Pydantic v1
["name", "foo"],
),
"type": "object", "type": "object",
"properties": { "properties": {
"name": {"title": "Name", "type": "string"}, "name": {"title": "Name", "type": "string"},
"description": IsDict( "description": {
{ "title": "Description",
"title": "Description", "anyOf": [{"type": "string"}, {"type": "null"}],
"anyOf": [{"type": "string"}, {"type": "null"}], },
}
)
|
# TODO remove when deprecating Pydantic v1
IsDict({"title": "Description", "type": "string"}),
"foo": {"$ref": "#/components/schemas/ModelB"}, "foo": {"$ref": "#/components/schemas/ModelB"},
"tags": { "tags": {
"additionalProperties": {"type": "string"}, "additionalProperties": {"type": "string"},

View File

@ -1,6 +1,5 @@
from typing import Annotated, Optional from typing import Annotated, Optional
from dirty_equals import IsDict
from fastapi import FastAPI, Form from fastapi import FastAPI, Form
from fastapi.testclient import TestClient from fastapi.testclient import TestClient
from pydantic import BaseModel, Field from pydantic import BaseModel, Field
@ -79,68 +78,37 @@ def test_invalid_data():
}, },
) )
assert response.status_code == 422, response.text assert response.status_code == 422, response.text
assert response.json() == IsDict( assert response.json() == {
{ "detail": [
"detail": [ {
{ "type": "int_parsing",
"type": "int_parsing", "loc": ["body", "age"],
"loc": ["body", "age"], "msg": "Input should be a valid integer, unable to parse string as an integer",
"msg": "Input should be a valid integer, unable to parse string as an integer", "input": "seventy",
"input": "seventy", }
} ]
] }
}
) | IsDict(
# TODO: remove when deprecating Pydantic v1
{
"detail": [
{
"loc": ["body", "age"],
"msg": "value is not a valid integer",
"type": "type_error.integer",
}
]
}
)
def test_no_data(): def test_no_data():
response = client.post("/form/") response = client.post("/form/")
assert response.status_code == 422, response.text assert response.status_code == 422, response.text
assert response.json() == IsDict( assert response.json() == {
{ "detail": [
"detail": [ {
{ "type": "missing",
"type": "missing", "loc": ["body", "username"],
"loc": ["body", "username"], "msg": "Field required",
"msg": "Field required", "input": {"tags": ["foo", "bar"], "with": "nothing"},
"input": {"tags": ["foo", "bar"], "with": "nothing"}, },
}, {
{ "type": "missing",
"type": "missing", "loc": ["body", "lastname"],
"loc": ["body", "lastname"], "msg": "Field required",
"msg": "Field required", "input": {"tags": ["foo", "bar"], "with": "nothing"},
"input": {"tags": ["foo", "bar"], "with": "nothing"}, },
}, ]
] }
}
) | IsDict(
# TODO: remove when deprecating Pydantic v1
{
"detail": [
{
"loc": ["body", "username"],
"msg": "field required",
"type": "value_error.missing",
},
{
"loc": ["body", "lastname"],
"msg": "field required",
"type": "value_error.missing",
},
]
}
)
def test_extra_param_single(): def test_extra_param_single():

View File

@ -1,6 +1,5 @@
from typing import Optional from typing import Optional
from dirty_equals import IsDict
from fastapi import APIRouter, FastAPI from fastapi import APIRouter, FastAPI
from fastapi.testclient import TestClient from fastapi.testclient import TestClient
@ -163,16 +162,10 @@ def test_openapi_schema():
"required": False, "required": False,
"name": "user_id", "name": "user_id",
"in": "query", "in": "query",
"schema": IsDict( "schema": {
{ "anyOf": [{"type": "string"}, {"type": "null"}],
"anyOf": [{"type": "string"}, {"type": "null"}], "title": "User Id",
"title": "User Id", },
}
)
| IsDict(
# TODO: remove when deprecating Pydantic v1
{"title": "User Id", "type": "string"}
),
} }
], ],
"responses": { "responses": {
@ -208,16 +201,10 @@ def test_openapi_schema():
"required": False, "required": False,
"name": "user_id", "name": "user_id",
"in": "query", "in": "query",
"schema": IsDict( "schema": {
{ "anyOf": [{"type": "string"}, {"type": "null"}],
"anyOf": [{"type": "string"}, {"type": "null"}], "title": "User Id",
"title": "User Id", },
}
)
| IsDict(
# TODO: remove when deprecating Pydantic v1
{"title": "User Id", "type": "string"}
),
}, },
], ],
"responses": { "responses": {
@ -247,16 +234,10 @@ def test_openapi_schema():
"required": True, "required": True,
"name": "user_id", "name": "user_id",
"in": "path", "in": "path",
"schema": IsDict( "schema": {
{ "anyOf": [{"type": "string"}, {"type": "null"}],
"anyOf": [{"type": "string"}, {"type": "null"}], "title": "User Id",
"title": "User Id", },
}
)
| IsDict(
# TODO: remove when deprecating Pydantic v1
{"title": "User Id", "type": "string"}
),
} }
], ],
"responses": { "responses": {
@ -292,16 +273,10 @@ def test_openapi_schema():
"required": True, "required": True,
"name": "user_id", "name": "user_id",
"in": "path", "in": "path",
"schema": IsDict( "schema": {
{ "anyOf": [{"type": "string"}, {"type": "null"}],
"anyOf": [{"type": "string"}, {"type": "null"}], "title": "User Id",
"title": "User Id", },
}
)
| IsDict(
# TODO: remove when deprecating Pydantic v1
{"title": "User Id", "type": "string"}
),
}, },
], ],
"responses": { "responses": {

View File

@ -1,8 +1,9 @@
from decimal import Decimal from decimal import Decimal
from dirty_equals import IsDict, IsOneOf from dirty_equals import IsOneOf
from fastapi import FastAPI from fastapi import FastAPI
from fastapi.testclient import TestClient from fastapi.testclient import TestClient
from inline_snapshot import snapshot
from pydantic import BaseModel, condecimal from pydantic import BaseModel, condecimal
app = FastAPI() app = FastAPI()
@ -24,109 +25,65 @@ client = TestClient(app)
def test_put_correct_body(): def test_put_correct_body():
response = client.post("/items/", json=[{"name": "Foo", "age": 5}]) response = client.post("/items/", json=[{"name": "Foo", "age": 5}])
assert response.status_code == 200, response.text assert response.status_code == 200, response.text
assert response.json() == { assert response.json() == snapshot(
"item": [ {
{ "item": [
"name": "Foo", {
"age": IsOneOf( "name": "Foo",
5, "age": "5",
# TODO: remove when deprecating Pydantic v1 }
"5", ]
), }
} )
]
}
def test_jsonable_encoder_requiring_error(): def test_jsonable_encoder_requiring_error():
response = client.post("/items/", json=[{"name": "Foo", "age": -1.0}]) response = client.post("/items/", json=[{"name": "Foo", "age": -1.0}])
assert response.status_code == 422, response.text assert response.status_code == 422, response.text
assert response.json() == IsDict( assert response.json() == {
{ "detail": [
"detail": [ {
{ "type": "greater_than",
"type": "greater_than", "loc": ["body", 0, "age"],
"loc": ["body", 0, "age"], "msg": "Input should be greater than 0",
"msg": "Input should be greater than 0", "input": -1.0,
"input": -1.0, "ctx": {"gt": 0},
"ctx": {"gt": 0}, }
} ]
] }
}
) | IsDict(
# TODO: remove when deprecating Pydantic v1
{
"detail": [
{
"ctx": {"limit_value": 0.0},
"loc": ["body", 0, "age"],
"msg": "ensure this value is greater than 0",
"type": "value_error.number.not_gt",
}
]
}
)
def test_put_incorrect_body_multiple(): def test_put_incorrect_body_multiple():
response = client.post("/items/", json=[{"age": "five"}, {"age": "six"}]) response = client.post("/items/", json=[{"age": "five"}, {"age": "six"}])
assert response.status_code == 422, response.text assert response.status_code == 422, response.text
assert response.json() == IsDict( assert response.json() == {
{ "detail": [
"detail": [ {
{ "type": "missing",
"type": "missing", "loc": ["body", 0, "name"],
"loc": ["body", 0, "name"], "msg": "Field required",
"msg": "Field required", "input": {"age": "five"},
"input": {"age": "five"}, },
}, {
{ "type": "decimal_parsing",
"type": "decimal_parsing", "loc": ["body", 0, "age"],
"loc": ["body", 0, "age"], "msg": "Input should be a valid decimal",
"msg": "Input should be a valid decimal", "input": "five",
"input": "five", },
}, {
{ "type": "missing",
"type": "missing", "loc": ["body", 1, "name"],
"loc": ["body", 1, "name"], "msg": "Field required",
"msg": "Field required", "input": {"age": "six"},
"input": {"age": "six"}, },
}, {
{ "type": "decimal_parsing",
"type": "decimal_parsing", "loc": ["body", 1, "age"],
"loc": ["body", 1, "age"], "msg": "Input should be a valid decimal",
"msg": "Input should be a valid decimal", "input": "six",
"input": "six", },
}, ]
] }
}
) | IsDict(
# TODO: remove when deprecating Pydantic v1
{
"detail": [
{
"loc": ["body", 0, "name"],
"msg": "field required",
"type": "value_error.missing",
},
{
"loc": ["body", 0, "age"],
"msg": "value is not a valid decimal",
"type": "type_error.decimal",
},
{
"loc": ["body", 1, "name"],
"msg": "field required",
"type": "value_error.missing",
},
{
"loc": ["body", 1, "age"],
"msg": "value is not a valid decimal",
"type": "type_error.decimal",
},
]
}
)
def test_openapi_schema(): def test_openapi_schema():
@ -179,31 +136,21 @@ def test_openapi_schema():
"type": "object", "type": "object",
"properties": { "properties": {
"name": {"title": "Name", "type": "string"}, "name": {"title": "Name", "type": "string"},
"age": IsDict( "age": {
{ "title": "Age",
"title": "Age", "anyOf": [
"anyOf": [ {"exclusiveMinimum": 0.0, "type": "number"},
{"exclusiveMinimum": 0.0, "type": "number"}, IsOneOf(
IsOneOf( # pydantic < 2.12.0
# pydantic < 2.12.0 {"type": "string"},
{"type": "string"}, # pydantic >= 2.12.0
# pydantic >= 2.12.0 {
{ "type": "string",
"type": "string", "pattern": r"^(?!^[-+.]*$)[+-]?0*\d*\.?\d*$",
"pattern": r"^(?!^[-+.]*$)[+-]?0*\d*\.?\d*$", },
}, ),
), ],
], },
}
)
| IsDict(
# TODO: remove when deprecating Pydantic v1
{
"title": "Age",
"exclusiveMinimum": 0.0,
"type": "number",
}
),
}, },
}, },
"ValidationError": { "ValidationError": {

View File

@ -1,4 +1,3 @@
from dirty_equals import IsDict
from fastapi import FastAPI, Query from fastapi import FastAPI, Query
from fastapi.testclient import TestClient from fastapi.testclient import TestClient
@ -22,40 +21,22 @@ def test_multi_query():
def test_multi_query_incorrect(): def test_multi_query_incorrect():
response = client.get("/items/?q=five&q=six") response = client.get("/items/?q=five&q=six")
assert response.status_code == 422, response.text assert response.status_code == 422, response.text
assert response.json() == IsDict( assert response.json() == {
{ "detail": [
"detail": [ {
{ "type": "int_parsing",
"type": "int_parsing", "loc": ["query", "q", 0],
"loc": ["query", "q", 0], "msg": "Input should be a valid integer, unable to parse string as an integer",
"msg": "Input should be a valid integer, unable to parse string as an integer", "input": "five",
"input": "five", },
}, {
{ "type": "int_parsing",
"type": "int_parsing", "loc": ["query", "q", 1],
"loc": ["query", "q", 1], "msg": "Input should be a valid integer, unable to parse string as an integer",
"msg": "Input should be a valid integer, unable to parse string as an integer", "input": "six",
"input": "six", },
}, ]
] }
}
) | IsDict(
# TODO: remove when deprecating Pydantic v1
{
"detail": [
{
"loc": ["query", "q", 0],
"msg": "value is not a valid integer",
"type": "type_error.integer",
},
{
"loc": ["query", "q", 1],
"msg": "value is not a valid integer",
"type": "type_error.integer",
},
]
}
)
def test_openapi_schema(): def test_openapi_schema():

View File

@ -1,6 +1,5 @@
from typing import Union from typing import Union
from dirty_equals import IsDict
from fastapi import Body, Cookie, FastAPI, Header, Path, Query from fastapi import Body, Cookie, FastAPI, Header, Path, Query
from fastapi.testclient import TestClient from fastapi.testclient import TestClient
from pydantic import BaseModel from pydantic import BaseModel
@ -155,26 +154,12 @@ def test_openapi_schema():
"requestBody": { "requestBody": {
"content": { "content": {
"application/json": { "application/json": {
"schema": IsDict( "schema": {
{ "$ref": "#/components/schemas/Item",
"$ref": "#/components/schemas/Item", "examples": [
"examples": [ {"data": "Data in Body examples, example1"}
{"data": "Data in Body examples, example1"} ],
], },
}
)
| IsDict(
{
# TODO: remove when deprecating Pydantic v1
"allOf": [
{"$ref": "#/components/schemas/Item"}
],
"title": "Item",
"examples": [
{"data": "Data in Body examples, example1"}
],
}
),
"examples": { "examples": {
"Example One": { "Example One": {
"summary": "Example One Summary", "summary": "Example One Summary",
@ -265,27 +250,14 @@ def test_openapi_schema():
"name": "data", "name": "data",
"in": "query", "in": "query",
"required": False, "required": False,
"schema": IsDict( "schema": {
{ "anyOf": [{"type": "string"}, {"type": "null"}],
"anyOf": [{"type": "string"}, {"type": "null"}], "examples": [
"examples": [ "json_schema_query1",
"json_schema_query1", "json_schema_query2",
"json_schema_query2", ],
], "title": "Data",
"title": "Data", },
}
)
| IsDict(
# TODO: remove when deprecating Pydantic v1
{
"examples": [
"json_schema_query1",
"json_schema_query2",
],
"type": "string",
"title": "Data",
}
),
"examples": { "examples": {
"Query One": { "Query One": {
"summary": "Query One Summary", "summary": "Query One Summary",
@ -323,27 +295,14 @@ def test_openapi_schema():
"name": "data", "name": "data",
"in": "header", "in": "header",
"required": False, "required": False,
"schema": IsDict( "schema": {
{ "anyOf": [{"type": "string"}, {"type": "null"}],
"anyOf": [{"type": "string"}, {"type": "null"}], "examples": [
"examples": [ "json_schema_header1",
"json_schema_header1", "json_schema_header2",
"json_schema_header2", ],
], "title": "Data",
"title": "Data", },
}
)
| IsDict(
# TODO: remove when deprecating Pydantic v1
{
"type": "string",
"examples": [
"json_schema_header1",
"json_schema_header2",
],
"title": "Data",
}
),
"examples": { "examples": {
"Header One": { "Header One": {
"summary": "Header One Summary", "summary": "Header One Summary",
@ -381,27 +340,14 @@ def test_openapi_schema():
"name": "data", "name": "data",
"in": "cookie", "in": "cookie",
"required": False, "required": False,
"schema": IsDict( "schema": {
{ "anyOf": [{"type": "string"}, {"type": "null"}],
"anyOf": [{"type": "string"}, {"type": "null"}], "examples": [
"examples": [ "json_schema_cookie1",
"json_schema_cookie1", "json_schema_cookie2",
"json_schema_cookie2", ],
], "title": "Data",
"title": "Data", },
}
)
| IsDict(
# TODO: remove when deprecating Pydantic v1
{
"type": "string",
"examples": [
"json_schema_cookie1",
"json_schema_cookie2",
],
"title": "Data",
}
),
"examples": { "examples": {
"Cookie One": { "Cookie One": {
"summary": "Cookie One Summary", "summary": "Cookie One Summary",

View File

@ -1,6 +1,5 @@
from typing import Optional from typing import Optional
from dirty_equals import IsDict
from fastapi import FastAPI from fastapi import FastAPI
from fastapi.testclient import TestClient from fastapi.testclient import TestClient
@ -53,21 +52,11 @@ def test_openapi():
"parameters": [ "parameters": [
{ {
"required": False, "required": False,
"schema": IsDict( "schema": {
{ "anyOf": [{"type": "integer"}, {"type": "null"}],
"anyOf": [{"type": "integer"}, {"type": "null"}], "default": 50,
"default": 50, "title": "Standard Query Param",
"title": "Standard Query Param", },
}
)
| IsDict(
# TODO: remove when deprecating Pydantic v1
{
"title": "Standard Query Param",
"type": "integer",
"default": 50,
}
),
"name": "standard_query_param", "name": "standard_query_param",
"in": "query", "in": "query",
}, },

View File

@ -1,6 +1,6 @@
from dirty_equals import IsOneOf
from fastapi import FastAPI from fastapi import FastAPI
from fastapi.testclient import TestClient from fastapi.testclient import TestClient
from inline_snapshot import snapshot
app = FastAPI( app = FastAPI(
servers=[ servers=[
@ -30,39 +30,31 @@ def test_app():
def test_openapi_schema(): def test_openapi_schema():
response = client.get("/openapi.json") response = client.get("/openapi.json")
assert response.status_code == 200, response.text assert response.status_code == 200, response.text
assert response.json() == { assert response.json() == snapshot(
"openapi": "3.1.0", {
"info": {"title": "FastAPI", "version": "0.1.0"}, "openapi": "3.1.0",
"servers": [ "info": {"title": "FastAPI", "version": "0.1.0"},
{"url": "/", "description": "Default, relative server"}, "servers": [
{ {"url": "/", "description": "Default, relative server"},
"url": IsOneOf( {
"http://staging.localhost.tiangolo.com:8000/", "url": "http://staging.localhost.tiangolo.com:8000",
# TODO: remove when deprecating Pydantic v1 "description": "Staging but actually localhost still",
"http://staging.localhost.tiangolo.com:8000", },
), {"url": "https://prod.example.com"},
"description": "Staging but actually localhost still", ],
}, "paths": {
{ "/foo": {
"url": IsOneOf( "get": {
"https://prod.example.com/", "summary": "Foo",
# TODO: remove when deprecating Pydantic v1 "operationId": "foo_foo_get",
"https://prod.example.com", "responses": {
) "200": {
}, "description": "Successful Response",
], "content": {"application/json": {"schema": {}}},
"paths": { }
"/foo": { },
"get": { }
"summary": "Foo",
"operationId": "foo_foo_get",
"responses": {
"200": {
"description": "Successful Response",
"content": {"application/json": {"schema": {}}},
}
},
} }
} },
}, }
} )

View File

@ -1,6 +1,5 @@
from typing import Any from typing import Any
from dirty_equals import IsOneOf
from fastapi.params import Body, Cookie, Header, Param, Path, Query from fastapi.params import Body, Cookie, Header, Param, Path, Query
test_data: list[Any] = ["teststr", None, ..., 1, []] test_data: list[Any] = ["teststr", None, ..., 1, []]
@ -19,11 +18,7 @@ def test_param_repr_none():
def test_param_repr_ellipsis(): def test_param_repr_ellipsis():
assert repr(Param(...)) == IsOneOf( assert repr(Param(...)) == "Param(PydanticUndefined)"
"Param(PydanticUndefined)",
# TODO: remove when deprecating Pydantic v1
"Param(Ellipsis)",
)
def test_param_repr_number(): def test_param_repr_number():
@ -35,16 +30,8 @@ def test_param_repr_list():
def test_path_repr(): def test_path_repr():
assert repr(Path()) == IsOneOf( assert repr(Path()) == "Path(PydanticUndefined)"
"Path(PydanticUndefined)", assert repr(Path(...)) == "Path(PydanticUndefined)"
# TODO: remove when deprecating Pydantic v1
"Path(Ellipsis)",
)
assert repr(Path(...)) == IsOneOf(
"Path(PydanticUndefined)",
# TODO: remove when deprecating Pydantic v1
"Path(Ellipsis)",
)
def test_query_repr_str(): def test_query_repr_str():
@ -56,11 +43,7 @@ def test_query_repr_none():
def test_query_repr_ellipsis(): def test_query_repr_ellipsis():
assert repr(Query(...)) == IsOneOf( assert repr(Query(...)) == "Query(PydanticUndefined)"
"Query(PydanticUndefined)",
# TODO: remove when deprecating Pydantic v1
"Query(Ellipsis)",
)
def test_query_repr_number(): def test_query_repr_number():
@ -80,11 +63,7 @@ def test_header_repr_none():
def test_header_repr_ellipsis(): def test_header_repr_ellipsis():
assert repr(Header(...)) == IsOneOf( assert repr(Header(...)) == "Header(PydanticUndefined)"
"Header(PydanticUndefined)",
# TODO: remove when deprecating Pydantic v1
"Header(Ellipsis)",
)
def test_header_repr_number(): def test_header_repr_number():
@ -104,11 +83,7 @@ def test_cookie_repr_none():
def test_cookie_repr_ellipsis(): def test_cookie_repr_ellipsis():
assert repr(Cookie(...)) == IsOneOf( assert repr(Cookie(...)) == "Cookie(PydanticUndefined)"
"Cookie(PydanticUndefined)",
# TODO: remove when deprecating Pydantic v1
"Cookie(Ellipsis)",
)
def test_cookie_repr_number(): def test_cookie_repr_number():
@ -128,11 +103,7 @@ def test_body_repr_none():
def test_body_repr_ellipsis(): def test_body_repr_ellipsis():
assert repr(Body(...)) == IsOneOf( assert repr(Body(...)) == "Body(PydanticUndefined)"
"Body(PydanticUndefined)",
# TODO: remove when deprecating Pydantic v1
"Body(Ellipsis)",
)
def test_body_repr_number(): def test_body_repr_number():

File diff suppressed because it is too large Load Diff

View File

@ -1,4 +1,3 @@
from dirty_equals import IsDict
from fastapi.testclient import TestClient from fastapi.testclient import TestClient
from .main import app from .main import app
@ -9,29 +8,16 @@ client = TestClient(app)
def test_query(): def test_query():
response = client.get("/query") response = client.get("/query")
assert response.status_code == 422 assert response.status_code == 422
assert response.json() == IsDict( assert response.json() == {
{ "detail": [
"detail": [ {
{ "type": "missing",
"type": "missing", "loc": ["query", "query"],
"loc": ["query", "query"], "msg": "Field required",
"msg": "Field required", "input": None,
"input": None, }
} ]
] }
}
) | IsDict(
# TODO: remove when deprecating Pydantic v1
{
"detail": [
{
"loc": ["query", "query"],
"msg": "field required",
"type": "value_error.missing",
}
]
}
)
def test_query_query_baz(): def test_query_query_baz():
@ -43,29 +29,16 @@ def test_query_query_baz():
def test_query_not_declared_baz(): def test_query_not_declared_baz():
response = client.get("/query?not_declared=baz") response = client.get("/query?not_declared=baz")
assert response.status_code == 422 assert response.status_code == 422
assert response.json() == IsDict( assert response.json() == {
{ "detail": [
"detail": [ {
{ "type": "missing",
"type": "missing", "loc": ["query", "query"],
"loc": ["query", "query"], "msg": "Field required",
"msg": "Field required", "input": None,
"input": None, }
} ]
] }
}
) | IsDict(
# TODO: remove when deprecating Pydantic v1
{
"detail": [
{
"loc": ["query", "query"],
"msg": "field required",
"type": "value_error.missing",
}
]
}
)
def test_query_optional(): def test_query_optional():
@ -89,29 +62,16 @@ def test_query_optional_not_declared_baz():
def test_query_int(): def test_query_int():
response = client.get("/query/int") response = client.get("/query/int")
assert response.status_code == 422 assert response.status_code == 422
assert response.json() == IsDict( assert response.json() == {
{ "detail": [
"detail": [ {
{ "type": "missing",
"type": "missing", "loc": ["query", "query"],
"loc": ["query", "query"], "msg": "Field required",
"msg": "Field required", "input": None,
"input": None, }
} ]
] }
}
) | IsDict(
# TODO: remove when deprecating Pydantic v1
{
"detail": [
{
"loc": ["query", "query"],
"msg": "field required",
"type": "value_error.missing",
}
]
}
)
def test_query_int_query_42(): def test_query_int_query_42():
@ -123,85 +83,46 @@ def test_query_int_query_42():
def test_query_int_query_42_5(): def test_query_int_query_42_5():
response = client.get("/query/int?query=42.5") response = client.get("/query/int?query=42.5")
assert response.status_code == 422 assert response.status_code == 422
assert response.json() == IsDict( assert response.json() == {
{ "detail": [
"detail": [ {
{ "type": "int_parsing",
"type": "int_parsing", "loc": ["query", "query"],
"loc": ["query", "query"], "msg": "Input should be a valid integer, unable to parse string as an integer",
"msg": "Input should be a valid integer, unable to parse string as an integer", "input": "42.5",
"input": "42.5", }
} ]
] }
}
) | IsDict(
# TODO: remove when deprecating Pydantic v1
{
"detail": [
{
"loc": ["query", "query"],
"msg": "value is not a valid integer",
"type": "type_error.integer",
}
]
}
)
def test_query_int_query_baz(): def test_query_int_query_baz():
response = client.get("/query/int?query=baz") response = client.get("/query/int?query=baz")
assert response.status_code == 422 assert response.status_code == 422
assert response.json() == IsDict( assert response.json() == {
{ "detail": [
"detail": [ {
{ "type": "int_parsing",
"type": "int_parsing", "loc": ["query", "query"],
"loc": ["query", "query"], "msg": "Input should be a valid integer, unable to parse string as an integer",
"msg": "Input should be a valid integer, unable to parse string as an integer", "input": "baz",
"input": "baz", }
} ]
] }
}
) | IsDict(
# TODO: remove when deprecating Pydantic v1
{
"detail": [
{
"loc": ["query", "query"],
"msg": "value is not a valid integer",
"type": "type_error.integer",
}
]
}
)
def test_query_int_not_declared_baz(): def test_query_int_not_declared_baz():
response = client.get("/query/int?not_declared=baz") response = client.get("/query/int?not_declared=baz")
assert response.status_code == 422 assert response.status_code == 422
assert response.json() == IsDict( assert response.json() == {
{ "detail": [
"detail": [ {
{ "type": "missing",
"type": "missing", "loc": ["query", "query"],
"loc": ["query", "query"], "msg": "Field required",
"msg": "Field required", "input": None,
"input": None, }
} ]
] }
}
) | IsDict(
# TODO: remove when deprecating Pydantic v1
{
"detail": [
{
"loc": ["query", "query"],
"msg": "field required",
"type": "value_error.missing",
}
]
}
)
def test_query_int_optional(): def test_query_int_optional():
@ -219,29 +140,16 @@ def test_query_int_optional_query_50():
def test_query_int_optional_query_foo(): def test_query_int_optional_query_foo():
response = client.get("/query/int/optional?query=foo") response = client.get("/query/int/optional?query=foo")
assert response.status_code == 422 assert response.status_code == 422
assert response.json() == IsDict( assert response.json() == {
{ "detail": [
"detail": [ {
{ "type": "int_parsing",
"type": "int_parsing", "loc": ["query", "query"],
"loc": ["query", "query"], "msg": "Input should be a valid integer, unable to parse string as an integer",
"msg": "Input should be a valid integer, unable to parse string as an integer", "input": "foo",
"input": "foo", }
} ]
] }
}
) | IsDict(
# TODO: remove when deprecating Pydantic v1
{
"detail": [
{
"loc": ["query", "query"],
"msg": "value is not a valid integer",
"type": "type_error.integer",
}
]
}
)
def test_query_int_default(): def test_query_int_default():
@ -259,29 +167,16 @@ def test_query_int_default_query_50():
def test_query_int_default_query_foo(): def test_query_int_default_query_foo():
response = client.get("/query/int/default?query=foo") response = client.get("/query/int/default?query=foo")
assert response.status_code == 422 assert response.status_code == 422
assert response.json() == IsDict( assert response.json() == {
{ "detail": [
"detail": [ {
{ "type": "int_parsing",
"type": "int_parsing", "loc": ["query", "query"],
"loc": ["query", "query"], "msg": "Input should be a valid integer, unable to parse string as an integer",
"msg": "Input should be a valid integer, unable to parse string as an integer", "input": "foo",
"input": "foo", }
} ]
] }
}
) | IsDict(
# TODO: remove when deprecating Pydantic v1
{
"detail": [
{
"loc": ["query", "query"],
"msg": "value is not a valid integer",
"type": "type_error.integer",
}
]
}
)
def test_query_param(): def test_query_param():
@ -299,29 +194,16 @@ def test_query_param_query_50():
def test_query_param_required(): def test_query_param_required():
response = client.get("/query/param-required") response = client.get("/query/param-required")
assert response.status_code == 422 assert response.status_code == 422
assert response.json() == IsDict( assert response.json() == {
{ "detail": [
"detail": [ {
{ "type": "missing",
"type": "missing", "loc": ["query", "query"],
"loc": ["query", "query"], "msg": "Field required",
"msg": "Field required", "input": None,
"input": None, }
} ]
] }
}
) | IsDict(
# TODO: remove when deprecating Pydantic v1
{
"detail": [
{
"loc": ["query", "query"],
"msg": "field required",
"type": "value_error.missing",
}
]
}
)
def test_query_param_required_query_50(): def test_query_param_required_query_50():
@ -333,29 +215,16 @@ def test_query_param_required_query_50():
def test_query_param_required_int(): def test_query_param_required_int():
response = client.get("/query/param-required/int") response = client.get("/query/param-required/int")
assert response.status_code == 422 assert response.status_code == 422
assert response.json() == IsDict( assert response.json() == {
{ "detail": [
"detail": [ {
{ "type": "missing",
"type": "missing", "loc": ["query", "query"],
"loc": ["query", "query"], "msg": "Field required",
"msg": "Field required", "input": None,
"input": None, }
} ]
] }
}
) | IsDict(
# TODO: remove when deprecating Pydantic v1
{
"detail": [
{
"loc": ["query", "query"],
"msg": "field required",
"type": "value_error.missing",
}
]
}
)
def test_query_param_required_int_query_50(): def test_query_param_required_int_query_50():
@ -367,29 +236,16 @@ def test_query_param_required_int_query_50():
def test_query_param_required_int_query_foo(): def test_query_param_required_int_query_foo():
response = client.get("/query/param-required/int?query=foo") response = client.get("/query/param-required/int?query=foo")
assert response.status_code == 422 assert response.status_code == 422
assert response.json() == IsDict( assert response.json() == {
{ "detail": [
"detail": [ {
{ "type": "int_parsing",
"type": "int_parsing", "loc": ["query", "query"],
"loc": ["query", "query"], "msg": "Input should be a valid integer, unable to parse string as an integer",
"msg": "Input should be a valid integer, unable to parse string as an integer", "input": "foo",
"input": "foo", }
} ]
] }
}
) | IsDict(
# TODO: remove when deprecating Pydantic v1
{
"detail": [
{
"loc": ["query", "query"],
"msg": "value is not a valid integer",
"type": "type_error.integer",
}
]
}
)
def test_query_frozenset_query_1_query_1_query_2(): def test_query_frozenset_query_1_query_1_query_2():

View File

@ -1,10 +1,10 @@
from typing import Annotated from typing import Annotated
import pytest import pytest
from dirty_equals import IsDict
from fastapi import FastAPI, Form from fastapi import FastAPI, Form
from fastapi.exceptions import FastAPIDeprecationWarning from fastapi.exceptions import FastAPIDeprecationWarning
from fastapi.testclient import TestClient from fastapi.testclient import TestClient
from inline_snapshot import snapshot
from .utils import needs_py310 from .utils import needs_py310
@ -47,31 +47,17 @@ def test_query_nonregexquery():
client = get_client() client = get_client()
response = client.post("/items/", data={"q": "nonregexquery"}) response = client.post("/items/", data={"q": "nonregexquery"})
assert response.status_code == 422 assert response.status_code == 422
assert response.json() == IsDict( assert response.json() == {
{ "detail": [
"detail": [ {
{ "type": "string_pattern_mismatch",
"type": "string_pattern_mismatch", "loc": ["body", "q"],
"loc": ["body", "q"], "msg": "String should match pattern '^fixedquery$'",
"msg": "String should match pattern '^fixedquery$'", "input": "nonregexquery",
"input": "nonregexquery", "ctx": {"pattern": "^fixedquery$"},
"ctx": {"pattern": "^fixedquery$"}, }
} ]
] }
}
) | IsDict(
# TODO: remove when deprecating Pydantic v1
{
"detail": [
{
"ctx": {"pattern": "^fixedquery$"},
"loc": ["body", "q"],
"msg": 'string does not match regex "^fixedquery$"',
"type": "value_error.str.regex",
}
]
}
)
@needs_py310 @needs_py310
@ -79,104 +65,88 @@ def test_openapi_schema():
client = get_client() client = get_client()
response = client.get("/openapi.json") response = client.get("/openapi.json")
assert response.status_code == 200, response.text assert response.status_code == 200, response.text
# insert_assert(response.json()) assert response.json() == snapshot(
assert response.json() == { {
"openapi": "3.1.0", "openapi": "3.1.0",
"info": {"title": "FastAPI", "version": "0.1.0"}, "info": {"title": "FastAPI", "version": "0.1.0"},
"paths": { "paths": {
"/items/": { "/items/": {
"post": { "post": {
"summary": "Read Items", "summary": "Read Items",
"operationId": "read_items_items__post", "operationId": "read_items_items__post",
"requestBody": { "requestBody": {
"content": { "content": {
"application/x-www-form-urlencoded": { "application/x-www-form-urlencoded": {
"schema": IsDict( "schema": {
{
"allOf": [
{
"$ref": "#/components/schemas/Body_read_items_items__post"
}
],
"title": "Body",
}
)
| IsDict(
# TODO: remove when deprecating Pydantic v1
{
"$ref": "#/components/schemas/Body_read_items_items__post" "$ref": "#/components/schemas/Body_read_items_items__post"
} }
)
}
}
},
"responses": {
"200": {
"description": "Successful Response",
"content": {"application/json": {"schema": {}}},
},
"422": {
"description": "Validation Error",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/HTTPValidationError"
}
} }
}
},
"responses": {
"200": {
"description": "Successful Response",
"content": {"application/json": {"schema": {}}},
},
"422": {
"description": "Validation Error",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/HTTPValidationError"
}
}
},
}, },
}, },
}, }
} }
} },
}, "components": {
"components": { "schemas": {
"schemas": { "Body_read_items_items__post": {
"Body_read_items_items__post": { "properties": {
"properties": { "q": {
"q": IsDict(
{
"anyOf": [ "anyOf": [
{"type": "string", "pattern": "^fixedquery$"}, {"type": "string", "pattern": "^fixedquery$"},
{"type": "null"}, {"type": "null"},
], ],
"title": "Q", "title": "Q",
} }
)
| IsDict(
# TODO: remove when deprecating Pydantic v1
{"type": "string", "pattern": "^fixedquery$", "title": "Q"}
)
},
"type": "object",
"title": "Body_read_items_items__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": "object",
"type": {"type": "string", "title": "Error Type"}, "title": "Body_read_items_items__post",
}, },
"type": "object", "HTTPValidationError": {
"required": ["loc", "msg", "type"], "properties": {
"title": "ValidationError", "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",
},
}
},
}
)

View File

@ -1,7 +1,6 @@
from typing import Annotated from typing import Annotated
import pytest import pytest
from dirty_equals import IsDict
from fastapi import FastAPI, Query from fastapi import FastAPI, Query
from fastapi.exceptions import FastAPIDeprecationWarning from fastapi.exceptions import FastAPIDeprecationWarning
from fastapi.testclient import TestClient from fastapi.testclient import TestClient
@ -47,31 +46,17 @@ def test_query_params_str_validations_item_query_nonregexquery():
client = get_client() client = get_client()
response = client.get("/items/", params={"q": "nonregexquery"}) response = client.get("/items/", params={"q": "nonregexquery"})
assert response.status_code == 422 assert response.status_code == 422
assert response.json() == IsDict( assert response.json() == {
{ "detail": [
"detail": [ {
{ "type": "string_pattern_mismatch",
"type": "string_pattern_mismatch", "loc": ["query", "q"],
"loc": ["query", "q"], "msg": "String should match pattern '^fixedquery$'",
"msg": "String should match pattern '^fixedquery$'", "input": "nonregexquery",
"input": "nonregexquery", "ctx": {"pattern": "^fixedquery$"},
"ctx": {"pattern": "^fixedquery$"}, }
} ]
] }
}
) | IsDict(
# TODO: remove when deprecating Pydantic v1
{
"detail": [
{
"ctx": {"pattern": "^fixedquery$"},
"loc": ["query", "q"],
"msg": 'string does not match regex "^fixedquery$"',
"type": "value_error.str.regex",
}
]
}
)
@needs_py310 @needs_py310
@ -93,23 +78,13 @@ def test_openapi_schema():
"name": "q", "name": "q",
"in": "query", "in": "query",
"required": False, "required": False,
"schema": IsDict( "schema": {
{ "anyOf": [
"anyOf": [ {"type": "string", "pattern": "^fixedquery$"},
{"type": "string", "pattern": "^fixedquery$"}, {"type": "null"},
{"type": "null"}, ],
], "title": "Q",
"title": "Q", },
}
)
| IsDict(
# TODO: remove when deprecating Pydantic v1
{
"type": "string",
"pattern": "^fixedquery$",
"title": "Q",
}
),
} }
], ],
"responses": { "responses": {

View File

@ -148,29 +148,16 @@ def test_required_list_alias_missing(path: str, json: Union[dict, None]):
client = TestClient(app) client = TestClient(app)
response = client.post(path, json=json) response = client.post(path, json=json)
assert response.status_code == 422 assert response.status_code == 422
assert response.json() == IsDict( assert response.json() == {
{ "detail": [
"detail": [ {
{ "type": "missing",
"type": "missing", "loc": IsOneOf(["body", "p_alias"], ["body"]),
"loc": IsOneOf(["body", "p_alias"], ["body"]), "msg": "Field required",
"msg": "Field required", "input": IsOneOf(None, {}),
"input": IsOneOf(None, {}), }
} ]
] }
}
) | IsDict(
# TODO: remove when deprecating Pydantic v1
{
"detail": [
{
"loc": IsOneOf(["body", "p_alias"], ["body"]),
"msg": "field required",
"type": "value_error.missing",
}
]
}
)
@pytest.mark.parametrize( @pytest.mark.parametrize(
@ -181,29 +168,16 @@ def test_required_list_alias_by_name(path: str):
client = TestClient(app) client = TestClient(app)
response = client.post(path, json={"p": ["hello", "world"]}) response = client.post(path, json={"p": ["hello", "world"]})
assert response.status_code == 422 assert response.status_code == 422
assert response.json() == IsDict( assert response.json() == {
{ "detail": [
"detail": [ {
{ "type": "missing",
"type": "missing", "loc": ["body", "p_alias"],
"loc": ["body", "p_alias"], "msg": "Field required",
"msg": "Field required", "input": IsOneOf(None, {"p": ["hello", "world"]}),
"input": IsOneOf(None, {"p": ["hello", "world"]}), }
} ]
] }
}
) | IsDict(
# TODO: remove when deprecating Pydantic v1
{
"detail": [
{
"loc": ["body", "p_alias"],
"msg": "field required",
"type": "value_error.missing",
}
]
}
)
@pytest.mark.parametrize( @pytest.mark.parametrize(

View File

@ -1,7 +1,6 @@
from typing import Annotated, Optional from typing import Annotated, Optional
import pytest import pytest
from dirty_equals import IsDict
from fastapi import Body, FastAPI from fastapi import Body, FastAPI
from fastapi.testclient import TestClient from fastapi.testclient import TestClient
from pydantic import BaseModel, Field from pydantic import BaseModel, Field
@ -38,30 +37,19 @@ def test_optional_list_str_schema(path: str):
openapi = app.openapi() openapi = app.openapi()
body_model_name = get_body_model_name(openapi, path) body_model_name = get_body_model_name(openapi, path)
assert app.openapi()["components"]["schemas"][body_model_name] == IsDict( assert app.openapi()["components"]["schemas"][body_model_name] == {
{ "properties": {
"properties": { "p": {
"p": { "anyOf": [
"anyOf": [ {"items": {"type": "string"}, "type": "array"},
{"items": {"type": "string"}, "type": "array"}, {"type": "null"},
{"type": "null"}, ],
], "title": "P",
"title": "P",
},
}, },
"title": body_model_name, },
"type": "object", "title": body_model_name,
} "type": "object",
) | IsDict( }
# TODO: remove when deprecating Pydantic v1
{
"properties": {
"p": {"items": {"type": "string"}, "type": "array", "title": "P"},
},
"title": body_model_name,
"type": "object",
}
)
def test_optional_list_str_missing(): def test_optional_list_str_missing():
@ -75,29 +63,16 @@ def test_model_optional_list_str_missing():
client = TestClient(app) client = TestClient(app)
response = client.post("/model-optional-list-str") response = client.post("/model-optional-list-str")
assert response.status_code == 422, response.text assert response.status_code == 422, response.text
assert response.json() == IsDict( assert response.json() == {
{ "detail": [
"detail": [ {
{ "input": None,
"input": None, "loc": ["body"],
"loc": ["body"], "msg": "Field required",
"msg": "Field required", "type": "missing",
"type": "missing", },
}, ],
], }
}
) | IsDict(
{
# TODO: remove when deprecating Pydantic v1
"detail": [
{
"loc": ["body"],
"msg": "field required",
"type": "value_error.missing",
},
],
}
)
@pytest.mark.parametrize( @pytest.mark.parametrize(
@ -153,34 +128,19 @@ def test_optional_list_str_alias_schema(path: str):
openapi = app.openapi() openapi = app.openapi()
body_model_name = get_body_model_name(openapi, path) body_model_name = get_body_model_name(openapi, path)
assert app.openapi()["components"]["schemas"][body_model_name] == IsDict( assert app.openapi()["components"]["schemas"][body_model_name] == {
{ "properties": {
"properties": { "p_alias": {
"p_alias": { "anyOf": [
"anyOf": [ {"items": {"type": "string"}, "type": "array"},
{"items": {"type": "string"}, "type": "array"}, {"type": "null"},
{"type": "null"}, ],
], "title": "P Alias",
"title": "P Alias",
},
}, },
"title": body_model_name, },
"type": "object", "title": body_model_name,
} "type": "object",
) | IsDict( }
# TODO: remove when deprecating Pydantic v1
{
"properties": {
"p_alias": {
"items": {"type": "string"},
"type": "array",
"title": "P Alias",
},
},
"title": body_model_name,
"type": "object",
}
)
def test_optional_list_alias_missing(): def test_optional_list_alias_missing():
@ -194,29 +154,16 @@ def test_model_optional_list_alias_missing():
client = TestClient(app) client = TestClient(app)
response = client.post("/model-optional-list-alias") response = client.post("/model-optional-list-alias")
assert response.status_code == 422, response.text assert response.status_code == 422, response.text
assert response.json() == IsDict( assert response.json() == {
{ "detail": [
"detail": [ {
{ "input": None,
"input": None, "loc": ["body"],
"loc": ["body"], "msg": "Field required",
"msg": "Field required", "type": "missing",
"type": "missing", },
}, ],
], }
}
) | IsDict(
{
# TODO: remove when deprecating Pydantic v1
"detail": [
{
"loc": ["body"],
"msg": "field required",
"type": "value_error.missing",
},
],
}
)
@pytest.mark.parametrize( @pytest.mark.parametrize(
@ -289,34 +236,19 @@ def test_optional_list_validation_alias_schema(path: str):
openapi = app.openapi() openapi = app.openapi()
body_model_name = get_body_model_name(openapi, path) body_model_name = get_body_model_name(openapi, path)
assert app.openapi()["components"]["schemas"][body_model_name] == IsDict( assert app.openapi()["components"]["schemas"][body_model_name] == {
{ "properties": {
"properties": { "p_val_alias": {
"p_val_alias": { "anyOf": [
"anyOf": [ {"items": {"type": "string"}, "type": "array"},
{"items": {"type": "string"}, "type": "array"}, {"type": "null"},
{"type": "null"}, ],
], "title": "P Val Alias",
"title": "P Val Alias",
},
}, },
"title": body_model_name, },
"type": "object", "title": body_model_name,
} "type": "object",
) | IsDict( }
# TODO: remove when deprecating Pydantic v1
{
"properties": {
"p_val_alias": {
"items": {"type": "string"},
"type": "array",
"title": "P Val Alias",
},
},
"title": body_model_name,
"type": "object",
}
)
def test_optional_list_validation_alias_missing(): def test_optional_list_validation_alias_missing():
@ -330,29 +262,16 @@ def test_model_optional_list_validation_alias_missing():
client = TestClient(app) client = TestClient(app)
response = client.post("/model-optional-list-validation-alias") response = client.post("/model-optional-list-validation-alias")
assert response.status_code == 422, response.text assert response.status_code == 422, response.text
assert response.json() == IsDict( assert response.json() == {
{ "detail": [
"detail": [ {
{ "input": None,
"input": None, "loc": ["body"],
"loc": ["body"], "msg": "Field required",
"msg": "Field required", "type": "missing",
"type": "missing", },
}, ],
], }
}
) | IsDict(
{
# TODO: remove when deprecating Pydantic v1
"detail": [
{
"loc": ["body"],
"msg": "field required",
"type": "value_error.missing",
},
],
}
)
@pytest.mark.parametrize( @pytest.mark.parametrize(
@ -438,34 +357,19 @@ def test_optional_list_alias_and_validation_alias_schema(path: str):
openapi = app.openapi() openapi = app.openapi()
body_model_name = get_body_model_name(openapi, path) body_model_name = get_body_model_name(openapi, path)
assert app.openapi()["components"]["schemas"][body_model_name] == IsDict( assert app.openapi()["components"]["schemas"][body_model_name] == {
{ "properties": {
"properties": { "p_val_alias": {
"p_val_alias": { "anyOf": [
"anyOf": [ {"items": {"type": "string"}, "type": "array"},
{"items": {"type": "string"}, "type": "array"}, {"type": "null"},
{"type": "null"}, ],
], "title": "P Val Alias",
"title": "P Val Alias",
},
}, },
"title": body_model_name, },
"type": "object", "title": body_model_name,
} "type": "object",
) | IsDict( }
# TODO: remove when deprecating Pydantic v1
{
"properties": {
"p_val_alias": {
"items": {"type": "string"},
"type": "array",
"title": "P Val Alias",
},
},
"title": body_model_name,
"type": "object",
}
)
def test_optional_list_alias_and_validation_alias_missing(): def test_optional_list_alias_and_validation_alias_missing():
@ -479,29 +383,16 @@ def test_model_optional_list_alias_and_validation_alias_missing():
client = TestClient(app) client = TestClient(app)
response = client.post("/model-optional-list-alias-and-validation-alias") response = client.post("/model-optional-list-alias-and-validation-alias")
assert response.status_code == 422, response.text assert response.status_code == 422, response.text
assert response.json() == IsDict( assert response.json() == {
{ "detail": [
"detail": [ {
{ "input": None,
"input": None, "loc": ["body"],
"loc": ["body"], "msg": "Field required",
"msg": "Field required", "type": "missing",
"type": "missing", },
}, ],
], }
}
) | IsDict(
{
# TODO: remove when deprecating Pydantic v1
"detail": [
{
"loc": ["body"],
"msg": "field required",
"type": "value_error.missing",
},
],
}
)
@pytest.mark.parametrize( @pytest.mark.parametrize(

View File

@ -1,7 +1,6 @@
from typing import Annotated, Optional from typing import Annotated, Optional
import pytest import pytest
from dirty_equals import IsDict
from fastapi import Body, FastAPI from fastapi import Body, FastAPI
from fastapi.testclient import TestClient from fastapi.testclient import TestClient
from pydantic import BaseModel, Field from pydantic import BaseModel, Field
@ -36,27 +35,16 @@ def test_optional_str_schema(path: str):
openapi = app.openapi() openapi = app.openapi()
body_model_name = get_body_model_name(openapi, path) body_model_name = get_body_model_name(openapi, path)
assert app.openapi()["components"]["schemas"][body_model_name] == IsDict( assert app.openapi()["components"]["schemas"][body_model_name] == {
{ "properties": {
"properties": { "p": {
"p": { "anyOf": [{"type": "string"}, {"type": "null"}],
"anyOf": [{"type": "string"}, {"type": "null"}], "title": "P",
"title": "P",
},
}, },
"title": body_model_name, },
"type": "object", "title": body_model_name,
} "type": "object",
) | IsDict( }
# TODO: remove when deprecating Pydantic v1
{
"properties": {
"p": {"type": "string", "title": "P"},
},
"title": body_model_name,
"type": "object",
}
)
def test_optional_str_missing(): def test_optional_str_missing():
@ -70,29 +58,16 @@ def test_model_optional_str_missing():
client = TestClient(app) client = TestClient(app)
response = client.post("/model-optional-str") response = client.post("/model-optional-str")
assert response.status_code == 422, response.text assert response.status_code == 422, response.text
assert response.json() == IsDict( assert response.json() == {
{ "detail": [
"detail": [ {
{ "input": None,
"input": None, "loc": ["body"],
"loc": ["body"], "msg": "Field required",
"msg": "Field required", "type": "missing",
"type": "missing", },
}, ],
], }
}
) | IsDict(
{
# TODO: remove when deprecating Pydantic v1
"detail": [
{
"loc": ["body"],
"msg": "field required",
"type": "value_error.missing",
},
],
}
)
@pytest.mark.parametrize( @pytest.mark.parametrize(
@ -148,27 +123,16 @@ def test_optional_str_alias_schema(path: str):
openapi = app.openapi() openapi = app.openapi()
body_model_name = get_body_model_name(openapi, path) body_model_name = get_body_model_name(openapi, path)
assert app.openapi()["components"]["schemas"][body_model_name] == IsDict( assert app.openapi()["components"]["schemas"][body_model_name] == {
{ "properties": {
"properties": { "p_alias": {
"p_alias": { "anyOf": [{"type": "string"}, {"type": "null"}],
"anyOf": [{"type": "string"}, {"type": "null"}], "title": "P Alias",
"title": "P Alias",
},
}, },
"title": body_model_name, },
"type": "object", "title": body_model_name,
} "type": "object",
) | IsDict( }
# TODO: remove when deprecating Pydantic v1
{
"properties": {
"p_alias": {"type": "string", "title": "P Alias"},
},
"title": body_model_name,
"type": "object",
}
)
def test_optional_alias_missing(): def test_optional_alias_missing():
@ -182,29 +146,16 @@ def test_model_optional_alias_missing():
client = TestClient(app) client = TestClient(app)
response = client.post("/model-optional-alias") response = client.post("/model-optional-alias")
assert response.status_code == 422, response.text assert response.status_code == 422, response.text
assert response.json() == IsDict( assert response.json() == {
{ "detail": [
"detail": [ {
{ "input": None,
"input": None, "loc": ["body"],
"loc": ["body"], "msg": "Field required",
"msg": "Field required", "type": "missing",
"type": "missing", },
}, ],
], }
}
) | IsDict(
{
# TODO: remove when deprecating Pydantic v1
"detail": [
{
"loc": ["body"],
"msg": "field required",
"type": "value_error.missing",
},
],
}
)
@pytest.mark.parametrize( @pytest.mark.parametrize(
@ -274,27 +225,16 @@ def test_optional_validation_alias_schema(path: str):
openapi = app.openapi() openapi = app.openapi()
body_model_name = get_body_model_name(openapi, path) body_model_name = get_body_model_name(openapi, path)
assert app.openapi()["components"]["schemas"][body_model_name] == IsDict( assert app.openapi()["components"]["schemas"][body_model_name] == {
{ "properties": {
"properties": { "p_val_alias": {
"p_val_alias": { "anyOf": [{"type": "string"}, {"type": "null"}],
"anyOf": [{"type": "string"}, {"type": "null"}], "title": "P Val Alias",
"title": "P Val Alias",
},
}, },
"title": body_model_name, },
"type": "object", "title": body_model_name,
} "type": "object",
) | IsDict( }
# TODO: remove when deprecating Pydantic v1
{
"properties": {
"p_val_alias": {"type": "string", "title": "P Val Alias"},
},
"title": body_model_name,
"type": "object",
}
)
def test_optional_validation_alias_missing(): def test_optional_validation_alias_missing():
@ -308,29 +248,16 @@ def test_model_optional_validation_alias_missing():
client = TestClient(app) client = TestClient(app)
response = client.post("/model-optional-validation-alias") response = client.post("/model-optional-validation-alias")
assert response.status_code == 422, response.text assert response.status_code == 422, response.text
assert response.json() == IsDict( assert response.json() == {
{ "detail": [
"detail": [ {
{ "input": None,
"input": None, "loc": ["body"],
"loc": ["body"], "msg": "Field required",
"msg": "Field required", "type": "missing",
"type": "missing", },
}, ],
], }
}
) | IsDict(
{
# TODO: remove when deprecating Pydantic v1
"detail": [
{
"loc": ["body"],
"msg": "field required",
"type": "value_error.missing",
},
],
}
)
@pytest.mark.parametrize( @pytest.mark.parametrize(
@ -413,27 +340,16 @@ def test_optional_alias_and_validation_alias_schema(path: str):
openapi = app.openapi() openapi = app.openapi()
body_model_name = get_body_model_name(openapi, path) body_model_name = get_body_model_name(openapi, path)
assert app.openapi()["components"]["schemas"][body_model_name] == IsDict( assert app.openapi()["components"]["schemas"][body_model_name] == {
{ "properties": {
"properties": { "p_val_alias": {
"p_val_alias": { "anyOf": [{"type": "string"}, {"type": "null"}],
"anyOf": [{"type": "string"}, {"type": "null"}], "title": "P Val Alias",
"title": "P Val Alias",
},
}, },
"title": body_model_name, },
"type": "object", "title": body_model_name,
} "type": "object",
) | IsDict( }
# TODO: remove when deprecating Pydantic v1
{
"properties": {
"p_val_alias": {"type": "string", "title": "P Val Alias"},
},
"title": body_model_name,
"type": "object",
}
)
def test_optional_alias_and_validation_alias_missing(): def test_optional_alias_and_validation_alias_missing():
@ -447,29 +363,16 @@ def test_model_optional_alias_and_validation_alias_missing():
client = TestClient(app) client = TestClient(app)
response = client.post("/model-optional-alias-and-validation-alias") response = client.post("/model-optional-alias-and-validation-alias")
assert response.status_code == 422, response.text assert response.status_code == 422, response.text
assert response.json() == IsDict( assert response.json() == {
{ "detail": [
"detail": [ {
{ "input": None,
"input": None, "loc": ["body"],
"loc": ["body"], "msg": "Field required",
"msg": "Field required", "type": "missing",
"type": "missing", },
}, ],
], }
}
) | IsDict(
{
# TODO: remove when deprecating Pydantic v1
"detail": [
{
"loc": ["body"],
"msg": "field required",
"type": "value_error.missing",
},
],
}
)
@pytest.mark.parametrize( @pytest.mark.parametrize(

View File

@ -1,7 +1,7 @@
from typing import Annotated, Any, Union from typing import Annotated, Any, Union
import pytest import pytest
from dirty_equals import IsDict, IsOneOf from dirty_equals import IsOneOf
from fastapi import Body, FastAPI from fastapi import Body, FastAPI
from fastapi.testclient import TestClient from fastapi.testclient import TestClient
from pydantic import BaseModel, Field from pydantic import BaseModel, Field
@ -55,29 +55,16 @@ def test_required_str_missing(path: str, json: Union[dict[str, Any], None]):
client = TestClient(app) client = TestClient(app)
response = client.post(path, json=json) response = client.post(path, json=json)
assert response.status_code == 422 assert response.status_code == 422
assert response.json() == IsDict( assert response.json() == {
{ "detail": [
"detail": [ {
{ "type": "missing",
"type": "missing", "loc": IsOneOf(["body"], ["body", "p"]),
"loc": IsOneOf(["body"], ["body", "p"]), "msg": "Field required",
"msg": "Field required", "input": IsOneOf(None, {}),
"input": IsOneOf(None, {}), }
} ]
] }
}
) | IsDict(
# TODO: remove when deprecating Pydantic v1
{
"detail": [
{
"loc": IsOneOf(["body"], ["body", "p"]),
"msg": "field required",
"type": "value_error.missing",
}
]
}
)
@pytest.mark.parametrize( @pytest.mark.parametrize(
@ -141,29 +128,16 @@ def test_required_alias_missing(path: str, json: Union[dict[str, Any], None]):
client = TestClient(app) client = TestClient(app)
response = client.post(path, json=json) response = client.post(path, json=json)
assert response.status_code == 422 assert response.status_code == 422
assert response.json() == IsDict( assert response.json() == {
{ "detail": [
"detail": [ {
{ "type": "missing",
"type": "missing", "loc": IsOneOf(["body", "p_alias"], ["body"]),
"loc": IsOneOf(["body", "p_alias"], ["body"]), "msg": "Field required",
"msg": "Field required", "input": IsOneOf(None, {}),
"input": IsOneOf(None, {}), }
} ]
] }
}
) | IsDict(
# TODO: remove when deprecating Pydantic v1
{
"detail": [
{
"loc": IsOneOf(["body", "p_alias"], ["body"]),
"msg": "field required",
"type": "value_error.missing",
}
]
}
)
@pytest.mark.parametrize( @pytest.mark.parametrize(
@ -174,29 +148,16 @@ def test_required_alias_by_name(path: str):
client = TestClient(app) client = TestClient(app)
response = client.post(path, json={"p": "hello"}) response = client.post(path, json={"p": "hello"})
assert response.status_code == 422 assert response.status_code == 422
assert response.json() == IsDict( assert response.json() == {
{ "detail": [
"detail": [ {
{ "type": "missing",
"type": "missing", "loc": ["body", "p_alias"],
"loc": ["body", "p_alias"], "msg": "Field required",
"msg": "Field required", "input": IsOneOf(None, {"p": "hello"}),
"input": IsOneOf(None, {"p": "hello"}), }
} ]
] }
}
) | IsDict(
# TODO: remove when deprecating Pydantic v1
{
"detail": [
{
"loc": IsOneOf(["body", "p_alias"], ["body"]),
"msg": "field required",
"type": "value_error.missing",
}
]
}
)
@pytest.mark.parametrize( @pytest.mark.parametrize(

View File

@ -1,7 +1,6 @@
from typing import Annotated, Optional from typing import Annotated, Optional
import pytest import pytest
from dirty_equals import IsDict
from fastapi import Cookie, FastAPI from fastapi import Cookie, FastAPI
from fastapi.testclient import TestClient from fastapi.testclient import TestClient
from pydantic import BaseModel, Field from pydantic import BaseModel, Field
@ -32,26 +31,15 @@ async def read_model_optional_str(p: Annotated[CookieModelOptionalStr, Cookie()]
) )
def test_optional_str_schema(path: str): def test_optional_str_schema(path: str):
assert app.openapi()["paths"][path]["get"]["parameters"] == [ assert app.openapi()["paths"][path]["get"]["parameters"] == [
IsDict( {
{ "required": False,
"required": False, "schema": {
"schema": { "anyOf": [{"type": "string"}, {"type": "null"}],
"anyOf": [{"type": "string"}, {"type": "null"}], "title": "P",
"title": "P", },
}, "name": "p",
"name": "p", "in": "cookie",
"in": "cookie", }
}
)
| IsDict(
# TODO: remove when deprecating Pydantic v1
{
"required": False,
"schema": {"title": "P", "type": "string"},
"name": "p",
"in": "cookie",
}
)
] ]
@ -104,26 +92,15 @@ async def read_model_optional_alias(p: Annotated[CookieModelOptionalAlias, Cooki
) )
def test_optional_str_alias_schema(path: str): def test_optional_str_alias_schema(path: str):
assert app.openapi()["paths"][path]["get"]["parameters"] == [ assert app.openapi()["paths"][path]["get"]["parameters"] == [
IsDict( {
{ "required": False,
"required": False, "schema": {
"schema": { "anyOf": [{"type": "string"}, {"type": "null"}],
"anyOf": [{"type": "string"}, {"type": "null"}], "title": "P Alias",
"title": "P Alias", },
}, "name": "p_alias",
"name": "p_alias", "in": "cookie",
"in": "cookie", }
}
)
| IsDict(
# TODO: remove when deprecating Pydantic v1
{
"required": False,
"schema": {"title": "P Alias", "type": "string"},
"name": "p_alias",
"in": "cookie",
}
)
] ]

View File

@ -1,7 +1,7 @@
from typing import Annotated from typing import Annotated
import pytest import pytest
from dirty_equals import IsDict, IsOneOf from dirty_equals import IsOneOf
from fastapi import Cookie, FastAPI from fastapi import Cookie, FastAPI
from fastapi.testclient import TestClient from fastapi.testclient import TestClient
from pydantic import BaseModel, Field from pydantic import BaseModel, Field
@ -49,29 +49,16 @@ def test_required_str_missing(path: str):
client = TestClient(app) client = TestClient(app)
response = client.get(path) response = client.get(path)
assert response.status_code == 422 assert response.status_code == 422
assert response.json() == IsDict( assert response.json() == {
{ "detail": [
"detail": [ {
{ "type": "missing",
"type": "missing", "loc": ["cookie", "p"],
"loc": ["cookie", "p"], "msg": "Field required",
"msg": "Field required", "input": IsOneOf(None, {}),
"input": IsOneOf(None, {}), }
} ]
] }
}
) | IsDict(
# TODO: remove when deprecating Pydantic v1
{
"detail": [
{
"loc": ["cookie", "p"],
"msg": "field required",
"type": "value_error.missing",
}
]
}
)
@pytest.mark.parametrize( @pytest.mark.parametrize(
@ -127,29 +114,16 @@ def test_required_alias_missing(path: str):
client = TestClient(app) client = TestClient(app)
response = client.get(path) response = client.get(path)
assert response.status_code == 422 assert response.status_code == 422
assert response.json() == IsDict( assert response.json() == {
{ "detail": [
"detail": [ {
{ "type": "missing",
"type": "missing", "loc": ["cookie", "p_alias"],
"loc": ["cookie", "p_alias"], "msg": "Field required",
"msg": "Field required", "input": IsOneOf(None, {}),
"input": IsOneOf(None, {}), }
} ]
] }
}
) | IsDict(
# TODO: remove when deprecating Pydantic v1
{
"detail": [
{
"loc": ["cookie", "p_alias"],
"msg": "field required",
"type": "value_error.missing",
}
]
}
)
@pytest.mark.parametrize( @pytest.mark.parametrize(
@ -164,32 +138,19 @@ def test_required_alias_by_name(path: str):
client.cookies.set("p", "hello") client.cookies.set("p", "hello")
response = client.get(path) response = client.get(path)
assert response.status_code == 422 assert response.status_code == 422
assert response.json() == IsDict( assert response.json() == {
{ "detail": [
"detail": [ {
{ "type": "missing",
"type": "missing", "loc": ["cookie", "p_alias"],
"loc": ["cookie", "p_alias"], "msg": "Field required",
"msg": "Field required", "input": IsOneOf(
"input": IsOneOf( None,
None, {"p": "hello"},
{"p": "hello"}, ),
), }
} ]
] }
}
) | IsDict(
# TODO: remove when deprecating Pydantic v1
{
"detail": [
{
"loc": ["cookie", "p_alias"],
"msg": "field required",
"type": "value_error.missing",
}
]
}
)
@pytest.mark.parametrize( @pytest.mark.parametrize(

View File

@ -75,29 +75,16 @@ def test_list_missing(path: str):
client = TestClient(app) client = TestClient(app)
response = client.post(path) response = client.post(path)
assert response.status_code == 422 assert response.status_code == 422
assert response.json() == IsDict( assert response.json() == {
{ "detail": [
"detail": [ {
{ "type": "missing",
"type": "missing", "loc": ["body", "p"],
"loc": ["body", "p"], "msg": "Field required",
"msg": "Field required", "input": None,
"input": None, }
} ]
] }
}
) | IsDict(
# TODO: remove when deprecating Pydantic v1
{
"detail": [
{
"loc": ["body", "p"],
"msg": "field required",
"type": "value_error.missing",
}
]
}
)
@pytest.mark.parametrize( @pytest.mark.parametrize(
@ -182,29 +169,16 @@ def test_list_alias_missing(path: str):
client = TestClient(app) client = TestClient(app)
response = client.post(path) response = client.post(path)
assert response.status_code == 422 assert response.status_code == 422
assert response.json() == IsDict( assert response.json() == {
{ "detail": [
"detail": [ {
{ "type": "missing",
"type": "missing", "loc": ["body", "p_alias"],
"loc": ["body", "p_alias"], "msg": "Field required",
"msg": "Field required", "input": None,
"input": None, }
} ]
] }
}
) | IsDict(
# TODO: remove when deprecating Pydantic v1
{
"detail": [
{
"loc": ["body", "p_alias"],
"msg": "field required",
"type": "value_error.missing",
}
]
}
)
@pytest.mark.parametrize( @pytest.mark.parametrize(
@ -218,29 +192,16 @@ def test_list_alias_by_name(path: str):
client = TestClient(app) client = TestClient(app)
response = client.post(path, files=[("p", b"hello"), ("p", b"world")]) response = client.post(path, files=[("p", b"hello"), ("p", b"world")])
assert response.status_code == 422 assert response.status_code == 422
assert response.json() == IsDict( assert response.json() == {
{ "detail": [
"detail": [ {
{ "type": "missing",
"type": "missing", "loc": ["body", "p_alias"],
"loc": ["body", "p_alias"], "msg": "Field required",
"msg": "Field required", "input": None,
"input": None, }
} ]
] }
}
) | IsDict(
# TODO: remove when deprecating Pydantic v1
{
"detail": [
{
"loc": ["body", "p_alias"],
"msg": "field required",
"type": "value_error.missing",
}
]
}
)
@pytest.mark.parametrize( @pytest.mark.parametrize(

View File

@ -1,7 +1,6 @@
from typing import Annotated, Optional from typing import Annotated, Optional
import pytest import pytest
from dirty_equals import IsDict
from fastapi import FastAPI, File, UploadFile from fastapi import FastAPI, File, UploadFile
from fastapi.testclient import TestClient from fastapi.testclient import TestClient
@ -36,21 +35,13 @@ def test_optional_schema(path: str):
assert app.openapi()["components"]["schemas"][body_model_name] == { assert app.openapi()["components"]["schemas"][body_model_name] == {
"properties": { "properties": {
"p": ( "p": {
IsDict( "anyOf": [
{ {"type": "string", "format": "binary"},
"anyOf": [ {"type": "null"},
{"type": "string", "format": "binary"}, ],
{"type": "null"}, "title": "P",
], }
"title": "P",
}
)
| IsDict(
# TODO: remove when deprecating Pydantic v1
{"title": "P", "type": "string", "format": "binary"}
)
),
}, },
"title": body_model_name, "title": body_model_name,
"type": "object", "type": "object",
@ -116,21 +107,13 @@ def test_optional_alias_schema(path: str):
assert app.openapi()["components"]["schemas"][body_model_name] == { assert app.openapi()["components"]["schemas"][body_model_name] == {
"properties": { "properties": {
"p_alias": ( "p_alias": {
IsDict( "anyOf": [
{ {"type": "string", "format": "binary"},
"anyOf": [ {"type": "null"},
{"type": "string", "format": "binary"}, ],
{"type": "null"}, "title": "P Alias",
], }
"title": "P Alias",
}
)
| IsDict(
# TODO: remove when deprecating Pydantic v1
{"title": "P Alias", "type": "string", "format": "binary"}
)
),
}, },
"title": body_model_name, "title": body_model_name,
"type": "object", "type": "object",
@ -215,21 +198,13 @@ def test_optional_validation_alias_schema(path: str):
assert app.openapi()["components"]["schemas"][body_model_name] == { assert app.openapi()["components"]["schemas"][body_model_name] == {
"properties": { "properties": {
"p_val_alias": ( "p_val_alias": {
IsDict( "anyOf": [
{ {"type": "string", "format": "binary"},
"anyOf": [ {"type": "null"},
{"type": "string", "format": "binary"}, ],
{"type": "null"}, "title": "P Val Alias",
], }
"title": "P Val Alias",
}
)
| IsDict(
# TODO: remove when deprecating Pydantic v1
{"title": "P Val Alias", "type": "string", "format": "binary"}
)
),
}, },
"title": body_model_name, "title": body_model_name,
"type": "object", "type": "object",
@ -319,21 +294,13 @@ def test_optional_alias_and_validation_alias_schema(path: str):
assert app.openapi()["components"]["schemas"][body_model_name] == { assert app.openapi()["components"]["schemas"][body_model_name] == {
"properties": { "properties": {
"p_val_alias": ( "p_val_alias": {
IsDict( "anyOf": [
{ {"type": "string", "format": "binary"},
"anyOf": [ {"type": "null"},
{"type": "string", "format": "binary"}, ],
{"type": "null"}, "title": "P Val Alias",
], }
"title": "P Val Alias",
}
)
| IsDict(
# TODO: remove when deprecating Pydantic v1
{"title": "P Val Alias", "type": "string", "format": "binary"}
)
),
}, },
"title": body_model_name, "title": body_model_name,
"type": "object", "type": "object",

View File

@ -1,7 +1,6 @@
from typing import Annotated, Optional from typing import Annotated, Optional
import pytest import pytest
from dirty_equals import IsDict
from fastapi import FastAPI, File, UploadFile from fastapi import FastAPI, File, UploadFile
from fastapi.testclient import TestClient from fastapi.testclient import TestClient
@ -38,28 +37,16 @@ def test_optional_list_schema(path: str):
assert app.openapi()["components"]["schemas"][body_model_name] == { assert app.openapi()["components"]["schemas"][body_model_name] == {
"properties": { "properties": {
"p": ( "p": {
IsDict( "anyOf": [
{ {
"anyOf": [
{
"type": "array",
"items": {"type": "string", "format": "binary"},
},
{"type": "null"},
],
"title": "P",
}
)
| IsDict(
# TODO: remove when deprecating Pydantic v1
{
"title": "P",
"type": "array", "type": "array",
"items": {"type": "string", "format": "binary"}, "items": {"type": "string", "format": "binary"},
}, },
) {"type": "null"},
), ],
"title": "P",
}
}, },
"title": body_model_name, "title": body_model_name,
"type": "object", "type": "object",
@ -125,28 +112,16 @@ def test_optional_list_alias_schema(path: str):
assert app.openapi()["components"]["schemas"][body_model_name] == { assert app.openapi()["components"]["schemas"][body_model_name] == {
"properties": { "properties": {
"p_alias": ( "p_alias": {
IsDict( "anyOf": [
{ {
"anyOf": [
{
"type": "array",
"items": {"type": "string", "format": "binary"},
},
{"type": "null"},
],
"title": "P Alias",
}
)
| IsDict(
# TODO: remove when deprecating Pydantic v1
{
"title": "P Alias",
"type": "array", "type": "array",
"items": {"type": "string", "format": "binary"}, "items": {"type": "string", "format": "binary"},
} },
) {"type": "null"},
), ],
"title": "P Alias",
}
}, },
"title": body_model_name, "title": body_model_name,
"type": "object", "type": "object",
@ -228,28 +203,16 @@ def test_optional_validation_alias_schema(path: str):
assert app.openapi()["components"]["schemas"][body_model_name] == { assert app.openapi()["components"]["schemas"][body_model_name] == {
"properties": { "properties": {
"p_val_alias": ( "p_val_alias": {
IsDict( "anyOf": [
{ {
"anyOf": [
{
"type": "array",
"items": {"type": "string", "format": "binary"},
},
{"type": "null"},
],
"title": "P Val Alias",
}
)
| IsDict(
# TODO: remove when deprecating Pydantic v1
{
"title": "P Val Alias",
"type": "array", "type": "array",
"items": {"type": "string", "format": "binary"}, "items": {"type": "string", "format": "binary"},
} },
) {"type": "null"},
), ],
"title": "P Val Alias",
}
}, },
"title": body_model_name, "title": body_model_name,
"type": "object", "type": "object",
@ -336,28 +299,16 @@ def test_optional_list_alias_and_validation_alias_schema(path: str):
assert app.openapi()["components"]["schemas"][body_model_name] == { assert app.openapi()["components"]["schemas"][body_model_name] == {
"properties": { "properties": {
"p_val_alias": ( "p_val_alias": {
IsDict( "anyOf": [
{ {
"anyOf": [
{
"type": "array",
"items": {"type": "string", "format": "binary"},
},
{"type": "null"},
],
"title": "P Val Alias",
}
)
| IsDict(
# TODO: remove when deprecating Pydantic v1
{
"title": "P Val Alias",
"type": "array", "type": "array",
"items": {"type": "string", "format": "binary"}, "items": {"type": "string", "format": "binary"},
} },
) {"type": "null"},
), ],
"title": "P Val Alias",
}
}, },
"title": body_model_name, "title": body_model_name,
"type": "object", "type": "object",

View File

@ -1,7 +1,6 @@
from typing import Annotated from typing import Annotated
import pytest import pytest
from dirty_equals import IsDict
from fastapi import FastAPI, File, UploadFile from fastapi import FastAPI, File, UploadFile
from fastapi.testclient import TestClient from fastapi.testclient import TestClient
@ -55,29 +54,16 @@ def test_required_missing(path: str):
client = TestClient(app) client = TestClient(app)
response = client.post(path) response = client.post(path)
assert response.status_code == 422 assert response.status_code == 422
assert response.json() == IsDict( assert response.json() == {
{ "detail": [
"detail": [ {
{ "type": "missing",
"type": "missing", "loc": ["body", "p"],
"loc": ["body", "p"], "msg": "Field required",
"msg": "Field required", "input": None,
"input": None, }
} ]
] }
}
) | IsDict(
# TODO: remove when deprecating Pydantic v1
{
"detail": [
{
"loc": ["body", "p"],
"msg": "field required",
"type": "value_error.missing",
}
]
}
)
@pytest.mark.parametrize( @pytest.mark.parametrize(
@ -142,29 +128,16 @@ def test_required_alias_missing(path: str):
client = TestClient(app) client = TestClient(app)
response = client.post(path) response = client.post(path)
assert response.status_code == 422 assert response.status_code == 422
assert response.json() == IsDict( assert response.json() == {
{ "detail": [
"detail": [ {
{ "type": "missing",
"type": "missing", "loc": ["body", "p_alias"],
"loc": ["body", "p_alias"], "msg": "Field required",
"msg": "Field required", "input": None,
"input": None, }
} ]
] }
}
) | IsDict(
# TODO: remove when deprecating Pydantic v1
{
"detail": [
{
"loc": ["body", "p_alias"],
"msg": "field required",
"type": "value_error.missing",
}
]
}
)
@pytest.mark.parametrize( @pytest.mark.parametrize(
@ -178,29 +151,16 @@ def test_required_alias_by_name(path: str):
client = TestClient(app) client = TestClient(app)
response = client.post(path, files=[("p", b"hello")]) response = client.post(path, files=[("p", b"hello")])
assert response.status_code == 422 assert response.status_code == 422
assert response.json() == IsDict( assert response.json() == {
{ "detail": [
"detail": [ {
{ "type": "missing",
"type": "missing", "loc": ["body", "p_alias"],
"loc": ["body", "p_alias"], "msg": "Field required",
"msg": "Field required", "input": None,
"input": None, }
} ]
] }
}
) | IsDict(
# TODO: remove when deprecating Pydantic v1
{
"detail": [
{
"loc": ["body", "p_alias"],
"msg": "field required",
"type": "value_error.missing",
}
]
}
)
@pytest.mark.parametrize( @pytest.mark.parametrize(

View File

@ -146,29 +146,16 @@ def test_required_list_alias_missing(path: str):
client = TestClient(app) client = TestClient(app)
response = client.post(path) response = client.post(path)
assert response.status_code == 422 assert response.status_code == 422
assert response.json() == IsDict( assert response.json() == {
{ "detail": [
"detail": [ {
{ "type": "missing",
"type": "missing", "loc": ["body", "p_alias"],
"loc": ["body", "p_alias"], "msg": "Field required",
"msg": "Field required", "input": IsOneOf(None, {}),
"input": IsOneOf(None, {}), }
} ]
] }
}
) | IsDict(
# TODO: remove when deprecating Pydantic v1
{
"detail": [
{
"loc": ["body", "p_alias"],
"msg": "field required",
"type": "value_error.missing",
}
]
}
)
@pytest.mark.parametrize( @pytest.mark.parametrize(
@ -182,29 +169,16 @@ def test_required_list_alias_by_name(path: str):
client = TestClient(app) client = TestClient(app)
response = client.post(path, data={"p": ["hello", "world"]}) response = client.post(path, data={"p": ["hello", "world"]})
assert response.status_code == 422 assert response.status_code == 422
assert response.json() == IsDict( assert response.json() == {
{ "detail": [
"detail": [ {
{ "type": "missing",
"type": "missing", "loc": ["body", "p_alias"],
"loc": ["body", "p_alias"], "msg": "Field required",
"msg": "Field required", "input": IsOneOf(None, {"p": ["hello", "world"]}),
"input": IsOneOf(None, {"p": ["hello", "world"]}), }
} ]
] }
}
) | IsDict(
# TODO: remove when deprecating Pydantic v1
{
"detail": [
{
"loc": ["body", "p_alias"],
"msg": "field required",
"type": "value_error.missing",
}
]
}
)
@pytest.mark.parametrize( @pytest.mark.parametrize(

View File

@ -1,7 +1,6 @@
from typing import Annotated, Optional from typing import Annotated, Optional
import pytest import pytest
from dirty_equals import IsDict
from fastapi import FastAPI, Form from fastapi import FastAPI, Form
from fastapi.testclient import TestClient from fastapi.testclient import TestClient
from pydantic import BaseModel, Field from pydantic import BaseModel, Field
@ -38,30 +37,19 @@ def test_optional_list_str_schema(path: str):
openapi = app.openapi() openapi = app.openapi()
body_model_name = get_body_model_name(openapi, path) body_model_name = get_body_model_name(openapi, path)
assert app.openapi()["components"]["schemas"][body_model_name] == IsDict( assert app.openapi()["components"]["schemas"][body_model_name] == {
{ "properties": {
"properties": { "p": {
"p": { "anyOf": [
"anyOf": [ {"items": {"type": "string"}, "type": "array"},
{"items": {"type": "string"}, "type": "array"}, {"type": "null"},
{"type": "null"}, ],
], "title": "P",
"title": "P",
},
}, },
"title": body_model_name, },
"type": "object", "title": body_model_name,
} "type": "object",
) | IsDict( }
# TODO: remove when deprecating Pydantic v1
{
"properties": {
"p": {"items": {"type": "string"}, "type": "array", "title": "P"},
},
"title": body_model_name,
"type": "object",
}
)
@pytest.mark.parametrize( @pytest.mark.parametrize(
@ -119,34 +107,19 @@ def test_optional_list_str_alias_schema(path: str):
openapi = app.openapi() openapi = app.openapi()
body_model_name = get_body_model_name(openapi, path) body_model_name = get_body_model_name(openapi, path)
assert app.openapi()["components"]["schemas"][body_model_name] == IsDict( assert app.openapi()["components"]["schemas"][body_model_name] == {
{ "properties": {
"properties": { "p_alias": {
"p_alias": { "anyOf": [
"anyOf": [ {"items": {"type": "string"}, "type": "array"},
{"items": {"type": "string"}, "type": "array"}, {"type": "null"},
{"type": "null"}, ],
], "title": "P Alias",
"title": "P Alias",
},
}, },
"title": body_model_name, },
"type": "object", "title": body_model_name,
} "type": "object",
) | IsDict( }
# TODO: remove when deprecating Pydantic v1
{
"properties": {
"p_alias": {
"items": {"type": "string"},
"type": "array",
"title": "P Alias",
},
},
"title": body_model_name,
"type": "object",
}
)
@pytest.mark.parametrize( @pytest.mark.parametrize(
@ -217,34 +190,19 @@ def test_optional_list_validation_alias_schema(path: str):
openapi = app.openapi() openapi = app.openapi()
body_model_name = get_body_model_name(openapi, path) body_model_name = get_body_model_name(openapi, path)
assert app.openapi()["components"]["schemas"][body_model_name] == IsDict( assert app.openapi()["components"]["schemas"][body_model_name] == {
{ "properties": {
"properties": { "p_val_alias": {
"p_val_alias": { "anyOf": [
"anyOf": [ {"items": {"type": "string"}, "type": "array"},
{"items": {"type": "string"}, "type": "array"}, {"type": "null"},
{"type": "null"}, ],
], "title": "P Val Alias",
"title": "P Val Alias",
},
}, },
"title": body_model_name, },
"type": "object", "title": body_model_name,
} "type": "object",
) | IsDict( }
# TODO: remove when deprecating Pydantic v1
{
"properties": {
"p_val_alias": {
"items": {"type": "string"},
"type": "array",
"title": "P Val Alias",
},
},
"title": body_model_name,
"type": "object",
}
)
@pytest.mark.parametrize( @pytest.mark.parametrize(
@ -326,34 +284,19 @@ def test_optional_list_alias_and_validation_alias_schema(path: str):
openapi = app.openapi() openapi = app.openapi()
body_model_name = get_body_model_name(openapi, path) body_model_name = get_body_model_name(openapi, path)
assert app.openapi()["components"]["schemas"][body_model_name] == IsDict( assert app.openapi()["components"]["schemas"][body_model_name] == {
{ "properties": {
"properties": { "p_val_alias": {
"p_val_alias": { "anyOf": [
"anyOf": [ {"items": {"type": "string"}, "type": "array"},
{"items": {"type": "string"}, "type": "array"}, {"type": "null"},
{"type": "null"}, ],
], "title": "P Val Alias",
"title": "P Val Alias",
},
}, },
"title": body_model_name, },
"type": "object", "title": body_model_name,
} "type": "object",
) | IsDict( }
# TODO: remove when deprecating Pydantic v1
{
"properties": {
"p_val_alias": {
"items": {"type": "string"},
"type": "array",
"title": "P Val Alias",
},
},
"title": body_model_name,
"type": "object",
}
)
@pytest.mark.parametrize( @pytest.mark.parametrize(

View File

@ -1,7 +1,6 @@
from typing import Annotated, Optional from typing import Annotated, Optional
import pytest import pytest
from dirty_equals import IsDict
from fastapi import FastAPI, Form from fastapi import FastAPI, Form
from fastapi.testclient import TestClient from fastapi.testclient import TestClient
from pydantic import BaseModel, Field from pydantic import BaseModel, Field
@ -36,27 +35,16 @@ def test_optional_str_schema(path: str):
openapi = app.openapi() openapi = app.openapi()
body_model_name = get_body_model_name(openapi, path) body_model_name = get_body_model_name(openapi, path)
assert app.openapi()["components"]["schemas"][body_model_name] == IsDict( assert app.openapi()["components"]["schemas"][body_model_name] == {
{ "properties": {
"properties": { "p": {
"p": { "anyOf": [{"type": "string"}, {"type": "null"}],
"anyOf": [{"type": "string"}, {"type": "null"}], "title": "P",
"title": "P",
},
}, },
"title": body_model_name, },
"type": "object", "title": body_model_name,
} "type": "object",
) | IsDict( }
# TODO: remove when deprecating Pydantic v1
{
"properties": {
"p": {"type": "string", "title": "P"},
},
"title": body_model_name,
"type": "object",
}
)
@pytest.mark.parametrize( @pytest.mark.parametrize(
@ -112,27 +100,16 @@ def test_optional_str_alias_schema(path: str):
openapi = app.openapi() openapi = app.openapi()
body_model_name = get_body_model_name(openapi, path) body_model_name = get_body_model_name(openapi, path)
assert app.openapi()["components"]["schemas"][body_model_name] == IsDict( assert app.openapi()["components"]["schemas"][body_model_name] == {
{ "properties": {
"properties": { "p_alias": {
"p_alias": { "anyOf": [{"type": "string"}, {"type": "null"}],
"anyOf": [{"type": "string"}, {"type": "null"}], "title": "P Alias",
"title": "P Alias",
},
}, },
"title": body_model_name, },
"type": "object", "title": body_model_name,
} "type": "object",
) | IsDict( }
# TODO: remove when deprecating Pydantic v1
{
"properties": {
"p_alias": {"type": "string", "title": "P Alias"},
},
"title": body_model_name,
"type": "object",
}
)
@pytest.mark.parametrize( @pytest.mark.parametrize(
@ -200,27 +177,16 @@ def test_optional_validation_alias_schema(path: str):
openapi = app.openapi() openapi = app.openapi()
body_model_name = get_body_model_name(openapi, path) body_model_name = get_body_model_name(openapi, path)
assert app.openapi()["components"]["schemas"][body_model_name] == IsDict( assert app.openapi()["components"]["schemas"][body_model_name] == {
{ "properties": {
"properties": { "p_val_alias": {
"p_val_alias": { "anyOf": [{"type": "string"}, {"type": "null"}],
"anyOf": [{"type": "string"}, {"type": "null"}], "title": "P Val Alias",
"title": "P Val Alias",
},
}, },
"title": body_model_name, },
"type": "object", "title": body_model_name,
} "type": "object",
) | IsDict( }
# TODO: remove when deprecating Pydantic v1
{
"properties": {
"p_val_alias": {"type": "string", "title": "P Val Alias"},
},
"title": body_model_name,
"type": "object",
}
)
@pytest.mark.parametrize( @pytest.mark.parametrize(
@ -303,27 +269,16 @@ def test_optional_alias_and_validation_alias_schema(path: str):
openapi = app.openapi() openapi = app.openapi()
body_model_name = get_body_model_name(openapi, path) body_model_name = get_body_model_name(openapi, path)
assert app.openapi()["components"]["schemas"][body_model_name] == IsDict( assert app.openapi()["components"]["schemas"][body_model_name] == {
{ "properties": {
"properties": { "p_val_alias": {
"p_val_alias": { "anyOf": [{"type": "string"}, {"type": "null"}],
"anyOf": [{"type": "string"}, {"type": "null"}], "title": "P Val Alias",
"title": "P Val Alias",
},
}, },
"title": body_model_name, },
"type": "object", "title": body_model_name,
} "type": "object",
) | IsDict( }
# TODO: remove when deprecating Pydantic v1
{
"properties": {
"p_val_alias": {"type": "string", "title": "P Val Alias"},
},
"title": body_model_name,
"type": "object",
}
)
@pytest.mark.parametrize( @pytest.mark.parametrize(

View File

@ -1,7 +1,7 @@
from typing import Annotated from typing import Annotated
import pytest import pytest
from dirty_equals import IsDict, IsOneOf from dirty_equals import IsOneOf
from fastapi import FastAPI, Form from fastapi import FastAPI, Form
from fastapi.testclient import TestClient from fastapi.testclient import TestClient
from pydantic import BaseModel, Field from pydantic import BaseModel, Field
@ -54,29 +54,16 @@ def test_required_str_missing(path: str):
client = TestClient(app) client = TestClient(app)
response = client.post(path) response = client.post(path)
assert response.status_code == 422 assert response.status_code == 422
assert response.json() == IsDict( assert response.json() == {
{ "detail": [
"detail": [ {
{ "type": "missing",
"type": "missing", "loc": ["body", "p"],
"loc": ["body", "p"], "msg": "Field required",
"msg": "Field required", "input": IsOneOf(None, {}),
"input": IsOneOf(None, {}), }
} ]
] }
}
) | IsDict(
# TODO: remove when deprecating Pydantic v1
{
"detail": [
{
"loc": ["body", "p"],
"msg": "field required",
"type": "value_error.missing",
}
]
}
)
@pytest.mark.parametrize( @pytest.mark.parametrize(
@ -137,29 +124,16 @@ def test_required_alias_missing(path: str):
client = TestClient(app) client = TestClient(app)
response = client.post(path) response = client.post(path)
assert response.status_code == 422 assert response.status_code == 422
assert response.json() == IsDict( assert response.json() == {
{ "detail": [
"detail": [ {
{ "type": "missing",
"type": "missing", "loc": ["body", "p_alias"],
"loc": ["body", "p_alias"], "msg": "Field required",
"msg": "Field required", "input": IsOneOf(None, {}),
"input": IsOneOf(None, {}), }
} ]
] }
}
) | IsDict(
# TODO: remove when deprecating Pydantic v1
{
"detail": [
{
"loc": ["body", "p_alias"],
"msg": "field required",
"type": "value_error.missing",
}
]
}
)
@pytest.mark.parametrize( @pytest.mark.parametrize(
@ -170,29 +144,16 @@ def test_required_alias_by_name(path: str):
client = TestClient(app) client = TestClient(app)
response = client.post(path, data={"p": "hello"}) response = client.post(path, data={"p": "hello"})
assert response.status_code == 422 assert response.status_code == 422
assert response.json() == IsDict( assert response.json() == {
{ "detail": [
"detail": [ {
{ "type": "missing",
"type": "missing", "loc": ["body", "p_alias"],
"loc": ["body", "p_alias"], "msg": "Field required",
"msg": "Field required", "input": IsOneOf(None, {"p": "hello"}),
"input": IsOneOf(None, {"p": "hello"}), }
} ]
] }
}
) | IsDict(
# TODO: remove when deprecating Pydantic v1
{
"detail": [
{
"loc": ["body", "p_alias"],
"msg": "field required",
"type": "value_error.missing",
}
]
}
)
@pytest.mark.parametrize( @pytest.mark.parametrize(

View File

@ -135,29 +135,16 @@ def test_required_list_alias_missing(path: str):
client = TestClient(app) client = TestClient(app)
response = client.get(path) response = client.get(path)
assert response.status_code == 422 assert response.status_code == 422
assert response.json() == IsDict( assert response.json() == {
{ "detail": [
"detail": [ {
{ "type": "missing",
"type": "missing", "loc": ["header", "p_alias"],
"loc": ["header", "p_alias"], "msg": "Field required",
"msg": "Field required", "input": AnyThing,
"input": AnyThing, }
} ]
] }
}
) | IsDict(
# TODO: remove when deprecating Pydantic v1
{
"detail": [
{
"loc": ["header", "p_alias"],
"msg": "field required",
"type": "value_error.missing",
}
]
}
)
@pytest.mark.parametrize( @pytest.mark.parametrize(
@ -171,29 +158,16 @@ def test_required_list_alias_by_name(path: str):
client = TestClient(app) client = TestClient(app)
response = client.get(path, headers=[("p", "hello"), ("p", "world")]) response = client.get(path, headers=[("p", "hello"), ("p", "world")])
assert response.status_code == 422 assert response.status_code == 422
assert response.json() == IsDict( assert response.json() == {
{ "detail": [
"detail": [ {
{ "type": "missing",
"type": "missing", "loc": ["header", "p_alias"],
"loc": ["header", "p_alias"], "msg": "Field required",
"msg": "Field required", "input": IsOneOf(None, IsPartialDict({"p": ["hello", "world"]})),
"input": IsOneOf(None, IsPartialDict({"p": ["hello", "world"]})), }
} ]
] }
}
) | IsDict(
# TODO: remove when deprecating Pydantic v1
{
"detail": [
{
"loc": ["header", "p_alias"],
"msg": "field required",
"type": "value_error.missing",
}
]
}
)
@pytest.mark.parametrize( @pytest.mark.parametrize(

View File

@ -1,7 +1,6 @@
from typing import Annotated, Optional from typing import Annotated, Optional
import pytest import pytest
from dirty_equals import IsDict
from fastapi import FastAPI, Header from fastapi import FastAPI, Header
from fastapi.testclient import TestClient from fastapi.testclient import TestClient
from pydantic import BaseModel, Field from pydantic import BaseModel, Field
@ -36,29 +35,18 @@ async def read_model_optional_list_str(
) )
def test_optional_list_str_schema(path: str): def test_optional_list_str_schema(path: str):
assert app.openapi()["paths"][path]["get"]["parameters"] == [ assert app.openapi()["paths"][path]["get"]["parameters"] == [
IsDict( {
{ "required": False,
"required": False, "schema": {
"schema": { "anyOf": [
"anyOf": [ {"items": {"type": "string"}, "type": "array"},
{"items": {"type": "string"}, "type": "array"}, {"type": "null"},
{"type": "null"}, ],
], "title": "P",
"title": "P", },
}, "name": "p",
"name": "p", "in": "header",
"in": "header", }
}
)
| IsDict(
# TODO: remove when deprecating Pydantic v1
{
"required": False,
"schema": {"items": {"type": "string"}, "type": "array", "title": "P"},
"name": "p",
"in": "header",
}
)
] ]
@ -112,33 +100,18 @@ async def read_model_optional_list_alias(
) )
def test_optional_list_str_alias_schema(path: str): def test_optional_list_str_alias_schema(path: str):
assert app.openapi()["paths"][path]["get"]["parameters"] == [ assert app.openapi()["paths"][path]["get"]["parameters"] == [
IsDict( {
{ "required": False,
"required": False, "schema": {
"schema": { "anyOf": [
"anyOf": [ {"items": {"type": "string"}, "type": "array"},
{"items": {"type": "string"}, "type": "array"}, {"type": "null"},
{"type": "null"}, ],
], "title": "P Alias",
"title": "P Alias", },
}, "name": "p_alias",
"name": "p_alias", "in": "header",
"in": "header", }
}
)
| IsDict(
# TODO: remove when deprecating Pydantic v1
{
"required": False,
"schema": {
"items": {"type": "string"},
"type": "array",
"title": "P Alias",
},
"name": "p_alias",
"in": "header",
}
)
] ]

View File

@ -1,7 +1,6 @@
from typing import Annotated, Optional from typing import Annotated, Optional
import pytest import pytest
from dirty_equals import IsDict
from fastapi import FastAPI, Header from fastapi import FastAPI, Header
from fastapi.testclient import TestClient from fastapi.testclient import TestClient
from pydantic import BaseModel, Field from pydantic import BaseModel, Field
@ -32,26 +31,15 @@ async def read_model_optional_str(p: Annotated[HeaderModelOptionalStr, Header()]
) )
def test_optional_str_schema(path: str): def test_optional_str_schema(path: str):
assert app.openapi()["paths"][path]["get"]["parameters"] == [ assert app.openapi()["paths"][path]["get"]["parameters"] == [
IsDict( {
{ "required": False,
"required": False, "schema": {
"schema": { "anyOf": [{"type": "string"}, {"type": "null"}],
"anyOf": [{"type": "string"}, {"type": "null"}], "title": "P",
"title": "P", },
}, "name": "p",
"name": "p", "in": "header",
"in": "header", }
}
)
| IsDict(
# TODO: remove when deprecating Pydantic v1
{
"required": False,
"schema": {"title": "P", "type": "string"},
"name": "p",
"in": "header",
}
)
] ]
@ -103,26 +91,15 @@ async def read_model_optional_alias(p: Annotated[HeaderModelOptionalAlias, Heade
) )
def test_optional_str_alias_schema(path: str): def test_optional_str_alias_schema(path: str):
assert app.openapi()["paths"][path]["get"]["parameters"] == [ assert app.openapi()["paths"][path]["get"]["parameters"] == [
IsDict( {
{ "required": False,
"required": False, "schema": {
"schema": { "anyOf": [{"type": "string"}, {"type": "null"}],
"anyOf": [{"type": "string"}, {"type": "null"}], "title": "P Alias",
"title": "P Alias", },
}, "name": "p_alias",
"name": "p_alias", "in": "header",
"in": "header", }
}
)
| IsDict(
# TODO: remove when deprecating Pydantic v1
{
"required": False,
"schema": {"title": "P Alias", "type": "string"},
"name": "p_alias",
"in": "header",
}
)
] ]

View File

@ -1,7 +1,7 @@
from typing import Annotated from typing import Annotated
import pytest import pytest
from dirty_equals import AnyThing, IsDict, IsOneOf, IsPartialDict from dirty_equals import AnyThing, IsOneOf, IsPartialDict
from fastapi import FastAPI, Header from fastapi import FastAPI, Header
from fastapi.testclient import TestClient from fastapi.testclient import TestClient
from pydantic import BaseModel, Field from pydantic import BaseModel, Field
@ -49,29 +49,16 @@ def test_required_str_missing(path: str):
client = TestClient(app) client = TestClient(app)
response = client.get(path) response = client.get(path)
assert response.status_code == 422 assert response.status_code == 422
assert response.json() == IsDict( assert response.json() == {
{ "detail": [
"detail": [ {
{ "type": "missing",
"type": "missing", "loc": ["header", "p"],
"loc": ["header", "p"], "msg": "Field required",
"msg": "Field required", "input": AnyThing,
"input": AnyThing, }
} ]
] }
}
) | IsDict(
# TODO: remove when deprecating Pydantic v1
{
"detail": [
{
"loc": ["header", "p"],
"msg": "field required",
"type": "value_error.missing",
}
]
}
)
@pytest.mark.parametrize( @pytest.mark.parametrize(
@ -126,29 +113,16 @@ def test_required_alias_missing(path: str):
client = TestClient(app) client = TestClient(app)
response = client.get(path) response = client.get(path)
assert response.status_code == 422 assert response.status_code == 422
assert response.json() == IsDict( assert response.json() == {
{ "detail": [
"detail": [ {
{ "type": "missing",
"type": "missing", "loc": ["header", "p_alias"],
"loc": ["header", "p_alias"], "msg": "Field required",
"msg": "Field required", "input": AnyThing,
"input": AnyThing, }
} ]
] }
}
) | IsDict(
# TODO: remove when deprecating Pydantic v1
{
"detail": [
{
"loc": ["header", "p_alias"],
"msg": "field required",
"type": "value_error.missing",
}
]
}
)
@pytest.mark.parametrize( @pytest.mark.parametrize(
@ -162,29 +136,16 @@ def test_required_alias_by_name(path: str):
client = TestClient(app) client = TestClient(app)
response = client.get(path, headers={"p": "hello"}) response = client.get(path, headers={"p": "hello"})
assert response.status_code == 422 assert response.status_code == 422
assert response.json() == IsDict( assert response.json() == {
{ "detail": [
"detail": [ {
{ "type": "missing",
"type": "missing", "loc": ["header", "p_alias"],
"loc": ["header", "p_alias"], "msg": "Field required",
"msg": "Field required", "input": IsOneOf(None, IsPartialDict({"p": "hello"})),
"input": IsOneOf(None, IsPartialDict({"p": "hello"})), }
} ]
] }
}
) | IsDict(
# TODO: remove when deprecating Pydantic v1
{
"detail": [
{
"loc": ["header", "p_alias"],
"msg": "field required",
"type": "value_error.missing",
}
]
}
)
@pytest.mark.parametrize( @pytest.mark.parametrize(

View File

@ -135,29 +135,16 @@ def test_required_list_alias_missing(path: str):
client = TestClient(app) client = TestClient(app)
response = client.get(path) response = client.get(path)
assert response.status_code == 422 assert response.status_code == 422
assert response.json() == IsDict( assert response.json() == {
{ "detail": [
"detail": [ {
{ "type": "missing",
"type": "missing", "loc": ["query", "p_alias"],
"loc": ["query", "p_alias"], "msg": "Field required",
"msg": "Field required", "input": IsOneOf(None, {}),
"input": IsOneOf(None, {}), }
} ]
] }
}
) | IsDict(
# TODO: remove when deprecating Pydantic v1
{
"detail": [
{
"loc": ["query", "p_alias"],
"msg": "field required",
"type": "value_error.missing",
}
]
}
)
@pytest.mark.parametrize( @pytest.mark.parametrize(
@ -171,29 +158,16 @@ def test_required_list_alias_by_name(path: str):
client = TestClient(app) client = TestClient(app)
response = client.get(f"{path}?p=hello&p=world") response = client.get(f"{path}?p=hello&p=world")
assert response.status_code == 422 assert response.status_code == 422
assert response.json() == IsDict( assert response.json() == {
{ "detail": [
"detail": [ {
{ "type": "missing",
"type": "missing", "loc": ["query", "p_alias"],
"loc": ["query", "p_alias"], "msg": "Field required",
"msg": "Field required", "input": IsOneOf(None, {"p": ["hello", "world"]}),
"input": IsOneOf(None, {"p": ["hello", "world"]}), }
} ]
] }
}
) | IsDict(
# TODO: remove when deprecating Pydantic v1
{
"detail": [
{
"loc": ["query", "p_alias"],
"msg": "field required",
"type": "value_error.missing",
}
]
}
)
@pytest.mark.parametrize( @pytest.mark.parametrize(

View File

@ -1,7 +1,6 @@
from typing import Annotated, Optional from typing import Annotated, Optional
import pytest import pytest
from dirty_equals import IsDict
from fastapi import FastAPI, Query from fastapi import FastAPI, Query
from fastapi.testclient import TestClient from fastapi.testclient import TestClient
from pydantic import BaseModel, Field from pydantic import BaseModel, Field
@ -36,29 +35,18 @@ async def read_model_optional_list_str(
) )
def test_optional_list_str_schema(path: str): def test_optional_list_str_schema(path: str):
assert app.openapi()["paths"][path]["get"]["parameters"] == [ assert app.openapi()["paths"][path]["get"]["parameters"] == [
IsDict( {
{ "required": False,
"required": False, "schema": {
"schema": { "anyOf": [
"anyOf": [ {"items": {"type": "string"}, "type": "array"},
{"items": {"type": "string"}, "type": "array"}, {"type": "null"},
{"type": "null"}, ],
], "title": "P",
"title": "P", },
}, "name": "p",
"name": "p", "in": "query",
"in": "query", }
}
)
| IsDict(
# TODO: remove when deprecating Pydantic v1
{
"required": False,
"schema": {"items": {"type": "string"}, "type": "array", "title": "P"},
"name": "p",
"in": "query",
}
)
] ]
@ -112,33 +100,18 @@ async def read_model_optional_list_alias(
) )
def test_optional_list_str_alias_schema(path: str): def test_optional_list_str_alias_schema(path: str):
assert app.openapi()["paths"][path]["get"]["parameters"] == [ assert app.openapi()["paths"][path]["get"]["parameters"] == [
IsDict( {
{ "required": False,
"required": False, "schema": {
"schema": { "anyOf": [
"anyOf": [ {"items": {"type": "string"}, "type": "array"},
{"items": {"type": "string"}, "type": "array"}, {"type": "null"},
{"type": "null"}, ],
], "title": "P Alias",
"title": "P Alias", },
}, "name": "p_alias",
"name": "p_alias", "in": "query",
"in": "query", }
}
)
| IsDict(
# TODO: remove when deprecating Pydantic v1
{
"required": False,
"schema": {
"items": {"type": "string"},
"type": "array",
"title": "P Alias",
},
"name": "p_alias",
"in": "query",
}
)
] ]

View File

@ -1,7 +1,6 @@
from typing import Annotated, Optional from typing import Annotated, Optional
import pytest import pytest
from dirty_equals import IsDict
from fastapi import FastAPI, Query from fastapi import FastAPI, Query
from fastapi.testclient import TestClient from fastapi.testclient import TestClient
from pydantic import BaseModel, Field from pydantic import BaseModel, Field
@ -32,26 +31,15 @@ async def read_model_optional_str(p: Annotated[QueryModelOptionalStr, Query()]):
) )
def test_optional_str_schema(path: str): def test_optional_str_schema(path: str):
assert app.openapi()["paths"][path]["get"]["parameters"] == [ assert app.openapi()["paths"][path]["get"]["parameters"] == [
IsDict( {
{ "required": False,
"required": False, "schema": {
"schema": { "anyOf": [{"type": "string"}, {"type": "null"}],
"anyOf": [{"type": "string"}, {"type": "null"}], "title": "P",
"title": "P", },
}, "name": "p",
"name": "p", "in": "query",
"in": "query", }
}
)
| IsDict(
# TODO: remove when deprecating Pydantic v1
{
"required": False,
"schema": {"title": "P", "type": "string"},
"name": "p",
"in": "query",
}
)
] ]
@ -103,26 +91,15 @@ async def read_model_optional_alias(p: Annotated[QueryModelOptionalAlias, Query(
) )
def test_optional_str_alias_schema(path: str): def test_optional_str_alias_schema(path: str):
assert app.openapi()["paths"][path]["get"]["parameters"] == [ assert app.openapi()["paths"][path]["get"]["parameters"] == [
IsDict( {
{ "required": False,
"required": False, "schema": {
"schema": { "anyOf": [{"type": "string"}, {"type": "null"}],
"anyOf": [{"type": "string"}, {"type": "null"}], "title": "P Alias",
"title": "P Alias", },
}, "name": "p_alias",
"name": "p_alias", "in": "query",
"in": "query", }
}
)
| IsDict(
# TODO: remove when deprecating Pydantic v1
{
"required": False,
"schema": {"title": "P Alias", "type": "string"},
"name": "p_alias",
"in": "query",
}
)
] ]

View File

@ -1,7 +1,7 @@
from typing import Annotated from typing import Annotated
import pytest import pytest
from dirty_equals import IsDict, IsOneOf from dirty_equals import IsOneOf
from fastapi import FastAPI, Query from fastapi import FastAPI, Query
from fastapi.testclient import TestClient from fastapi.testclient import TestClient
from pydantic import BaseModel, Field from pydantic import BaseModel, Field
@ -49,29 +49,16 @@ def test_required_str_missing(path: str):
client = TestClient(app) client = TestClient(app)
response = client.get(path) response = client.get(path)
assert response.status_code == 422 assert response.status_code == 422
assert response.json() == IsDict( assert response.json() == {
{ "detail": [
"detail": [ {
{ "type": "missing",
"type": "missing", "loc": ["query", "p"],
"loc": ["query", "p"], "msg": "Field required",
"msg": "Field required", "input": IsOneOf(None, {}),
"input": IsOneOf(None, {}), }
} ]
] }
}
) | IsDict(
# TODO: remove when deprecating Pydantic v1
{
"detail": [
{
"loc": ["query", "p"],
"msg": "field required",
"type": "value_error.missing",
}
]
}
)
@pytest.mark.parametrize( @pytest.mark.parametrize(
@ -126,29 +113,16 @@ def test_required_alias_missing(path: str):
client = TestClient(app) client = TestClient(app)
response = client.get(path) response = client.get(path)
assert response.status_code == 422 assert response.status_code == 422
assert response.json() == IsDict( assert response.json() == {
{ "detail": [
"detail": [ {
{ "type": "missing",
"type": "missing", "loc": ["query", "p_alias"],
"loc": ["query", "p_alias"], "msg": "Field required",
"msg": "Field required", "input": IsOneOf(None, {}),
"input": IsOneOf(None, {}), }
} ]
] }
}
) | IsDict(
# TODO: remove when deprecating Pydantic v1
{
"detail": [
{
"loc": ["query", "p_alias"],
"msg": "field required",
"type": "value_error.missing",
}
]
}
)
@pytest.mark.parametrize( @pytest.mark.parametrize(
@ -162,32 +136,19 @@ def test_required_alias_by_name(path: str):
client = TestClient(app) client = TestClient(app)
response = client.get(f"{path}?p=hello") response = client.get(f"{path}?p=hello")
assert response.status_code == 422 assert response.status_code == 422
assert response.json() == IsDict( assert response.json() == {
{ "detail": [
"detail": [ {
{ "type": "missing",
"type": "missing", "loc": ["query", "p_alias"],
"loc": ["query", "p_alias"], "msg": "Field required",
"msg": "Field required", "input": IsOneOf(
"input": IsOneOf( None,
None, {"p": "hello"},
{"p": "hello"}, ),
), }
} ]
] }
}
) | IsDict(
# TODO: remove when deprecating Pydantic v1
{
"detail": [
{
"loc": ["query", "p_alias"],
"msg": "field required",
"type": "value_error.missing",
}
]
}
)
@pytest.mark.parametrize( @pytest.mark.parametrize(

View File

@ -1,7 +1,6 @@
from typing import Union from typing import Union
import pytest import pytest
from dirty_equals import IsDict
from fastapi import Body, Cookie, FastAPI, Header, Path, Query from fastapi import Body, Cookie, FastAPI, Header, Path, Query
from fastapi.exceptions import FastAPIDeprecationWarning from fastapi.exceptions import FastAPIDeprecationWarning
from fastapi.testclient import TestClient from fastapi.testclient import TestClient
@ -336,28 +335,13 @@ def test_openapi_schema():
"requestBody": { "requestBody": {
"content": { "content": {
"application/json": { "application/json": {
"schema": IsDict( "schema": {
{ "$ref": "#/components/schemas/Item",
"$ref": "#/components/schemas/Item", "examples": [
"examples": [ {"data": "Data in Body examples, example1"},
{"data": "Data in Body examples, example1"}, {"data": "Data in Body examples, example2"},
{"data": "Data in Body examples, example2"}, ],
], }
}
)
| IsDict(
# TODO: remove this when deprecating Pydantic v1
{
"allOf": [
{"$ref": "#/components/schemas/Item"}
],
"title": "Item",
"examples": [
{"data": "Data in Body examples, example1"},
{"data": "Data in Body examples, example2"},
],
}
)
} }
}, },
"required": True, "required": True,
@ -387,28 +371,13 @@ def test_openapi_schema():
"requestBody": { "requestBody": {
"content": { "content": {
"application/json": { "application/json": {
"schema": IsDict( "schema": {
{ "$ref": "#/components/schemas/Item",
"$ref": "#/components/schemas/Item", "examples": [
"examples": [ {"data": "examples example_examples 1"},
{"data": "examples example_examples 1"}, {"data": "examples example_examples 2"},
{"data": "examples example_examples 2"}, ],
], },
}
)
| IsDict(
# TODO: remove this when deprecating Pydantic v1
{
"allOf": [
{"$ref": "#/components/schemas/Item"}
],
"title": "Item",
"examples": [
{"data": "examples example_examples 1"},
{"data": "examples example_examples 2"},
],
},
),
"example": {"data": "Overridden example"}, "example": {"data": "Overridden example"},
} }
}, },
@ -539,16 +508,10 @@ def test_openapi_schema():
"parameters": [ "parameters": [
{ {
"required": False, "required": False,
"schema": IsDict( "schema": {
{ "anyOf": [{"type": "string"}, {"type": "null"}],
"anyOf": [{"type": "string"}, {"type": "null"}], "title": "Data",
"title": "Data", },
}
)
| IsDict(
# TODO: Remove this when deprecating Pydantic v1
{"title": "Data", "type": "string"}
),
"example": "query1", "example": "query1",
"name": "data", "name": "data",
"in": "query", "in": "query",
@ -579,21 +542,11 @@ def test_openapi_schema():
"parameters": [ "parameters": [
{ {
"required": False, "required": False,
"schema": IsDict( "schema": {
{ "anyOf": [{"type": "string"}, {"type": "null"}],
"anyOf": [{"type": "string"}, {"type": "null"}], "title": "Data",
"title": "Data", "examples": ["query1", "query2"],
"examples": ["query1", "query2"], },
}
)
| IsDict(
# TODO: Remove this when deprecating Pydantic v1
{
"type": "string",
"title": "Data",
"examples": ["query1", "query2"],
}
),
"name": "data", "name": "data",
"in": "query", "in": "query",
} }
@ -623,21 +576,11 @@ def test_openapi_schema():
"parameters": [ "parameters": [
{ {
"required": False, "required": False,
"schema": IsDict( "schema": {
{ "anyOf": [{"type": "string"}, {"type": "null"}],
"anyOf": [{"type": "string"}, {"type": "null"}], "title": "Data",
"title": "Data", "examples": ["query1", "query2"],
"examples": ["query1", "query2"], },
}
)
| IsDict(
# TODO: Remove this when deprecating Pydantic v1
{
"type": "string",
"title": "Data",
"examples": ["query1", "query2"],
}
),
"example": "query_overridden", "example": "query_overridden",
"name": "data", "name": "data",
"in": "query", "in": "query",
@ -668,16 +611,10 @@ def test_openapi_schema():
"parameters": [ "parameters": [
{ {
"required": False, "required": False,
"schema": IsDict( "schema": {
{ "anyOf": [{"type": "string"}, {"type": "null"}],
"anyOf": [{"type": "string"}, {"type": "null"}], "title": "Data",
"title": "Data", },
}
)
| IsDict(
# TODO: Remove this when deprecating Pydantic v1
{"title": "Data", "type": "string"}
),
"example": "header1", "example": "header1",
"name": "data", "name": "data",
"in": "header", "in": "header",
@ -708,21 +645,11 @@ def test_openapi_schema():
"parameters": [ "parameters": [
{ {
"required": False, "required": False,
"schema": IsDict( "schema": {
{ "anyOf": [{"type": "string"}, {"type": "null"}],
"anyOf": [{"type": "string"}, {"type": "null"}], "title": "Data",
"title": "Data", "examples": ["header1", "header2"],
"examples": ["header1", "header2"], },
}
)
| IsDict(
# TODO: Remove this when deprecating Pydantic v1
{
"type": "string",
"title": "Data",
"examples": ["header1", "header2"],
}
),
"name": "data", "name": "data",
"in": "header", "in": "header",
} }
@ -752,21 +679,11 @@ def test_openapi_schema():
"parameters": [ "parameters": [
{ {
"required": False, "required": False,
"schema": IsDict( "schema": {
{ "anyOf": [{"type": "string"}, {"type": "null"}],
"anyOf": [{"type": "string"}, {"type": "null"}], "title": "Data",
"title": "Data", "examples": ["header1", "header2"],
"examples": ["header1", "header2"], },
}
)
| IsDict(
# TODO: Remove this when deprecating Pydantic v1
{
"title": "Data",
"type": "string",
"examples": ["header1", "header2"],
}
),
"example": "header_overridden", "example": "header_overridden",
"name": "data", "name": "data",
"in": "header", "in": "header",
@ -797,16 +714,10 @@ def test_openapi_schema():
"parameters": [ "parameters": [
{ {
"required": False, "required": False,
"schema": IsDict( "schema": {
{ "anyOf": [{"type": "string"}, {"type": "null"}],
"anyOf": [{"type": "string"}, {"type": "null"}], "title": "Data",
"title": "Data", },
}
)
| IsDict(
# TODO: Remove this when deprecating Pydantic v1
{"title": "Data", "type": "string"}
),
"example": "cookie1", "example": "cookie1",
"name": "data", "name": "data",
"in": "cookie", "in": "cookie",
@ -837,21 +748,11 @@ def test_openapi_schema():
"parameters": [ "parameters": [
{ {
"required": False, "required": False,
"schema": IsDict( "schema": {
{ "anyOf": [{"type": "string"}, {"type": "null"}],
"anyOf": [{"type": "string"}, {"type": "null"}], "title": "Data",
"title": "Data", "examples": ["cookie1", "cookie2"],
"examples": ["cookie1", "cookie2"], },
}
)
| IsDict(
# TODO: Remove this when deprecating Pydantic v1
{
"title": "Data",
"type": "string",
"examples": ["cookie1", "cookie2"],
}
),
"name": "data", "name": "data",
"in": "cookie", "in": "cookie",
} }
@ -881,21 +782,11 @@ def test_openapi_schema():
"parameters": [ "parameters": [
{ {
"required": False, "required": False,
"schema": IsDict( "schema": {
{ "anyOf": [{"type": "string"}, {"type": "null"}],
"anyOf": [{"type": "string"}, {"type": "null"}], "title": "Data",
"title": "Data", "examples": ["cookie1", "cookie2"],
"examples": ["cookie1", "cookie2"], },
}
)
| IsDict(
# TODO: Remove this when deprecating Pydantic v1
{
"title": "Data",
"type": "string",
"examples": ["cookie1", "cookie2"],
}
),
"example": "cookie_overridden", "example": "cookie_overridden",
"name": "data", "name": "data",
"in": "cookie", "in": "cookie",

View File

@ -1,5 +1,4 @@
import pytest import pytest
from dirty_equals import IsDict
from fastapi import Depends, FastAPI, Security from fastapi import Depends, FastAPI, Security
from fastapi.security import OAuth2, OAuth2PasswordRequestFormStrict from fastapi.security import OAuth2, OAuth2PasswordRequestFormStrict
from fastapi.testclient import TestClient from fastapi.testclient import TestClient
@ -64,79 +63,43 @@ def test_security_oauth2_password_bearer_no_header():
def test_strict_login_no_data(): def test_strict_login_no_data():
response = client.post("/login") response = client.post("/login")
assert response.status_code == 422 assert response.status_code == 422
assert response.json() == IsDict( assert response.json() == {
{ "detail": [
"detail": [ {
{ "type": "missing",
"type": "missing", "loc": ["body", "grant_type"],
"loc": ["body", "grant_type"], "msg": "Field required",
"msg": "Field required", "input": None,
"input": None, },
}, {
{ "type": "missing",
"type": "missing", "loc": ["body", "username"],
"loc": ["body", "username"], "msg": "Field required",
"msg": "Field required", "input": None,
"input": None, },
}, {
{ "type": "missing",
"type": "missing", "loc": ["body", "password"],
"loc": ["body", "password"], "msg": "Field required",
"msg": "Field required", "input": None,
"input": None, },
}, ]
] }
}
) | IsDict(
# TODO: remove when deprecating Pydantic v1
{
"detail": [
{
"loc": ["body", "grant_type"],
"msg": "field required",
"type": "value_error.missing",
},
{
"loc": ["body", "username"],
"msg": "field required",
"type": "value_error.missing",
},
{
"loc": ["body", "password"],
"msg": "field required",
"type": "value_error.missing",
},
]
}
)
def test_strict_login_no_grant_type(): def test_strict_login_no_grant_type():
response = client.post("/login", data={"username": "johndoe", "password": "secret"}) response = client.post("/login", data={"username": "johndoe", "password": "secret"})
assert response.status_code == 422 assert response.status_code == 422
assert response.json() == IsDict( assert response.json() == {
{ "detail": [
"detail": [ {
{ "type": "missing",
"type": "missing", "loc": ["body", "grant_type"],
"loc": ["body", "grant_type"], "msg": "Field required",
"msg": "Field required", "input": None,
"input": None, }
} ]
] }
}
) | IsDict(
# TODO: remove when deprecating Pydantic v1
{
"detail": [
{
"loc": ["body", "grant_type"],
"msg": "field required",
"type": "value_error.missing",
}
]
}
)
@pytest.mark.parametrize( @pytest.mark.parametrize(
@ -153,31 +116,17 @@ def test_strict_login_incorrect_grant_type(grant_type: str):
data={"username": "johndoe", "password": "secret", "grant_type": grant_type}, data={"username": "johndoe", "password": "secret", "grant_type": grant_type},
) )
assert response.status_code == 422 assert response.status_code == 422
assert response.json() == IsDict( assert response.json() == {
{ "detail": [
"detail": [ {
{ "type": "string_pattern_mismatch",
"type": "string_pattern_mismatch", "loc": ["body", "grant_type"],
"loc": ["body", "grant_type"], "msg": "String should match pattern '^password$'",
"msg": "String should match pattern '^password$'", "input": grant_type,
"input": grant_type, "ctx": {"pattern": "^password$"},
"ctx": {"pattern": "^password$"}, }
} ]
] }
}
) | IsDict(
# TODO: remove when deprecating Pydantic v1
{
"detail": [
{
"loc": ["body", "grant_type"],
"msg": 'string does not match regex "^password$"',
"type": "value_error.str.regex",
"ctx": {"pattern": "^password$"},
}
]
}
)
def test_strict_login_correct_grant_type(): def test_strict_login_correct_grant_type():
@ -264,26 +213,14 @@ def test_openapi_schema():
"username": {"title": "Username", "type": "string"}, "username": {"title": "Username", "type": "string"},
"password": {"title": "Password", "type": "string"}, "password": {"title": "Password", "type": "string"},
"scope": {"title": "Scope", "type": "string", "default": ""}, "scope": {"title": "Scope", "type": "string", "default": ""},
"client_id": IsDict( "client_id": {
{ "title": "Client Id",
"title": "Client Id", "anyOf": [{"type": "string"}, {"type": "null"}],
"anyOf": [{"type": "string"}, {"type": "null"}], },
} "client_secret": {
) "title": "Client Secret",
| IsDict( "anyOf": [{"type": "string"}, {"type": "null"}],
# TODO: remove when deprecating Pydantic v1 },
{"title": "Client Id", "type": "string"}
),
"client_secret": IsDict(
{
"title": "Client Secret",
"anyOf": [{"type": "string"}, {"type": "null"}],
}
)
| IsDict(
# TODO: remove when deprecating Pydantic v1
{"title": "Client Secret", "type": "string"}
),
}, },
}, },
"ValidationError": { "ValidationError": {

View File

@ -1,7 +1,6 @@
from typing import Optional from typing import Optional
import pytest import pytest
from dirty_equals import IsDict
from fastapi import Depends, FastAPI, Security from fastapi import Depends, FastAPI, Security
from fastapi.security import OAuth2, OAuth2PasswordRequestFormStrict from fastapi.security import OAuth2, OAuth2PasswordRequestFormStrict
from fastapi.testclient import TestClient from fastapi.testclient import TestClient
@ -67,79 +66,43 @@ def test_security_oauth2_password_bearer_no_header():
def test_strict_login_no_data(): def test_strict_login_no_data():
response = client.post("/login") response = client.post("/login")
assert response.status_code == 422 assert response.status_code == 422
assert response.json() == IsDict( assert response.json() == {
{ "detail": [
"detail": [ {
{ "type": "missing",
"type": "missing", "loc": ["body", "grant_type"],
"loc": ["body", "grant_type"], "msg": "Field required",
"msg": "Field required", "input": None,
"input": None, },
}, {
{ "type": "missing",
"type": "missing", "loc": ["body", "username"],
"loc": ["body", "username"], "msg": "Field required",
"msg": "Field required", "input": None,
"input": None, },
}, {
{ "type": "missing",
"type": "missing", "loc": ["body", "password"],
"loc": ["body", "password"], "msg": "Field required",
"msg": "Field required", "input": None,
"input": None, },
}, ]
] }
}
) | IsDict(
# TODO: remove when deprecating Pydantic v1
{
"detail": [
{
"loc": ["body", "grant_type"],
"msg": "field required",
"type": "value_error.missing",
},
{
"loc": ["body", "username"],
"msg": "field required",
"type": "value_error.missing",
},
{
"loc": ["body", "password"],
"msg": "field required",
"type": "value_error.missing",
},
]
}
)
def test_strict_login_no_grant_type(): def test_strict_login_no_grant_type():
response = client.post("/login", data={"username": "johndoe", "password": "secret"}) response = client.post("/login", data={"username": "johndoe", "password": "secret"})
assert response.status_code == 422 assert response.status_code == 422
assert response.json() == IsDict( assert response.json() == {
{ "detail": [
"detail": [ {
{ "type": "missing",
"type": "missing", "loc": ["body", "grant_type"],
"loc": ["body", "grant_type"], "msg": "Field required",
"msg": "Field required", "input": None,
"input": None, }
} ]
] }
}
) | IsDict(
# TODO: remove when deprecating Pydantic v1
{
"detail": [
{
"loc": ["body", "grant_type"],
"msg": "field required",
"type": "value_error.missing",
}
]
}
)
@pytest.mark.parametrize( @pytest.mark.parametrize(
@ -156,31 +119,17 @@ def test_strict_login_incorrect_grant_type(grant_type: str):
data={"username": "johndoe", "password": "secret", "grant_type": grant_type}, data={"username": "johndoe", "password": "secret", "grant_type": grant_type},
) )
assert response.status_code == 422 assert response.status_code == 422
assert response.json() == IsDict( assert response.json() == {
{ "detail": [
"detail": [ {
{ "type": "string_pattern_mismatch",
"type": "string_pattern_mismatch", "loc": ["body", "grant_type"],
"loc": ["body", "grant_type"], "msg": "String should match pattern '^password$'",
"msg": "String should match pattern '^password$'", "input": grant_type,
"input": grant_type, "ctx": {"pattern": "^password$"},
"ctx": {"pattern": "^password$"}, }
} ]
] }
}
) | IsDict(
# TODO: remove when deprecating Pydantic v1
{
"detail": [
{
"loc": ["body", "grant_type"],
"msg": 'string does not match regex "^password$"',
"type": "value_error.str.regex",
"ctx": {"pattern": "^password$"},
}
]
}
)
def test_strict_login_correct_data(): def test_strict_login_correct_data():
@ -267,26 +216,14 @@ def test_openapi_schema():
"username": {"title": "Username", "type": "string"}, "username": {"title": "Username", "type": "string"},
"password": {"title": "Password", "type": "string"}, "password": {"title": "Password", "type": "string"},
"scope": {"title": "Scope", "type": "string", "default": ""}, "scope": {"title": "Scope", "type": "string", "default": ""},
"client_id": IsDict( "client_id": {
{ "title": "Client Id",
"title": "Client Id", "anyOf": [{"type": "string"}, {"type": "null"}],
"anyOf": [{"type": "string"}, {"type": "null"}], },
} "client_secret": {
) "title": "Client Secret",
| IsDict( "anyOf": [{"type": "string"}, {"type": "null"}],
# TODO: remove when deprecating Pydantic v1 },
{"title": "Client Id", "type": "string"}
),
"client_secret": IsDict(
{
"title": "Client Secret",
"anyOf": [{"type": "string"}, {"type": "null"}],
}
)
| IsDict(
# TODO: remove when deprecating Pydantic v1
{"title": "Client Secret", "type": "string"}
),
}, },
}, },
"ValidationError": { "ValidationError": {

View File

@ -1,7 +1,6 @@
from typing import Optional from typing import Optional
import pytest import pytest
from dirty_equals import IsDict
from fastapi import Depends, FastAPI, Security from fastapi import Depends, FastAPI, Security
from fastapi.security import OAuth2, OAuth2PasswordRequestFormStrict from fastapi.security import OAuth2, OAuth2PasswordRequestFormStrict
from fastapi.testclient import TestClient from fastapi.testclient import TestClient
@ -68,79 +67,43 @@ def test_security_oauth2_password_bearer_no_header():
def test_strict_login_None(): def test_strict_login_None():
response = client.post("/login", data=None) response = client.post("/login", data=None)
assert response.status_code == 422 assert response.status_code == 422
assert response.json() == IsDict( assert response.json() == {
{ "detail": [
"detail": [ {
{ "type": "missing",
"type": "missing", "loc": ["body", "grant_type"],
"loc": ["body", "grant_type"], "msg": "Field required",
"msg": "Field required", "input": None,
"input": None, },
}, {
{ "type": "missing",
"type": "missing", "loc": ["body", "username"],
"loc": ["body", "username"], "msg": "Field required",
"msg": "Field required", "input": None,
"input": None, },
}, {
{ "type": "missing",
"type": "missing", "loc": ["body", "password"],
"loc": ["body", "password"], "msg": "Field required",
"msg": "Field required", "input": None,
"input": None, },
}, ]
] }
}
) | IsDict(
# TODO: remove when deprecating Pydantic v1
{
"detail": [
{
"loc": ["body", "grant_type"],
"msg": "field required",
"type": "value_error.missing",
},
{
"loc": ["body", "username"],
"msg": "field required",
"type": "value_error.missing",
},
{
"loc": ["body", "password"],
"msg": "field required",
"type": "value_error.missing",
},
]
}
)
def test_strict_login_no_grant_type(): def test_strict_login_no_grant_type():
response = client.post("/login", data={"username": "johndoe", "password": "secret"}) response = client.post("/login", data={"username": "johndoe", "password": "secret"})
assert response.status_code == 422 assert response.status_code == 422
assert response.json() == IsDict( assert response.json() == {
{ "detail": [
"detail": [ {
{ "type": "missing",
"type": "missing", "loc": ["body", "grant_type"],
"loc": ["body", "grant_type"], "msg": "Field required",
"msg": "Field required", "input": None,
"input": None, }
} ]
] }
}
) | IsDict(
# TODO: remove when deprecating Pydantic v1
{
"detail": [
{
"loc": ["body", "grant_type"],
"msg": "field required",
"type": "value_error.missing",
}
]
}
)
@pytest.mark.parametrize( @pytest.mark.parametrize(
@ -157,31 +120,17 @@ def test_strict_login_incorrect_grant_type(grant_type: str):
data={"username": "johndoe", "password": "secret", "grant_type": grant_type}, data={"username": "johndoe", "password": "secret", "grant_type": grant_type},
) )
assert response.status_code == 422 assert response.status_code == 422
assert response.json() == IsDict( assert response.json() == {
{ "detail": [
"detail": [ {
{ "type": "string_pattern_mismatch",
"type": "string_pattern_mismatch", "loc": ["body", "grant_type"],
"loc": ["body", "grant_type"], "msg": "String should match pattern '^password$'",
"msg": "String should match pattern '^password$'", "input": grant_type,
"input": grant_type, "ctx": {"pattern": "^password$"},
"ctx": {"pattern": "^password$"}, }
} ]
] }
}
) | IsDict(
# TODO: remove when deprecating Pydantic v1
{
"detail": [
{
"loc": ["body", "grant_type"],
"msg": 'string does not match regex "^password$"',
"type": "value_error.str.regex",
"ctx": {"pattern": "^password$"},
}
]
}
)
def test_strict_login_correct_correct_grant_type(): def test_strict_login_correct_correct_grant_type():
@ -268,26 +217,14 @@ def test_openapi_schema():
"username": {"title": "Username", "type": "string"}, "username": {"title": "Username", "type": "string"},
"password": {"title": "Password", "type": "string"}, "password": {"title": "Password", "type": "string"},
"scope": {"title": "Scope", "type": "string", "default": ""}, "scope": {"title": "Scope", "type": "string", "default": ""},
"client_id": IsDict( "client_id": {
{ "title": "Client Id",
"title": "Client Id", "anyOf": [{"type": "string"}, {"type": "null"}],
"anyOf": [{"type": "string"}, {"type": "null"}], },
} "client_secret": {
) "title": "Client Secret",
| IsDict( "anyOf": [{"type": "string"}, {"type": "null"}],
# TODO: remove when deprecating Pydantic v1 },
{"title": "Client Id", "type": "string"}
),
"client_secret": IsDict(
{
"title": "Client Secret",
"anyOf": [{"type": "string"}, {"type": "null"}],
}
)
| IsDict(
# TODO: remove when deprecating Pydantic v1
{"title": "Client Secret", "type": "string"}
),
}, },
}, },
"ValidationError": { "ValidationError": {

View File

@ -1,6 +1,5 @@
from typing import Optional from typing import Optional
from dirty_equals import IsDict
from fastapi import APIRouter, FastAPI from fastapi import APIRouter, FastAPI
from fastapi.testclient import TestClient from fastapi.testclient import TestClient
from pydantic import BaseModel, HttpUrl from pydantic import BaseModel, HttpUrl
@ -99,30 +98,18 @@ def test_openapi_schema():
"parameters": [ "parameters": [
{ {
"required": False, "required": False,
"schema": IsDict( "schema": {
{ "title": "Callback Url",
"title": "Callback Url", "anyOf": [
"anyOf": [ {
{ "type": "string",
"type": "string", "format": "uri",
"format": "uri", "minLength": 1,
"minLength": 1, "maxLength": 2083,
"maxLength": 2083, },
}, {"type": "null"},
{"type": "null"}, ],
], },
}
)
| IsDict(
# TODO: remove when deprecating Pydantic v1
{
"title": "Callback Url",
"maxLength": 2083,
"minLength": 1,
"type": "string",
"format": "uri",
}
),
"name": "callback_url", "name": "callback_url",
"in": "query", "in": "query",
} }
@ -262,16 +249,10 @@ def test_openapi_schema():
"type": "object", "type": "object",
"properties": { "properties": {
"id": {"title": "Id", "type": "string"}, "id": {"title": "Id", "type": "string"},
"title": IsDict( "title": {
{ "title": "Title",
"title": "Title", "anyOf": [{"type": "string"}, {"type": "null"}],
"anyOf": [{"type": "string"}, {"type": "null"}], },
}
)
| IsDict(
# TODO: remove when deprecating Pydantic v1
{"title": "Title", "type": "string"}
),
"customer": {"title": "Customer", "type": "string"}, "customer": {"title": "Customer", "type": "string"},
"total": {"title": "Total", "type": "number"}, "total": {"title": "Total", "type": "number"},
}, },

View File

@ -1,4 +1,3 @@
from dirty_equals import IsDict
from fastapi import FastAPI, Form from fastapi import FastAPI, Form
from fastapi.testclient import TestClient from fastapi.testclient import TestClient
from pydantic import BaseModel from pydantic import BaseModel
@ -125,31 +124,16 @@ def test_openapi_schema():
"requestBody": { "requestBody": {
"content": { "content": {
"application/json": { "application/json": {
"schema": IsDict( "schema": {
{ "title": "Square",
"title": "Square", "maxItems": 2,
"maxItems": 2, "minItems": 2,
"minItems": 2, "type": "array",
"type": "array", "prefixItems": [
"prefixItems": [ {"$ref": "#/components/schemas/Coordinate"},
{"$ref": "#/components/schemas/Coordinate"}, {"$ref": "#/components/schemas/Coordinate"},
{"$ref": "#/components/schemas/Coordinate"}, ],
], }
}
)
| IsDict(
# TODO: remove when deprecating Pydantic v1
{
"title": "Square",
"maxItems": 2,
"minItems": 2,
"type": "array",
"items": [
{"$ref": "#/components/schemas/Coordinate"},
{"$ref": "#/components/schemas/Coordinate"},
],
}
)
} }
}, },
"required": True, "required": True,
@ -212,28 +196,16 @@ def test_openapi_schema():
"required": ["values"], "required": ["values"],
"type": "object", "type": "object",
"properties": { "properties": {
"values": IsDict( "values": {
{ "title": "Values",
"title": "Values", "maxItems": 2,
"maxItems": 2, "minItems": 2,
"minItems": 2, "type": "array",
"type": "array", "prefixItems": [
"prefixItems": [ {"type": "integer"},
{"type": "integer"}, {"type": "integer"},
{"type": "integer"}, ],
], }
}
)
| IsDict(
# TODO: remove when deprecating Pydantic v1
{
"title": "Values",
"maxItems": 2,
"minItems": 2,
"type": "array",
"items": [{"type": "integer"}, {"type": "integer"}],
}
)
}, },
}, },
"Coordinate": { "Coordinate": {
@ -264,26 +236,15 @@ def test_openapi_schema():
"items": { "items": {
"title": "Items", "title": "Items",
"type": "array", "type": "array",
"items": IsDict( "items": {
{ "maxItems": 2,
"maxItems": 2, "minItems": 2,
"minItems": 2, "type": "array",
"type": "array", "prefixItems": [
"prefixItems": [ {"type": "string"},
{"type": "string"}, {"type": "string"},
{"type": "string"}, ],
], },
}
)
| IsDict(
# TODO: remove when deprecating Pydantic v1
{
"maxItems": 2,
"minItems": 2,
"type": "array",
"items": [{"type": "string"}, {"type": "string"}],
}
),
} }
}, },
}, },

View File

@ -3,7 +3,6 @@ import os
import shutil import shutil
import pytest import pytest
from dirty_equals import IsDict
from fastapi.testclient import TestClient from fastapi.testclient import TestClient
from tests.utils import needs_py310 from tests.utils import needs_py310
@ -80,16 +79,10 @@ def test_openapi_schema(client: TestClient):
}, },
{ {
"required": False, "required": False,
"schema": IsDict( "schema": {
{ "anyOf": [{"type": "boolean"}, {"type": "null"}],
"anyOf": [{"type": "boolean"}, {"type": "null"}], "title": "Img",
"title": "Img", },
}
)
| IsDict(
# TODO: remove when deprecating Pydantic v1
{"title": "Img", "type": "boolean"}
),
"name": "img", "name": "img",
"in": "query", "in": "query",
}, },

View File

@ -3,7 +3,6 @@ import os
import shutil import shutil
import pytest import pytest
from dirty_equals import IsDict
from fastapi.testclient import TestClient from fastapi.testclient import TestClient
from tests.utils import needs_py310 from tests.utils import needs_py310
@ -83,16 +82,10 @@ def test_openapi_schema(client: TestClient):
}, },
{ {
"required": False, "required": False,
"schema": IsDict( "schema": {
{ "anyOf": [{"type": "boolean"}, {"type": "null"}],
"anyOf": [{"type": "boolean"}, {"type": "null"}], "title": "Img",
"title": "Img", },
}
)
| IsDict(
# TODO: remove when deprecating Pydantic v1
{"title": "Img", "type": "boolean"}
),
"name": "img", "name": "img",
"in": "query", "in": "query",
}, },

View File

@ -1,5 +1,5 @@
from dirty_equals import IsOneOf
from fastapi.testclient import TestClient from fastapi.testclient import TestClient
from inline_snapshot import snapshot
from docs_src.behind_a_proxy.tutorial003_py39 import app from docs_src.behind_a_proxy.tutorial003_py39 import app
@ -15,40 +15,34 @@ def test_main():
def test_openapi_schema(): def test_openapi_schema():
response = client.get("/openapi.json") response = client.get("/openapi.json")
assert response.status_code == 200 assert response.status_code == 200
assert response.json() == { assert response.json() == snapshot(
"openapi": "3.1.0", {
"info": {"title": "FastAPI", "version": "0.1.0"}, "openapi": "3.1.0",
"servers": [ "info": {"title": "FastAPI", "version": "0.1.0"},
{"url": "/api/v1"}, "servers": [
{ {"url": "/api/v1"},
"url": IsOneOf( {
"https://stag.example.com/", "url": "https://stag.example.com",
# TODO: remove when deprecating Pydantic v1 "description": "Staging environment",
"https://stag.example.com", },
), {
"description": "Staging environment", "url": "https://prod.example.com",
}, "description": "Production environment",
{ },
"url": IsOneOf( ],
"https://prod.example.com/", "paths": {
# TODO: remove when deprecating Pydantic v1 "/app": {
"https://prod.example.com", "get": {
), "summary": "Read Main",
"description": "Production environment", "operationId": "read_main_app_get",
}, "responses": {
], "200": {
"paths": { "description": "Successful Response",
"/app": { "content": {"application/json": {"schema": {}}},
"get": { }
"summary": "Read Main", },
"operationId": "read_main_app_get", }
"responses": {
"200": {
"description": "Successful Response",
"content": {"application/json": {"schema": {}}},
}
},
} }
} },
}, }
} )

View File

@ -1,5 +1,5 @@
from dirty_equals import IsOneOf
from fastapi.testclient import TestClient from fastapi.testclient import TestClient
from inline_snapshot import snapshot
from docs_src.behind_a_proxy.tutorial004_py39 import app from docs_src.behind_a_proxy.tutorial004_py39 import app
@ -15,39 +15,33 @@ def test_main():
def test_openapi_schema(): def test_openapi_schema():
response = client.get("/openapi.json") response = client.get("/openapi.json")
assert response.status_code == 200 assert response.status_code == 200
assert response.json() == { assert response.json() == snapshot(
"openapi": "3.1.0", {
"info": {"title": "FastAPI", "version": "0.1.0"}, "openapi": "3.1.0",
"servers": [ "info": {"title": "FastAPI", "version": "0.1.0"},
{ "servers": [
"url": IsOneOf( {
"https://stag.example.com/", "url": "https://stag.example.com",
# TODO: remove when deprecating Pydantic v1 "description": "Staging environment",
"https://stag.example.com", },
), {
"description": "Staging environment", "url": "https://prod.example.com",
}, "description": "Production environment",
{ },
"url": IsOneOf( ],
"https://prod.example.com/", "paths": {
# TODO: remove when deprecating Pydantic v1 "/app": {
"https://prod.example.com", "get": {
), "summary": "Read Main",
"description": "Production environment", "operationId": "read_main_app_get",
}, "responses": {
], "200": {
"paths": { "description": "Successful Response",
"/app": { "content": {"application/json": {"schema": {}}},
"get": { }
"summary": "Read Main", },
"operationId": "read_main_app_get", }
"responses": {
"200": {
"description": "Successful Response",
"content": {"application/json": {"schema": {}}},
}
},
} }
} },
}, }
} )

View File

@ -1,7 +1,6 @@
import importlib import importlib
import pytest import pytest
from dirty_equals import IsDict
from fastapi.testclient import TestClient from fastapi.testclient import TestClient
@ -28,29 +27,16 @@ def test_users_token_jessica(client: TestClient):
def test_users_with_no_token(client: TestClient): def test_users_with_no_token(client: TestClient):
response = client.get("/users") response = client.get("/users")
assert response.status_code == 422 assert response.status_code == 422
assert response.json() == IsDict( assert response.json() == {
{ "detail": [
"detail": [ {
{ "type": "missing",
"type": "missing", "loc": ["query", "token"],
"loc": ["query", "token"], "msg": "Field required",
"msg": "Field required", "input": None,
"input": None, }
} ]
] }
}
) | IsDict(
# TODO: remove when deprecating Pydantic v1
{
"detail": [
{
"loc": ["query", "token"],
"msg": "field required",
"type": "value_error.missing",
},
]
}
)
def test_users_foo_token_jessica(client: TestClient): def test_users_foo_token_jessica(client: TestClient):
@ -62,29 +48,16 @@ def test_users_foo_token_jessica(client: TestClient):
def test_users_foo_with_no_token(client: TestClient): def test_users_foo_with_no_token(client: TestClient):
response = client.get("/users/foo") response = client.get("/users/foo")
assert response.status_code == 422 assert response.status_code == 422
assert response.json() == IsDict( assert response.json() == {
{ "detail": [
"detail": [ {
{ "type": "missing",
"type": "missing", "loc": ["query", "token"],
"loc": ["query", "token"], "msg": "Field required",
"msg": "Field required", "input": None,
"input": None, }
} ]
] }
}
) | IsDict(
# TODO: remove when deprecating Pydantic v1
{
"detail": [
{
"loc": ["query", "token"],
"msg": "field required",
"type": "value_error.missing",
},
]
}
)
def test_users_me_token_jessica(client: TestClient): def test_users_me_token_jessica(client: TestClient):
@ -96,29 +69,16 @@ def test_users_me_token_jessica(client: TestClient):
def test_users_me_with_no_token(client: TestClient): def test_users_me_with_no_token(client: TestClient):
response = client.get("/users/me") response = client.get("/users/me")
assert response.status_code == 422 assert response.status_code == 422
assert response.json() == IsDict( assert response.json() == {
{ "detail": [
"detail": [ {
{ "type": "missing",
"type": "missing", "loc": ["query", "token"],
"loc": ["query", "token"], "msg": "Field required",
"msg": "Field required", "input": None,
"input": None, }
} ]
] }
}
) | IsDict(
# TODO: remove when deprecating Pydantic v1
{
"detail": [
{
"loc": ["query", "token"],
"msg": "field required",
"type": "value_error.missing",
},
]
}
)
def test_users_token_monica_with_no_jessica(client: TestClient): def test_users_token_monica_with_no_jessica(client: TestClient):
@ -141,29 +101,16 @@ def test_items_token_jessica(client: TestClient):
def test_items_with_no_token_jessica(client: TestClient): def test_items_with_no_token_jessica(client: TestClient):
response = client.get("/items", headers={"X-Token": "fake-super-secret-token"}) response = client.get("/items", headers={"X-Token": "fake-super-secret-token"})
assert response.status_code == 422 assert response.status_code == 422
assert response.json() == IsDict( assert response.json() == {
{ "detail": [
"detail": [ {
{ "type": "missing",
"type": "missing", "loc": ["query", "token"],
"loc": ["query", "token"], "msg": "Field required",
"msg": "Field required", "input": None,
"input": None, }
} ]
] }
}
) | IsDict(
# TODO: remove when deprecating Pydantic v1
{
"detail": [
{
"loc": ["query", "token"],
"msg": "field required",
"type": "value_error.missing",
},
]
}
)
def test_items_plumbus_token_jessica(client: TestClient): def test_items_plumbus_token_jessica(client: TestClient):
@ -187,29 +134,16 @@ def test_items_plumbus_with_no_token(client: TestClient):
"/items/plumbus", headers={"X-Token": "fake-super-secret-token"} "/items/plumbus", headers={"X-Token": "fake-super-secret-token"}
) )
assert response.status_code == 422 assert response.status_code == 422
assert response.json() == IsDict( assert response.json() == {
{ "detail": [
"detail": [ {
{ "type": "missing",
"type": "missing", "loc": ["query", "token"],
"loc": ["query", "token"], "msg": "Field required",
"msg": "Field required", "input": None,
"input": None, }
} ]
] }
}
) | IsDict(
# TODO: remove when deprecating Pydantic v1
{
"detail": [
{
"loc": ["query", "token"],
"msg": "field required",
"type": "value_error.missing",
},
]
}
)
def test_items_with_invalid_token(client: TestClient): def test_items_with_invalid_token(client: TestClient):
@ -227,57 +161,31 @@ def test_items_bar_with_invalid_token(client: TestClient):
def test_items_with_missing_x_token_header(client: TestClient): def test_items_with_missing_x_token_header(client: TestClient):
response = client.get("/items?token=jessica") response = client.get("/items?token=jessica")
assert response.status_code == 422 assert response.status_code == 422
assert response.json() == IsDict( assert response.json() == {
{ "detail": [
"detail": [ {
{ "type": "missing",
"type": "missing", "loc": ["header", "x-token"],
"loc": ["header", "x-token"], "msg": "Field required",
"msg": "Field required", "input": None,
"input": None, }
} ]
] }
}
) | IsDict(
# TODO: remove when deprecating Pydantic v1
{
"detail": [
{
"loc": ["header", "x-token"],
"msg": "field required",
"type": "value_error.missing",
}
]
}
)
def test_items_plumbus_with_missing_x_token_header(client: TestClient): def test_items_plumbus_with_missing_x_token_header(client: TestClient):
response = client.get("/items/plumbus?token=jessica") response = client.get("/items/plumbus?token=jessica")
assert response.status_code == 422 assert response.status_code == 422
assert response.json() == IsDict( assert response.json() == {
{ "detail": [
"detail": [ {
{ "type": "missing",
"type": "missing", "loc": ["header", "x-token"],
"loc": ["header", "x-token"], "msg": "Field required",
"msg": "Field required", "input": None,
"input": None, }
} ]
] }
}
) | IsDict(
# TODO: remove when deprecating Pydantic v1
{
"detail": [
{
"loc": ["header", "x-token"],
"msg": "field required",
"type": "value_error.missing",
}
]
}
)
def test_root_token_jessica(client: TestClient): def test_root_token_jessica(client: TestClient):
@ -289,68 +197,37 @@ def test_root_token_jessica(client: TestClient):
def test_root_with_no_token(client: TestClient): def test_root_with_no_token(client: TestClient):
response = client.get("/") response = client.get("/")
assert response.status_code == 422 assert response.status_code == 422
assert response.json() == IsDict( assert response.json() == {
{ "detail": [
"detail": [ {
{ "type": "missing",
"type": "missing", "loc": ["query", "token"],
"loc": ["query", "token"], "msg": "Field required",
"msg": "Field required", "input": None,
"input": None, }
} ]
] }
}
) | IsDict(
# TODO: remove when deprecating Pydantic v1
{
"detail": [
{
"loc": ["query", "token"],
"msg": "field required",
"type": "value_error.missing",
},
]
}
)
def test_put_no_header(client: TestClient): def test_put_no_header(client: TestClient):
response = client.put("/items/foo") response = client.put("/items/foo")
assert response.status_code == 422, response.text assert response.status_code == 422, response.text
assert response.json() == IsDict( assert response.json() == {
{ "detail": [
"detail": [ {
{ "type": "missing",
"type": "missing", "loc": ["query", "token"],
"loc": ["query", "token"], "msg": "Field required",
"msg": "Field required", "input": None,
"input": None, },
}, {
{ "type": "missing",
"type": "missing", "loc": ["header", "x-token"],
"loc": ["header", "x-token"], "msg": "Field required",
"msg": "Field required", "input": None,
"input": None, },
}, ]
] }
}
) | IsDict(
# TODO: remove when deprecating Pydantic v1
{
"detail": [
{
"loc": ["query", "token"],
"msg": "field required",
"type": "value_error.missing",
},
{
"loc": ["header", "x-token"],
"msg": "field required",
"type": "value_error.missing",
},
]
}
)
def test_put_invalid_header(client: TestClient): def test_put_invalid_header(client: TestClient):

View File

@ -2,7 +2,6 @@ import importlib
from unittest.mock import patch from unittest.mock import patch
import pytest import pytest
from dirty_equals import IsDict
from fastapi.testclient import TestClient from fastapi.testclient import TestClient
from ...utils import needs_py310 from ...utils import needs_py310
@ -74,124 +73,67 @@ def test_post_with_str_float_description_tax(client: TestClient):
def test_post_with_only_name(client: TestClient): def test_post_with_only_name(client: TestClient):
response = client.post("/items/", json={"name": "Foo"}) response = client.post("/items/", json={"name": "Foo"})
assert response.status_code == 422 assert response.status_code == 422
assert response.json() == IsDict( assert response.json() == {
{ "detail": [
"detail": [ {
{ "type": "missing",
"type": "missing", "loc": ["body", "price"],
"loc": ["body", "price"], "msg": "Field required",
"msg": "Field required", "input": {"name": "Foo"},
"input": {"name": "Foo"}, }
} ]
] }
}
) | IsDict(
# TODO: remove when deprecating Pydantic v1
{
"detail": [
{
"loc": ["body", "price"],
"msg": "field required",
"type": "value_error.missing",
}
]
}
)
def test_post_with_only_name_price(client: TestClient): def test_post_with_only_name_price(client: TestClient):
response = client.post("/items/", json={"name": "Foo", "price": "twenty"}) response = client.post("/items/", json={"name": "Foo", "price": "twenty"})
assert response.status_code == 422 assert response.status_code == 422
assert response.json() == IsDict( assert response.json() == {
{ "detail": [
"detail": [ {
{ "type": "float_parsing",
"type": "float_parsing", "loc": ["body", "price"],
"loc": ["body", "price"], "msg": "Input should be a valid number, unable to parse string as a number",
"msg": "Input should be a valid number, unable to parse string as a number", "input": "twenty",
"input": "twenty", }
} ]
] }
}
) | IsDict(
# TODO: remove when deprecating Pydantic v1
{
"detail": [
{
"loc": ["body", "price"],
"msg": "value is not a valid float",
"type": "type_error.float",
}
]
}
)
def test_post_with_no_data(client: TestClient): def test_post_with_no_data(client: TestClient):
response = client.post("/items/", json={}) response = client.post("/items/", json={})
assert response.status_code == 422 assert response.status_code == 422
assert response.json() == IsDict( assert response.json() == {
{ "detail": [
"detail": [ {
{ "type": "missing",
"type": "missing", "loc": ["body", "name"],
"loc": ["body", "name"], "msg": "Field required",
"msg": "Field required", "input": {},
"input": {}, },
}, {
{ "type": "missing",
"type": "missing", "loc": ["body", "price"],
"loc": ["body", "price"], "msg": "Field required",
"msg": "Field required", "input": {},
"input": {}, },
}, ]
] }
}
) | IsDict(
# TODO: remove when deprecating Pydantic v1
{
"detail": [
{
"loc": ["body", "name"],
"msg": "field required",
"type": "value_error.missing",
},
{
"loc": ["body", "price"],
"msg": "field required",
"type": "value_error.missing",
},
]
}
)
def test_post_with_none(client: TestClient): def test_post_with_none(client: TestClient):
response = client.post("/items/", json=None) response = client.post("/items/", json=None)
assert response.status_code == 422 assert response.status_code == 422
assert response.json() == IsDict( assert response.json() == {
{ "detail": [
"detail": [ {
{ "type": "missing",
"type": "missing", "loc": ["body"],
"loc": ["body"], "msg": "Field required",
"msg": "Field required", "input": None,
"input": None, }
} ]
] }
}
) | IsDict(
# TODO: remove when deprecating Pydantic v1
{
"detail": [
{
"loc": ["body"],
"msg": "field required",
"type": "value_error.missing",
}
]
}
)
def test_post_broken_body(client: TestClient): def test_post_broken_body(client: TestClient):
@ -201,67 +143,32 @@ def test_post_broken_body(client: TestClient):
content="{some broken json}", content="{some broken json}",
) )
assert response.status_code == 422, response.text assert response.status_code == 422, response.text
assert response.json() == IsDict( assert response.json() == {
{ "detail": [
"detail": [ {
{ "type": "json_invalid",
"type": "json_invalid", "loc": ["body", 1],
"loc": ["body", 1], "msg": "JSON decode error",
"msg": "JSON decode error", "input": {},
"input": {}, "ctx": {"error": "Expecting property name enclosed in double quotes"},
"ctx": { }
"error": "Expecting property name enclosed in double quotes" ]
}, }
}
]
}
) | IsDict(
# TODO: remove when deprecating Pydantic v1
{
"detail": [
{
"loc": ["body", 1],
"msg": "Expecting property name enclosed in double quotes: line 1 column 2 (char 1)",
"type": "value_error.jsondecode",
"ctx": {
"msg": "Expecting property name enclosed in double quotes",
"doc": "{some broken json}",
"pos": 1,
"lineno": 1,
"colno": 2,
},
}
]
}
)
def test_post_form_for_json(client: TestClient): def test_post_form_for_json(client: TestClient):
response = client.post("/items/", data={"name": "Foo", "price": 50.5}) response = client.post("/items/", data={"name": "Foo", "price": 50.5})
assert response.status_code == 422, response.text assert response.status_code == 422, response.text
assert response.json() == IsDict( assert response.json() == {
{ "detail": [
"detail": [ {
{ "type": "model_attributes_type",
"type": "model_attributes_type", "loc": ["body"],
"loc": ["body"], "msg": "Input should be a valid dictionary or object to extract fields from",
"msg": "Input should be a valid dictionary or object to extract fields from", "input": "name=Foo&price=50.5",
"input": "name=Foo&price=50.5", }
} ]
] }
}
) | IsDict(
# TODO: remove when deprecating Pydantic v1
{
"detail": [
{
"loc": ["body"],
"msg": "value is not a valid dict",
"type": "type_error.dict",
}
]
}
)
def test_explicit_content_type(client: TestClient): def test_explicit_content_type(client: TestClient):
@ -302,84 +209,46 @@ def test_wrong_headers(client: TestClient):
"/items/", content=data, headers={"Content-Type": "text/plain"} "/items/", content=data, headers={"Content-Type": "text/plain"}
) )
assert response.status_code == 422, response.text assert response.status_code == 422, response.text
assert response.json() == IsDict( assert response.json() == {
{ "detail": [
"detail": [ {
{ "type": "model_attributes_type",
"type": "model_attributes_type", "loc": ["body"],
"loc": ["body"], "msg": "Input should be a valid dictionary or object to extract fields from",
"msg": "Input should be a valid dictionary or object to extract fields from", "input": '{"name": "Foo", "price": 50.5}',
"input": '{"name": "Foo", "price": 50.5}', }
} ]
] }
}
) | IsDict(
# TODO: remove when deprecating Pydantic v1
{
"detail": [
{
"loc": ["body"],
"msg": "value is not a valid dict",
"type": "type_error.dict",
}
]
}
)
response = client.post( response = client.post(
"/items/", content=data, headers={"Content-Type": "application/geo+json-seq"} "/items/", content=data, headers={"Content-Type": "application/geo+json-seq"}
) )
assert response.status_code == 422, response.text assert response.status_code == 422, response.text
assert response.json() == IsDict( assert response.json() == {
{ "detail": [
"detail": [ {
{ "type": "model_attributes_type",
"type": "model_attributes_type", "loc": ["body"],
"loc": ["body"], "msg": "Input should be a valid dictionary or object to extract fields from",
"msg": "Input should be a valid dictionary or object to extract fields from", "input": '{"name": "Foo", "price": 50.5}',
"input": '{"name": "Foo", "price": 50.5}', }
} ]
] }
}
) | IsDict(
# TODO: remove when deprecating Pydantic v1
{
"detail": [
{
"loc": ["body"],
"msg": "value is not a valid dict",
"type": "type_error.dict",
}
]
}
)
response = client.post( response = client.post(
"/items/", content=data, headers={"Content-Type": "application/not-really-json"} "/items/", content=data, headers={"Content-Type": "application/not-really-json"}
) )
assert response.status_code == 422, response.text assert response.status_code == 422, response.text
assert response.json() == IsDict( assert response.json() == {
{ "detail": [
"detail": [ {
{ "type": "model_attributes_type",
"type": "model_attributes_type", "loc": ["body"],
"loc": ["body"], "msg": "Input should be a valid dictionary or object to extract fields from",
"msg": "Input should be a valid dictionary or object to extract fields from", "input": '{"name": "Foo", "price": 50.5}',
"input": '{"name": "Foo", "price": 50.5}', }
} ]
] }
}
) | IsDict(
# TODO: remove when deprecating Pydantic v1
{
"detail": [
{
"loc": ["body"],
"msg": "value is not a valid dict",
"type": "type_error.dict",
}
]
}
)
def test_other_exceptions(client: TestClient): def test_other_exceptions(client: TestClient):
@ -435,26 +304,14 @@ def test_openapi_schema(client: TestClient):
"properties": { "properties": {
"name": {"title": "Name", "type": "string"}, "name": {"title": "Name", "type": "string"},
"price": {"title": "Price", "type": "number"}, "price": {"title": "Price", "type": "number"},
"description": IsDict( "description": {
{ "title": "Description",
"title": "Description", "anyOf": [{"type": "string"}, {"type": "null"}],
"anyOf": [{"type": "string"}, {"type": "null"}], },
} "tax": {
) "title": "Tax",
| IsDict( "anyOf": [{"type": "number"}, {"type": "null"}],
# TODO: remove when deprecating Pydantic v1 },
{"title": "Description", "type": "string"}
),
"tax": IsDict(
{
"title": "Tax",
"anyOf": [{"type": "number"}, {"type": "null"}],
}
)
| IsDict(
# TODO: remove when deprecating Pydantic v1
{"title": "Tax", "type": "number"}
),
}, },
}, },
"ValidationError": { "ValidationError": {

View File

@ -1,7 +1,6 @@
import importlib import importlib
import pytest import pytest
from dirty_equals import IsDict
from fastapi.testclient import TestClient from fastapi.testclient import TestClient
from ...utils import needs_py310 from ...utils import needs_py310
@ -59,31 +58,17 @@ def test_items_6(client: TestClient):
def test_invalid_price(client: TestClient): def test_invalid_price(client: TestClient):
response = client.put("/items/5", json={"item": {"name": "Foo", "price": -3.0}}) response = client.put("/items/5", json={"item": {"name": "Foo", "price": -3.0}})
assert response.status_code == 422 assert response.status_code == 422
assert response.json() == IsDict( assert response.json() == {
{ "detail": [
"detail": [ {
{ "type": "greater_than",
"type": "greater_than", "loc": ["body", "item", "price"],
"loc": ["body", "item", "price"], "msg": "Input should be greater than 0",
"msg": "Input should be greater than 0", "input": -3.0,
"input": -3.0, "ctx": {"gt": 0.0},
"ctx": {"gt": 0.0}, }
} ]
] }
}
) | IsDict(
# TODO: remove when deprecating Pydantic v1
{
"detail": [
{
"ctx": {"limit_value": 0},
"loc": ["body", "item", "price"],
"msg": "ensure this value is greater than 0",
"type": "value_error.number.not_gt",
}
]
}
)
def test_openapi_schema(client: TestClient): def test_openapi_schema(client: TestClient):
@ -142,39 +127,23 @@ def test_openapi_schema(client: TestClient):
"type": "object", "type": "object",
"properties": { "properties": {
"name": {"title": "Name", "type": "string"}, "name": {"title": "Name", "type": "string"},
"description": IsDict( "description": {
{ "title": "The description of the item",
"title": "The description of the item", "anyOf": [
"anyOf": [ {"maxLength": 300, "type": "string"},
{"maxLength": 300, "type": "string"}, {"type": "null"},
{"type": "null"}, ],
], },
}
)
| IsDict(
# TODO: remove when deprecating Pydantic v1
{
"title": "The description of the item",
"maxLength": 300,
"type": "string",
}
),
"price": { "price": {
"title": "Price", "title": "Price",
"exclusiveMinimum": 0.0, "exclusiveMinimum": 0.0,
"type": "number", "type": "number",
"description": "The price must be greater than zero", "description": "The price must be greater than zero",
}, },
"tax": IsDict( "tax": {
{ "title": "Tax",
"title": "Tax", "anyOf": [{"type": "number"}, {"type": "null"}],
"anyOf": [{"type": "number"}, {"type": "null"}], },
}
)
| IsDict(
# TODO: remove when deprecating Pydantic v1
{"title": "Tax", "type": "number"}
),
}, },
}, },
"Body_update_item_items__item_id__put": { "Body_update_item_items__item_id__put": {

View File

@ -1,7 +1,6 @@
import importlib import importlib
import pytest import pytest
from dirty_equals import IsDict
from fastapi.testclient import TestClient from fastapi.testclient import TestClient
from ...utils import needs_py310 from ...utils import needs_py310
@ -53,29 +52,16 @@ def test_post_no_body(client: TestClient):
def test_post_id_foo(client: TestClient): def test_post_id_foo(client: TestClient):
response = client.put("/items/foo", json=None) response = client.put("/items/foo", json=None)
assert response.status_code == 422 assert response.status_code == 422
assert response.json() == IsDict( assert response.json() == {
{ "detail": [
"detail": [ {
{ "type": "int_parsing",
"type": "int_parsing", "loc": ["path", "item_id"],
"loc": ["path", "item_id"], "msg": "Input should be a valid integer, unable to parse string as an integer",
"msg": "Input should be a valid integer, unable to parse string as an integer", "input": "foo",
"input": "foo", }
} ]
] }
}
) | IsDict(
# TODO: remove when deprecating Pydantic v1
{
"detail": [
{
"loc": ["path", "item_id"],
"msg": "value is not a valid integer",
"type": "type_error.integer",
}
]
}
)
def test_openapi_schema(client: TestClient): def test_openapi_schema(client: TestClient):
@ -119,16 +105,10 @@ def test_openapi_schema(client: TestClient):
}, },
{ {
"required": False, "required": False,
"schema": IsDict( "schema": {
{ "anyOf": [{"type": "string"}, {"type": "null"}],
"anyOf": [{"type": "string"}, {"type": "null"}], "title": "Q",
"title": "Q", },
}
)
| IsDict(
# TODO: remove when deprecating Pydantic v1
{"title": "Q", "type": "string"}
),
"name": "q", "name": "q",
"in": "query", "in": "query",
}, },
@ -136,19 +116,13 @@ def test_openapi_schema(client: TestClient):
"requestBody": { "requestBody": {
"content": { "content": {
"application/json": { "application/json": {
"schema": IsDict( "schema": {
{ "anyOf": [
"anyOf": [ {"$ref": "#/components/schemas/Item"},
{"$ref": "#/components/schemas/Item"}, {"type": "null"},
{"type": "null"}, ],
], "title": "Item",
"title": "Item", }
}
)
| IsDict(
# TODO: remove when deprecating Pydantic v1
{"$ref": "#/components/schemas/Item"}
)
} }
} }
}, },
@ -163,27 +137,15 @@ def test_openapi_schema(client: TestClient):
"type": "object", "type": "object",
"properties": { "properties": {
"name": {"title": "Name", "type": "string"}, "name": {"title": "Name", "type": "string"},
"description": IsDict( "description": {
{ "title": "Description",
"title": "Description", "anyOf": [{"type": "string"}, {"type": "null"}],
"anyOf": [{"type": "string"}, {"type": "null"}], },
}
)
| IsDict(
# TODO: remove when deprecating Pydantic v1
{"title": "Description", "type": "string"}
),
"price": {"title": "Price", "type": "number"}, "price": {"title": "Price", "type": "number"},
"tax": IsDict( "tax": {
{ "title": "Tax",
"title": "Tax", "anyOf": [{"type": "number"}, {"type": "null"}],
"anyOf": [{"type": "number"}, {"type": "null"}], },
}
)
| IsDict(
# TODO: remove when deprecating Pydantic v1
{"title": "Tax", "type": "number"}
),
}, },
}, },
"ValidationError": { "ValidationError": {

View File

@ -1,7 +1,6 @@
import importlib import importlib
import pytest import pytest
from dirty_equals import IsDict
from fastapi.testclient import TestClient from fastapi.testclient import TestClient
from ...utils import needs_py310 from ...utils import needs_py310
@ -49,101 +48,55 @@ def test_post_body_valid(client: TestClient):
def test_post_body_no_data(client: TestClient): def test_post_body_no_data(client: TestClient):
response = client.put("/items/5", json=None) response = client.put("/items/5", json=None)
assert response.status_code == 422 assert response.status_code == 422
assert response.json() == IsDict( assert response.json() == {
{ "detail": [
"detail": [ {
{ "type": "missing",
"type": "missing", "loc": ["body", "item"],
"loc": ["body", "item"], "msg": "Field required",
"msg": "Field required", "input": None,
"input": None, },
}, {
{ "type": "missing",
"type": "missing", "loc": ["body", "user"],
"loc": ["body", "user"], "msg": "Field required",
"msg": "Field required", "input": None,
"input": None, },
}, {
{ "type": "missing",
"type": "missing", "loc": ["body", "importance"],
"loc": ["body", "importance"], "msg": "Field required",
"msg": "Field required", "input": None,
"input": None, },
}, ]
] }
}
) | IsDict(
# TODO: remove when deprecating Pydantic v1
{
"detail": [
{
"loc": ["body", "item"],
"msg": "field required",
"type": "value_error.missing",
},
{
"loc": ["body", "user"],
"msg": "field required",
"type": "value_error.missing",
},
{
"loc": ["body", "importance"],
"msg": "field required",
"type": "value_error.missing",
},
]
}
)
def test_post_body_empty_list(client: TestClient): def test_post_body_empty_list(client: TestClient):
response = client.put("/items/5", json=[]) response = client.put("/items/5", json=[])
assert response.status_code == 422 assert response.status_code == 422
assert response.json() == IsDict( assert response.json() == {
{ "detail": [
"detail": [ {
{ "type": "missing",
"type": "missing", "loc": ["body", "item"],
"loc": ["body", "item"], "msg": "Field required",
"msg": "Field required", "input": None,
"input": None, },
}, {
{ "type": "missing",
"type": "missing", "loc": ["body", "user"],
"loc": ["body", "user"], "msg": "Field required",
"msg": "Field required", "input": None,
"input": None, },
}, {
{ "type": "missing",
"type": "missing", "loc": ["body", "importance"],
"loc": ["body", "importance"], "msg": "Field required",
"msg": "Field required", "input": None,
"input": None, },
}, ]
] }
}
) | IsDict(
# TODO: remove when deprecating Pydantic v1
{
"detail": [
{
"loc": ["body", "item"],
"msg": "field required",
"type": "value_error.missing",
},
{
"loc": ["body", "user"],
"msg": "field required",
"type": "value_error.missing",
},
{
"loc": ["body", "importance"],
"msg": "field required",
"type": "value_error.missing",
},
]
}
)
def test_openapi_schema(client: TestClient): def test_openapi_schema(client: TestClient):
@ -202,27 +155,15 @@ def test_openapi_schema(client: TestClient):
"type": "object", "type": "object",
"properties": { "properties": {
"name": {"title": "Name", "type": "string"}, "name": {"title": "Name", "type": "string"},
"description": IsDict( "description": {
{ "title": "Description",
"title": "Description", "anyOf": [{"type": "string"}, {"type": "null"}],
"anyOf": [{"type": "string"}, {"type": "null"}], },
}
)
| IsDict(
# TODO: remove when deprecating Pydantic v1
{"title": "Description", "type": "string"}
),
"price": {"title": "Price", "type": "number"}, "price": {"title": "Price", "type": "number"},
"tax": IsDict( "tax": {
{ "title": "Tax",
"title": "Tax", "anyOf": [{"type": "number"}, {"type": "null"}],
"anyOf": [{"type": "number"}, {"type": "null"}], },
}
)
| IsDict(
# TODO: remove when deprecating Pydantic v1
{"title": "Tax", "type": "number"}
),
}, },
}, },
"User": { "User": {
@ -231,16 +172,10 @@ def test_openapi_schema(client: TestClient):
"type": "object", "type": "object",
"properties": { "properties": {
"username": {"title": "Username", "type": "string"}, "username": {"title": "Username", "type": "string"},
"full_name": IsDict( "full_name": {
{ "title": "Full Name",
"title": "Full Name", "anyOf": [{"type": "string"}, {"type": "null"}],
"anyOf": [{"type": "string"}, {"type": "null"}], },
}
)
| IsDict(
# TODO: remove when deprecating Pydantic v1
{"title": "Full Name", "type": "string"}
),
}, },
}, },
"Body_update_item_items__item_id__put": { "Body_update_item_items__item_id__put": {

View File

@ -1,7 +1,6 @@
import importlib import importlib
import pytest import pytest
from dirty_equals import IsDict
from fastapi.testclient import TestClient from fastapi.testclient import TestClient
@ -29,29 +28,16 @@ def test_post_invalid_body(client: TestClient):
data = {"foo": 2.2, "3": 3.3} data = {"foo": 2.2, "3": 3.3}
response = client.post("/index-weights/", json=data) response = client.post("/index-weights/", json=data)
assert response.status_code == 422, response.text assert response.status_code == 422, response.text
assert response.json() == IsDict( assert response.json() == {
{ "detail": [
"detail": [ {
{ "type": "int_parsing",
"type": "int_parsing", "loc": ["body", "foo", "[key]"],
"loc": ["body", "foo", "[key]"], "msg": "Input should be a valid integer, unable to parse string as an integer",
"msg": "Input should be a valid integer, unable to parse string as an integer", "input": "foo",
"input": "foo", }
} ]
] }
}
) | IsDict(
# TODO: remove when deprecating Pydantic v1
{
"detail": [
{
"loc": ["body", "__key__"],
"msg": "value is not a valid integer",
"type": "type_error.integer",
}
]
}
)
def test_openapi_schema(client: TestClient): def test_openapi_schema(client: TestClient):

View File

@ -1,7 +1,6 @@
import importlib import importlib
import pytest import pytest
from dirty_equals import IsDict
from fastapi.testclient import TestClient from fastapi.testclient import TestClient
from inline_snapshot import snapshot from inline_snapshot import snapshot
@ -54,30 +53,16 @@ def test_cookie_param_model_invalid(client: TestClient):
response = client.get("/items/") response = client.get("/items/")
assert response.status_code == 422 assert response.status_code == 422
assert response.json() == snapshot( assert response.json() == snapshot(
IsDict( {
{ "detail": [
"detail": [ {
{ "type": "missing",
"type": "missing", "loc": ["cookie", "session_id"],
"loc": ["cookie", "session_id"], "msg": "Field required",
"msg": "Field required", "input": {},
"input": {}, }
} ]
] }
}
)
| IsDict(
# TODO: remove when deprecating Pydantic v1
{
"detail": [
{
"type": "value_error.missing",
"loc": ["cookie", "session_id"],
"msg": "field required",
}
]
}
)
) )
@ -115,37 +100,19 @@ def test_openapi_schema(client: TestClient):
"name": "fatebook_tracker", "name": "fatebook_tracker",
"in": "cookie", "in": "cookie",
"required": False, "required": False,
"schema": IsDict( "schema": {
{ "anyOf": [{"type": "string"}, {"type": "null"}],
"anyOf": [{"type": "string"}, {"type": "null"}], "title": "Fatebook Tracker",
"title": "Fatebook Tracker", },
}
)
| IsDict(
# TODO: remove when deprecating Pydantic v1
{
"type": "string",
"title": "Fatebook Tracker",
}
),
}, },
{ {
"name": "googall_tracker", "name": "googall_tracker",
"in": "cookie", "in": "cookie",
"required": False, "required": False,
"schema": IsDict( "schema": {
{ "anyOf": [{"type": "string"}, {"type": "null"}],
"anyOf": [{"type": "string"}, {"type": "null"}], "title": "Googall Tracker",
"title": "Googall Tracker", },
}
)
| IsDict(
# TODO: remove when deprecating Pydantic v1
{
"type": "string",
"title": "Googall Tracker",
}
),
}, },
], ],
"responses": { "responses": {

View File

@ -1,7 +1,6 @@
import importlib import importlib
import pytest import pytest
from dirty_equals import IsDict
from fastapi.testclient import TestClient from fastapi.testclient import TestClient
from inline_snapshot import snapshot from inline_snapshot import snapshot
@ -72,30 +71,16 @@ def test_cookie_param_model_extra(client: TestClient):
response = c.get("/items/") response = c.get("/items/")
assert response.status_code == 422 assert response.status_code == 422
assert response.json() == snapshot( assert response.json() == snapshot(
IsDict( {
{ "detail": [
"detail": [ {
{ "type": "extra_forbidden",
"type": "extra_forbidden", "loc": ["cookie", "extra"],
"loc": ["cookie", "extra"], "msg": "Extra inputs are not permitted",
"msg": "Extra inputs are not permitted", "input": "track-me-here-too",
"input": "track-me-here-too", }
} ]
] }
}
)
| IsDict(
# TODO: remove when deprecating Pydantic v1
{
"detail": [
{
"type": "value_error.extra",
"loc": ["cookie", "extra"],
"msg": "extra fields not permitted",
}
]
}
)
) )
@ -134,19 +119,10 @@ def test_openapi_schema(client: TestClient):
"name": "googall_tracker", "name": "googall_tracker",
"in": "cookie", "in": "cookie",
"required": False, "required": False,
"schema": IsDict( "schema": {
{ "anyOf": [{"type": "string"}, {"type": "null"}],
"anyOf": [{"type": "string"}, {"type": "null"}], "title": "Googall Tracker",
"title": "Googall Tracker", },
}
)
| IsDict(
# TODO: remove when deprecating Pydantic v1
{
"type": "string",
"title": "Googall Tracker",
}
),
}, },
], ],
"responses": { "responses": {

View File

@ -2,7 +2,6 @@ import importlib
from types import ModuleType from types import ModuleType
import pytest import pytest
from dirty_equals import IsDict
from fastapi.testclient import TestClient from fastapi.testclient import TestClient
from ...utils import needs_py310 from ...utils import needs_py310
@ -75,16 +74,10 @@ def test_openapi_schema(mod: ModuleType):
"parameters": [ "parameters": [
{ {
"required": False, "required": False,
"schema": IsDict( "schema": {
{ "anyOf": [{"type": "string"}, {"type": "null"}],
"anyOf": [{"type": "string"}, {"type": "null"}], "title": "Ads Id",
"title": "Ads Id", },
}
)
| IsDict(
# TODO: remove when deprecating Pydantic v1
{"title": "Ads Id", "type": "string"}
),
"name": "ads_id", "name": "ads_id",
"in": "cookie", "in": "cookie",
} }

View File

@ -1,7 +1,7 @@
import importlib import importlib
import pytest import pytest
from dirty_equals import IsDict, IsOneOf from dirty_equals import IsOneOf
from fastapi.testclient import TestClient from fastapi.testclient import TestClient
from tests.utils import needs_py310 from tests.utils import needs_py310
@ -30,34 +30,17 @@ def test_endpoint_works(client: TestClient):
def test_exception_handler_body_access(client: TestClient): def test_exception_handler_body_access(client: TestClient):
response = client.post("/", json={"numbers": [1, 2, 3]}) response = client.post("/", json={"numbers": [1, 2, 3]})
assert response.json() == IsDict( assert response.json() == {
{ "detail": {
"detail": { "errors": [
"errors": [ {
{ "type": "list_type",
"type": "list_type", "loc": ["body"],
"loc": ["body"], "msg": "Input should be a valid list",
"msg": "Input should be a valid list", "input": {"numbers": [1, 2, 3]},
"input": {"numbers": [1, 2, 3]}, }
} ],
], # httpx 0.28.0 switches to compact JSON https://github.com/encode/httpx/issues/3363
# httpx 0.28.0 switches to compact JSON https://github.com/encode/httpx/issues/3363 "body": IsOneOf('{"numbers": [1, 2, 3]}', '{"numbers":[1,2,3]}'),
"body": IsOneOf('{"numbers": [1, 2, 3]}', '{"numbers":[1,2,3]}'),
}
} }
) | IsDict( }
# TODO: remove when deprecating Pydantic v1
{
"detail": {
# httpx 0.28.0 switches to compact JSON https://github.com/encode/httpx/issues/3363
"body": IsOneOf('{"numbers": [1, 2, 3]}', '{"numbers":[1,2,3]}'),
"errors": [
{
"loc": ["body"],
"msg": "value is not a valid list",
"type": "type_error.list",
}
],
}
}
)

View File

@ -1,7 +1,6 @@
import importlib import importlib
import pytest import pytest
from dirty_equals import IsDict
from fastapi.testclient import TestClient from fastapi.testclient import TestClient
from tests.utils import needs_py310 from tests.utils import needs_py310
@ -36,29 +35,16 @@ def test_post_item(client: TestClient):
def test_post_invalid_item(client: TestClient): def test_post_invalid_item(client: TestClient):
response = client.post("/items/", json={"name": "Foo", "price": "invalid price"}) response = client.post("/items/", json={"name": "Foo", "price": "invalid price"})
assert response.status_code == 422 assert response.status_code == 422
assert response.json() == IsDict( assert response.json() == {
{ "detail": [
"detail": [ {
{ "type": "float_parsing",
"type": "float_parsing", "loc": ["body", "price"],
"loc": ["body", "price"], "msg": "Input should be a valid number, unable to parse string as a number",
"msg": "Input should be a valid number, unable to parse string as a number", "input": "invalid price",
"input": "invalid price", }
} ]
] }
}
) | IsDict(
# TODO: remove when deprecating Pydantic v1
{
"detail": [
{
"loc": ["body", "price"],
"msg": "value is not a valid float",
"type": "type_error.float",
}
]
}
)
def test_openapi_schema(client: TestClient): def test_openapi_schema(client: TestClient):
@ -119,26 +105,14 @@ def test_openapi_schema(client: TestClient):
"properties": { "properties": {
"name": {"title": "Name", "type": "string"}, "name": {"title": "Name", "type": "string"},
"price": {"title": "Price", "type": "number"}, "price": {"title": "Price", "type": "number"},
"description": IsDict( "description": {
{ "title": "Description",
"title": "Description", "anyOf": [{"type": "string"}, {"type": "null"}],
"anyOf": [{"type": "string"}, {"type": "null"}], },
} "tax": {
) "title": "Tax",
| IsDict( "anyOf": [{"type": "number"}, {"type": "null"}],
# TODO: remove when deprecating Pydantic v1 },
{"title": "Description", "type": "string"}
),
"tax": IsDict(
{
"title": "Tax",
"anyOf": [{"type": "number"}, {"type": "null"}],
}
)
| IsDict(
# TODO: remove when deprecating Pydantic v1
{"title": "Tax", "type": "number"}
),
}, },
}, },
"ValidationError": { "ValidationError": {

View File

@ -1,8 +1,8 @@
import importlib import importlib
import pytest import pytest
from dirty_equals import IsDict, IsOneOf
from fastapi.testclient import TestClient from fastapi.testclient import TestClient
from inline_snapshot import snapshot
from tests.utils import needs_py310 from tests.utils import needs_py310
@ -37,77 +37,53 @@ def test_get_item(client: TestClient):
def test_openapi_schema(client: TestClient): def test_openapi_schema(client: TestClient):
response = client.get("/openapi.json") response = client.get("/openapi.json")
assert response.status_code == 200 assert response.status_code == 200
assert response.json() == { assert response.json() == snapshot(
"openapi": "3.1.0", {
"info": {"title": "FastAPI", "version": "0.1.0"}, "openapi": "3.1.0",
"paths": { "info": {"title": "FastAPI", "version": "0.1.0"},
"/items/next": { "paths": {
"get": { "/items/next": {
"summary": "Read Next Item", "get": {
"operationId": "read_next_item_items_next_get", "summary": "Read Next Item",
"responses": { "operationId": "read_next_item_items_next_get",
"200": { "responses": {
"description": "Successful Response", "200": {
"content": { "description": "Successful Response",
"application/json": { "content": {
"schema": {"$ref": "#/components/schemas/Item"} "application/json": {
} "schema": {"$ref": "#/components/schemas/Item"}
}, }
} },
}, }
},
}
} }
} },
}, "components": {
"components": { "schemas": {
"schemas": { "Item": {
"Item": { "title": "Item",
"title": "Item", "required": ["name", "price"],
"required": IsOneOf( "type": "object",
["name", "price", "tags", "description", "tax"], "properties": {
# TODO: remove when deprecating Pydantic v1 "name": {"title": "Name", "type": "string"},
["name", "price"], "price": {"title": "Price", "type": "number"},
), "tags": {
"type": "object",
"properties": {
"name": {"title": "Name", "type": "string"},
"price": {"title": "Price", "type": "number"},
"tags": IsDict(
{
"title": "Tags", "title": "Tags",
"type": "array", "type": "array",
"items": {"type": "string"}, "items": {"type": "string"},
} },
) "description": {
| IsDict(
# TODO: remove when deprecating Pydantic v1
{
"title": "Tags",
"type": "array",
"items": {"type": "string"},
}
),
"description": IsDict(
{
"title": "Description", "title": "Description",
"anyOf": [{"type": "string"}, {"type": "null"}], "anyOf": [{"type": "string"}, {"type": "null"}],
} },
) "tax": {
| IsDict(
# TODO: remove when deprecating Pydantic v1
{"title": "Description", "type": "string"}
),
"tax": IsDict(
{
"title": "Tax", "title": "Tax",
"anyOf": [{"type": "number"}, {"type": "null"}], "anyOf": [{"type": "number"}, {"type": "null"}],
} },
) },
| IsDict( }
# TODO: remove when deprecating Pydantic v1
{"title": "Tax", "type": "number"}
),
},
} }
} },
}, }
} )

View File

@ -1,7 +1,6 @@
import importlib import importlib
import pytest import pytest
from dirty_equals import IsDict
from fastapi.testclient import TestClient from fastapi.testclient import TestClient
@ -22,40 +21,22 @@ def get_client(request: pytest.FixtureRequest):
def test_get_no_headers(client: TestClient): def test_get_no_headers(client: TestClient):
response = client.get("/items/") response = client.get("/items/")
assert response.status_code == 422, response.text assert response.status_code == 422, response.text
assert response.json() == IsDict( assert response.json() == {
{ "detail": [
"detail": [ {
{ "type": "missing",
"type": "missing", "loc": ["header", "x-token"],
"loc": ["header", "x-token"], "msg": "Field required",
"msg": "Field required", "input": None,
"input": None, },
}, {
{ "type": "missing",
"type": "missing", "loc": ["header", "x-key"],
"loc": ["header", "x-key"], "msg": "Field required",
"msg": "Field required", "input": None,
"input": None, },
}, ]
] }
}
) | IsDict(
# TODO: remove when deprecating Pydantic v1
{
"detail": [
{
"loc": ["header", "x-token"],
"msg": "field required",
"type": "value_error.missing",
},
{
"loc": ["header", "x-key"],
"msg": "field required",
"type": "value_error.missing",
},
]
}
)
def test_get_invalid_one_header(client: TestClient): def test_get_invalid_one_header(client: TestClient):

View File

@ -1,7 +1,6 @@
import importlib import importlib
import pytest import pytest
from dirty_equals import IsDict
from fastapi.testclient import TestClient from fastapi.testclient import TestClient
@ -22,79 +21,43 @@ def get_client(request: pytest.FixtureRequest):
def test_get_no_headers_items(client: TestClient): def test_get_no_headers_items(client: TestClient):
response = client.get("/items/") response = client.get("/items/")
assert response.status_code == 422, response.text assert response.status_code == 422, response.text
assert response.json() == IsDict( assert response.json() == {
{ "detail": [
"detail": [ {
{ "type": "missing",
"type": "missing", "loc": ["header", "x-token"],
"loc": ["header", "x-token"], "msg": "Field required",
"msg": "Field required", "input": None,
"input": None, },
}, {
{ "type": "missing",
"type": "missing", "loc": ["header", "x-key"],
"loc": ["header", "x-key"], "msg": "Field required",
"msg": "Field required", "input": None,
"input": None, },
}, ]
] }
}
) | IsDict(
# TODO: remove when deprecating Pydantic v1
{
"detail": [
{
"loc": ["header", "x-token"],
"msg": "field required",
"type": "value_error.missing",
},
{
"loc": ["header", "x-key"],
"msg": "field required",
"type": "value_error.missing",
},
]
}
)
def test_get_no_headers_users(client: TestClient): def test_get_no_headers_users(client: TestClient):
response = client.get("/users/") response = client.get("/users/")
assert response.status_code == 422, response.text assert response.status_code == 422, response.text
assert response.json() == IsDict( assert response.json() == {
{ "detail": [
"detail": [ {
{ "type": "missing",
"type": "missing", "loc": ["header", "x-token"],
"loc": ["header", "x-token"], "msg": "Field required",
"msg": "Field required", "input": None,
"input": None, },
}, {
{ "type": "missing",
"type": "missing", "loc": ["header", "x-key"],
"loc": ["header", "x-key"], "msg": "Field required",
"msg": "Field required", "input": None,
"input": None, },
}, ]
] }
}
) | IsDict(
# TODO: remove when deprecating Pydantic v1
{
"detail": [
{
"loc": ["header", "x-token"],
"msg": "field required",
"type": "value_error.missing",
},
{
"loc": ["header", "x-key"],
"msg": "field required",
"type": "value_error.missing",
},
]
}
)
def test_get_invalid_one_header_items(client: TestClient): def test_get_invalid_one_header_items(client: TestClient):

View File

@ -1,8 +1,8 @@
import importlib import importlib
import pytest import pytest
from dirty_equals import IsDict
from fastapi.testclient import TestClient from fastapi.testclient import TestClient
from inline_snapshot import snapshot
from ...utils import needs_py310 from ...utils import needs_py310
@ -47,146 +47,117 @@ def test_extra_types(client: TestClient):
def test_openapi_schema(client: TestClient): def test_openapi_schema(client: TestClient):
response = client.get("/openapi.json") response = client.get("/openapi.json")
assert response.status_code == 200, response.text assert response.status_code == 200, response.text
assert response.json() == { assert response.json() == snapshot(
"openapi": "3.1.0", {
"info": {"title": "FastAPI", "version": "0.1.0"}, "openapi": "3.1.0",
"paths": { "info": {"title": "FastAPI", "version": "0.1.0"},
"/items/{item_id}": { "paths": {
"put": { "/items/{item_id}": {
"responses": { "put": {
"200": { "responses": {
"description": "Successful Response", "200": {
"content": {"application/json": {"schema": {}}}, "description": "Successful Response",
"content": {"application/json": {"schema": {}}},
},
"422": {
"description": "Validation Error",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/HTTPValidationError"
}
}
},
},
}, },
"422": { "summary": "Read Items",
"description": "Validation Error", "operationId": "read_items_items__item_id__put",
"parameters": [
{
"required": True,
"schema": {
"title": "Item Id",
"type": "string",
"format": "uuid",
},
"name": "item_id",
"in": "path",
}
],
"requestBody": {
"required": True,
"content": { "content": {
"application/json": { "application/json": {
"schema": { "schema": {
"$ref": "#/components/schemas/HTTPValidationError" "$ref": "#/components/schemas/Body_read_items_items__item_id__put"
} }
} }
}, },
}, },
}, }
"summary": "Read Items",
"operationId": "read_items_items__item_id__put",
"parameters": [
{
"required": True,
"schema": {
"title": "Item Id",
"type": "string",
"format": "uuid",
},
"name": "item_id",
"in": "path",
}
],
"requestBody": {
"required": True,
"content": {
"application/json": {
"schema": IsDict(
{
"allOf": [
{
"$ref": "#/components/schemas/Body_read_items_items__item_id__put"
}
],
"title": "Body",
}
)
| IsDict(
# TODO: remove when deprecating Pydantic v1
{
"$ref": "#/components/schemas/Body_read_items_items__item_id__put"
}
)
}
},
},
} }
} },
}, "components": {
"components": { "schemas": {
"schemas": { "Body_read_items_items__item_id__put": {
"Body_read_items_items__item_id__put": { "title": "Body_read_items_items__item_id__put",
"title": "Body_read_items_items__item_id__put", "type": "object",
"type": "object", "properties": {
"properties": { "start_datetime": {
"start_datetime": { "title": "Start Datetime",
"title": "Start Datetime", "type": "string",
"type": "string", "format": "date-time",
"format": "date-time", },
}, "end_datetime": {
"end_datetime": { "title": "End Datetime",
"title": "End Datetime", "type": "string",
"type": "string", "format": "date-time",
"format": "date-time", },
}, "repeat_at": {
"repeat_at": IsDict(
{
"title": "Repeat At", "title": "Repeat At",
"anyOf": [ "anyOf": [
{"type": "string", "format": "time"}, {"type": "string", "format": "time"},
{"type": "null"}, {"type": "null"},
], ],
} },
) "process_after": {
| IsDict(
# TODO: remove when deprecating Pydantic v1
{
"title": "Repeat At",
"type": "string",
"format": "time",
}
),
"process_after": IsDict(
{
"title": "Process After", "title": "Process After",
"type": "string", "type": "string",
"format": "duration", "format": "duration",
}
)
| IsDict(
# TODO: remove when deprecating Pydantic v1
{
"title": "Process After",
"type": "number",
"format": "time-delta",
}
),
},
"required": ["start_datetime", "end_datetime", "process_after"],
},
"ValidationError": {
"title": "ValidationError",
"required": ["loc", "msg", "type"],
"type": "object",
"properties": {
"loc": {
"title": "Location",
"type": "array",
"items": {
"anyOf": [{"type": "string"}, {"type": "integer"}]
}, },
}, },
"msg": {"title": "Message", "type": "string"}, "required": ["start_datetime", "end_datetime", "process_after"],
"type": {"title": "Error Type", "type": "string"},
}, },
}, "ValidationError": {
"HTTPValidationError": { "title": "ValidationError",
"title": "HTTPValidationError", "required": ["loc", "msg", "type"],
"type": "object", "type": "object",
"properties": { "properties": {
"detail": { "loc": {
"title": "Detail", "title": "Location",
"type": "array", "type": "array",
"items": {"$ref": "#/components/schemas/ValidationError"}, "items": {
} "anyOf": [{"type": "string"}, {"type": "integer"}]
},
},
"msg": {"title": "Message", "type": "string"},
"type": {"title": "Error Type", "type": "string"},
},
}, },
}, "HTTPValidationError": {
} "title": "HTTPValidationError",
}, "type": "object",
} "properties": {
"detail": {
"title": "Detail",
"type": "array",
"items": {
"$ref": "#/components/schemas/ValidationError"
},
}
},
},
}
},
}
)

View File

@ -1,8 +1,8 @@
import importlib import importlib
import pytest import pytest
from dirty_equals import IsOneOf
from fastapi.testclient import TestClient from fastapi.testclient import TestClient
from inline_snapshot import snapshot
from ...utils import needs_py310 from ...utils import needs_py310
@ -43,107 +43,115 @@ def test_get_plane(client: TestClient):
def test_openapi_schema(client: TestClient): def test_openapi_schema(client: TestClient):
response = client.get("/openapi.json") response = client.get("/openapi.json")
assert response.status_code == 200, response.text assert response.status_code == 200, response.text
assert response.json() == { assert response.json() == snapshot(
"openapi": "3.1.0", {
"info": {"title": "FastAPI", "version": "0.1.0"}, "openapi": "3.1.0",
"paths": { "info": {"title": "FastAPI", "version": "0.1.0"},
"/items/{item_id}": { "paths": {
"get": { "/items/{item_id}": {
"responses": { "get": {
"200": { "responses": {
"description": "Successful Response", "200": {
"content": { "description": "Successful Response",
"application/json": { "content": {
"schema": { "application/json": {
"title": "Response Read Item Items Item Id Get", "schema": {
"anyOf": [ "title": "Response Read Item Items Item Id Get",
{"$ref": "#/components/schemas/PlaneItem"}, "anyOf": [
{"$ref": "#/components/schemas/CarItem"}, {
], "$ref": "#/components/schemas/PlaneItem"
},
{
"$ref": "#/components/schemas/CarItem"
},
],
}
} }
} },
},
"422": {
"description": "Validation Error",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/HTTPValidationError"
}
}
},
}, },
}, },
"422": { "summary": "Read Item",
"description": "Validation Error", "operationId": "read_item_items__item_id__get",
"content": { "parameters": [
"application/json": { {
"schema": { "required": True,
"$ref": "#/components/schemas/HTTPValidationError" "schema": {"title": "Item Id", "type": "string"},
} "name": "item_id",
} "in": "path",
}, }
}, ],
}, }
"summary": "Read Item",
"operationId": "read_item_items__item_id__get",
"parameters": [
{
"required": True,
"schema": {"title": "Item Id", "type": "string"},
"name": "item_id",
"in": "path",
}
],
} }
} },
}, "components": {
"components": { "schemas": {
"schemas": { "PlaneItem": {
"PlaneItem": { "title": "PlaneItem",
"title": "PlaneItem", "required": ["description", "size"],
"required": IsOneOf( "type": "object",
["description", "type", "size"], "properties": {
# TODO: remove when deprecating Pydantic v1 "description": {"title": "Description", "type": "string"},
["description", "size"], "type": {
), "title": "Type",
"type": "object", "type": "string",
"properties": { "default": "plane",
"description": {"title": "Description", "type": "string"}, },
"type": {"title": "Type", "type": "string", "default": "plane"}, "size": {"title": "Size", "type": "integer"},
"size": {"title": "Size", "type": "integer"}, },
}, },
}, "CarItem": {
"CarItem": { "title": "CarItem",
"title": "CarItem", "required": ["description"],
"required": IsOneOf( "type": "object",
["description", "type"], "properties": {
# TODO: remove when deprecating Pydantic v1 "description": {"title": "Description", "type": "string"},
["description"], "type": {
), "title": "Type",
"type": "object", "type": "string",
"properties": { "default": "car",
"description": {"title": "Description", "type": "string"},
"type": {"title": "Type", "type": "string", "default": "car"},
},
},
"ValidationError": {
"title": "ValidationError",
"required": ["loc", "msg", "type"],
"type": "object",
"properties": {
"loc": {
"title": "Location",
"type": "array",
"items": {
"anyOf": [{"type": "string"}, {"type": "integer"}]
}, },
}, },
"msg": {"title": "Message", "type": "string"},
"type": {"title": "Error Type", "type": "string"},
}, },
}, "ValidationError": {
"HTTPValidationError": { "title": "ValidationError",
"title": "HTTPValidationError", "required": ["loc", "msg", "type"],
"type": "object", "type": "object",
"properties": { "properties": {
"detail": { "loc": {
"title": "Detail", "title": "Location",
"type": "array", "type": "array",
"items": {"$ref": "#/components/schemas/ValidationError"}, "items": {
} "anyOf": [{"type": "string"}, {"type": "integer"}]
},
},
"msg": {"title": "Message", "type": "string"},
"type": {"title": "Error Type", "type": "string"},
},
}, },
}, "HTTPValidationError": {
} "title": "HTTPValidationError",
}, "type": "object",
} "properties": {
"detail": {
"title": "Detail",
"type": "array",
"items": {
"$ref": "#/components/schemas/ValidationError"
},
}
},
},
}
},
}
)

View File

@ -1,4 +1,3 @@
from dirty_equals import IsDict
from fastapi.testclient import TestClient from fastapi.testclient import TestClient
from docs_src.handling_errors.tutorial005_py39 import app from docs_src.handling_errors.tutorial005_py39 import app
@ -9,31 +8,17 @@ client = TestClient(app)
def test_post_validation_error(): def test_post_validation_error():
response = client.post("/items/", json={"title": "towel", "size": "XL"}) response = client.post("/items/", json={"title": "towel", "size": "XL"})
assert response.status_code == 422, response.text assert response.status_code == 422, response.text
assert response.json() == IsDict( assert response.json() == {
{ "detail": [
"detail": [ {
{ "type": "int_parsing",
"type": "int_parsing", "loc": ["body", "size"],
"loc": ["body", "size"], "msg": "Input should be a valid integer, unable to parse string as an integer",
"msg": "Input should be a valid integer, unable to parse string as an integer", "input": "XL",
"input": "XL", }
} ],
], "body": {"title": "towel", "size": "XL"},
"body": {"title": "towel", "size": "XL"}, }
}
) | IsDict(
# TODO: remove when deprecating Pydantic v1
{
"detail": [
{
"loc": ["body", "size"],
"msg": "value is not a valid integer",
"type": "type_error.integer",
}
],
"body": {"title": "towel", "size": "XL"},
}
)
def test_post(): def test_post():

View File

@ -1,4 +1,3 @@
from dirty_equals import IsDict
from fastapi.testclient import TestClient from fastapi.testclient import TestClient
from docs_src.handling_errors.tutorial006_py39 import app from docs_src.handling_errors.tutorial006_py39 import app
@ -9,29 +8,16 @@ client = TestClient(app)
def test_get_validation_error(): def test_get_validation_error():
response = client.get("/items/foo") response = client.get("/items/foo")
assert response.status_code == 422, response.text assert response.status_code == 422, response.text
assert response.json() == IsDict( assert response.json() == {
{ "detail": [
"detail": [ {
{ "type": "int_parsing",
"type": "int_parsing", "loc": ["path", "item_id"],
"loc": ["path", "item_id"], "msg": "Input should be a valid integer, unable to parse string as an integer",
"msg": "Input should be a valid integer, unable to parse string as an integer", "input": "foo",
"input": "foo", }
} ]
] }
}
) | IsDict(
# TODO: remove when deprecating Pydantic v1
{
"detail": [
{
"loc": ["path", "item_id"],
"msg": "value is not a valid integer",
"type": "type_error.integer",
}
]
}
)
def test_get_http_error(): def test_get_http_error():

View File

@ -1,7 +1,6 @@
import importlib import importlib
import pytest import pytest
from dirty_equals import IsDict
from fastapi.testclient import TestClient from fastapi.testclient import TestClient
from inline_snapshot import snapshot from inline_snapshot import snapshot
@ -63,29 +62,19 @@ def test_header_param_model_invalid(client: TestClient):
assert response.json() == snapshot( assert response.json() == snapshot(
{ {
"detail": [ "detail": [
IsDict( {
{ "type": "missing",
"type": "missing", "loc": ["header", "save_data"],
"loc": ["header", "save_data"], "msg": "Field required",
"msg": "Field required", "input": {
"input": { "x_tag": [],
"x_tag": [], "host": "testserver",
"host": "testserver", "accept": "*/*",
"accept": "*/*", "accept-encoding": "gzip, deflate",
"accept-encoding": "gzip, deflate", "connection": "keep-alive",
"connection": "keep-alive", "user-agent": "testclient",
"user-agent": "testclient", },
}, }
}
)
| IsDict(
# TODO: remove when deprecating Pydantic v1
{
"type": "value_error.missing",
"loc": ["header", "save_data"],
"msg": "field required",
}
)
] ]
} }
) )
@ -136,37 +125,19 @@ def test_openapi_schema(client: TestClient):
"name": "if-modified-since", "name": "if-modified-since",
"in": "header", "in": "header",
"required": False, "required": False,
"schema": IsDict( "schema": {
{ "anyOf": [{"type": "string"}, {"type": "null"}],
"anyOf": [{"type": "string"}, {"type": "null"}], "title": "If Modified Since",
"title": "If Modified Since", },
}
)
| IsDict(
# TODO: remove when deprecating Pydantic v1
{
"type": "string",
"title": "If Modified Since",
}
),
}, },
{ {
"name": "traceparent", "name": "traceparent",
"in": "header", "in": "header",
"required": False, "required": False,
"schema": IsDict( "schema": {
{ "anyOf": [{"type": "string"}, {"type": "null"}],
"anyOf": [{"type": "string"}, {"type": "null"}], "title": "Traceparent",
"title": "Traceparent", },
}
)
| IsDict(
# TODO: remove when deprecating Pydantic v1
{
"type": "string",
"title": "Traceparent",
}
),
}, },
{ {
"name": "x-tag", "name": "x-tag",

View File

@ -1,7 +1,6 @@
import importlib import importlib
import pytest import pytest
from dirty_equals import IsDict
from fastapi.testclient import TestClient from fastapi.testclient import TestClient
from inline_snapshot import snapshot from inline_snapshot import snapshot
@ -64,22 +63,12 @@ def test_header_param_model_invalid(client: TestClient):
assert response.json() == snapshot( assert response.json() == snapshot(
{ {
"detail": [ "detail": [
IsDict( {
{ "type": "missing",
"type": "missing", "loc": ["header", "save_data"],
"loc": ["header", "save_data"], "msg": "Field required",
"msg": "Field required", "input": {"x_tag": [], "host": "testserver"},
"input": {"x_tag": [], "host": "testserver"}, }
}
)
| IsDict(
# TODO: remove when deprecating Pydantic v1
{
"type": "value_error.missing",
"loc": ["header", "save_data"],
"msg": "field required",
}
)
] ]
} }
) )
@ -93,22 +82,12 @@ def test_header_param_model_extra(client: TestClient):
assert response.json() == snapshot( assert response.json() == snapshot(
{ {
"detail": [ "detail": [
IsDict( {
{ "type": "extra_forbidden",
"type": "extra_forbidden", "loc": ["header", "tool"],
"loc": ["header", "tool"], "msg": "Extra inputs are not permitted",
"msg": "Extra inputs are not permitted", "input": "plumbus",
"input": "plumbus", }
}
)
| IsDict(
# TODO: remove when deprecating Pydantic v1
{
"type": "value_error.extra",
"loc": ["header", "tool"],
"msg": "extra fields not permitted",
}
)
] ]
} }
) )
@ -143,37 +122,19 @@ def test_openapi_schema(client: TestClient):
"name": "if-modified-since", "name": "if-modified-since",
"in": "header", "in": "header",
"required": False, "required": False,
"schema": IsDict( "schema": {
{ "anyOf": [{"type": "string"}, {"type": "null"}],
"anyOf": [{"type": "string"}, {"type": "null"}], "title": "If Modified Since",
"title": "If Modified Since", },
}
)
| IsDict(
# TODO: remove when deprecating Pydantic v1
{
"type": "string",
"title": "If Modified Since",
}
),
}, },
{ {
"name": "traceparent", "name": "traceparent",
"in": "header", "in": "header",
"required": False, "required": False,
"schema": IsDict( "schema": {
{ "anyOf": [{"type": "string"}, {"type": "null"}],
"anyOf": [{"type": "string"}, {"type": "null"}], "title": "Traceparent",
"title": "Traceparent", },
}
)
| IsDict(
# TODO: remove when deprecating Pydantic v1
{
"type": "string",
"title": "Traceparent",
}
),
}, },
{ {
"name": "x-tag", "name": "x-tag",

View File

@ -1,7 +1,6 @@
import importlib import importlib
import pytest import pytest
from dirty_equals import IsDict
from fastapi.testclient import TestClient from fastapi.testclient import TestClient
from inline_snapshot import snapshot from inline_snapshot import snapshot
@ -60,33 +59,23 @@ def test_header_param_model_no_underscore(client: TestClient):
assert response.json() == snapshot( assert response.json() == snapshot(
{ {
"detail": [ "detail": [
IsDict( {
{ "type": "missing",
"type": "missing", "loc": ["header", "save_data"],
"loc": ["header", "save_data"], "msg": "Field required",
"msg": "Field required", "input": {
"input": { "host": "testserver",
"host": "testserver", "traceparent": "123",
"traceparent": "123", "x_tag": [],
"x_tag": [], "accept": "*/*",
"accept": "*/*", "accept-encoding": "gzip, deflate",
"accept-encoding": "gzip, deflate", "connection": "keep-alive",
"connection": "keep-alive", "user-agent": "testclient",
"user-agent": "testclient", "save-data": "true",
"save-data": "true", "if-modified-since": "yesterday",
"if-modified-since": "yesterday", "x-tag": ["one", "two"],
"x-tag": ["one", "two"], },
}, }
}
)
| IsDict(
# TODO: remove when deprecating Pydantic v1
{
"type": "value_error.missing",
"loc": ["header", "save_data"],
"msg": "field required",
}
)
] ]
} }
) )
@ -110,29 +99,19 @@ def test_header_param_model_invalid(client: TestClient):
assert response.json() == snapshot( assert response.json() == snapshot(
{ {
"detail": [ "detail": [
IsDict( {
{ "type": "missing",
"type": "missing", "loc": ["header", "save_data"],
"loc": ["header", "save_data"], "msg": "Field required",
"msg": "Field required", "input": {
"input": { "x_tag": [],
"x_tag": [], "host": "testserver",
"host": "testserver", "accept": "*/*",
"accept": "*/*", "accept-encoding": "gzip, deflate",
"accept-encoding": "gzip, deflate", "connection": "keep-alive",
"connection": "keep-alive", "user-agent": "testclient",
"user-agent": "testclient", },
}, }
}
)
| IsDict(
# TODO: remove when deprecating Pydantic v1
{
"type": "value_error.missing",
"loc": ["header", "save_data"],
"msg": "field required",
}
)
] ]
} }
) )
@ -183,37 +162,19 @@ def test_openapi_schema(client: TestClient):
"name": "if_modified_since", "name": "if_modified_since",
"in": "header", "in": "header",
"required": False, "required": False,
"schema": IsDict( "schema": {
{ "anyOf": [{"type": "string"}, {"type": "null"}],
"anyOf": [{"type": "string"}, {"type": "null"}], "title": "If Modified Since",
"title": "If Modified Since", },
}
)
| IsDict(
# TODO: remove when deprecating Pydantic v1
{
"type": "string",
"title": "If Modified Since",
}
),
}, },
{ {
"name": "traceparent", "name": "traceparent",
"in": "header", "in": "header",
"required": False, "required": False,
"schema": IsDict( "schema": {
{ "anyOf": [{"type": "string"}, {"type": "null"}],
"anyOf": [{"type": "string"}, {"type": "null"}], "title": "Traceparent",
"title": "Traceparent", },
}
)
| IsDict(
# TODO: remove when deprecating Pydantic v1
{
"type": "string",
"title": "Traceparent",
}
),
}, },
{ {
"name": "x_tag", "name": "x_tag",

View File

@ -1,7 +1,6 @@
import importlib import importlib
import pytest import pytest
from dirty_equals import IsDict
from fastapi.testclient import TestClient from fastapi.testclient import TestClient
from ...utils import needs_py310 from ...utils import needs_py310
@ -67,16 +66,10 @@ def test_openapi_schema(client: TestClient):
"parameters": [ "parameters": [
{ {
"required": False, "required": False,
"schema": IsDict( "schema": {
{ "anyOf": [{"type": "string"}, {"type": "null"}],
"anyOf": [{"type": "string"}, {"type": "null"}], "title": "User-Agent",
"title": "User-Agent", },
}
)
| IsDict(
# TODO: remove when deprecating Pydantic v1
{"title": "User-Agent", "type": "string"}
),
"name": "user-agent", "name": "user-agent",
"in": "header", "in": "header",
} }

View File

@ -1,7 +1,6 @@
import importlib import importlib
import pytest import pytest
from dirty_equals import IsDict
from fastapi.testclient import TestClient from fastapi.testclient import TestClient
from ...utils import needs_py310 from ...utils import needs_py310
@ -78,16 +77,10 @@ def test_openapi_schema(client: TestClient):
"parameters": [ "parameters": [
{ {
"required": False, "required": False,
"schema": IsDict( "schema": {
{ "anyOf": [{"type": "string"}, {"type": "null"}],
"anyOf": [{"type": "string"}, {"type": "null"}], "title": "Strange Header",
"title": "Strange Header", },
}
)
| IsDict(
# TODO: remove when deprecating Pydantic v1
{"title": "Strange Header", "type": "string"}
),
"name": "strange_header", "name": "strange_header",
"in": "header", "in": "header",
} }

View File

@ -1,7 +1,6 @@
import importlib import importlib
import pytest import pytest
from dirty_equals import IsDict
from fastapi.testclient import TestClient from fastapi.testclient import TestClient
from ...utils import needs_py310 from ...utils import needs_py310
@ -56,23 +55,13 @@ def test_openapi_schema(client: TestClient):
"parameters": [ "parameters": [
{ {
"required": False, "required": False,
"schema": IsDict( "schema": {
{ "title": "X-Token",
"title": "X-Token", "anyOf": [
"anyOf": [ {"type": "array", "items": {"type": "string"}},
{"type": "array", "items": {"type": "string"}}, {"type": "null"},
{"type": "null"}, ],
], },
}
)
| IsDict(
# TODO: remove when deprecating Pydantic v1
{
"title": "X-Token",
"type": "array",
"items": {"type": "string"},
}
),
"name": "x-token", "name": "x-token",
"in": "header", "in": "header",
} }

View File

@ -2,7 +2,6 @@ import importlib
from types import ModuleType from types import ModuleType
import pytest import pytest
from dirty_equals import IsDict
from fastapi.testclient import TestClient from fastapi.testclient import TestClient
from tests.utils import needs_py310 from tests.utils import needs_py310
@ -55,30 +54,18 @@ def test_openapi_schema(client: TestClient):
"parameters": [ "parameters": [
{ {
"required": False, "required": False,
"schema": IsDict( "schema": {
{ "anyOf": [
"anyOf": [ {
{ "type": "string",
"type": "string", "format": "uri",
"format": "uri", "minLength": 1,
"minLength": 1, "maxLength": 2083,
"maxLength": 2083, },
}, {"type": "null"},
{"type": "null"}, ],
], "title": "Callback Url",
"title": "Callback Url", },
}
)
| IsDict(
# TODO: remove when deprecating Pydantic v1
{
"title": "Callback Url",
"maxLength": 2083,
"minLength": 1,
"type": "string",
"format": "uri",
}
),
"name": "callback_url", "name": "callback_url",
"in": "query", "in": "query",
} }
@ -171,16 +158,10 @@ def test_openapi_schema(client: TestClient):
"type": "object", "type": "object",
"properties": { "properties": {
"id": {"title": "Id", "type": "string"}, "id": {"title": "Id", "type": "string"},
"title": IsDict( "title": {
{ "title": "Title",
"title": "Title", "anyOf": [{"type": "string"}, {"type": "null"}],
"anyOf": [{"type": "string"}, {"type": "null"}], },
}
)
| IsDict(
# TODO: remove when deprecating Pydantic v1
{"title": "Title", "type": "string"}
),
"customer": {"title": "Customer", "type": "string"}, "customer": {"title": "Customer", "type": "string"},
"total": {"title": "Total", "type": "number"}, "total": {"title": "Total", "type": "number"},
}, },

View File

@ -1,4 +1,3 @@
from dirty_equals import IsDict
from fastapi.testclient import TestClient from fastapi.testclient import TestClient
from docs_src.path_params.tutorial005_py39 import app from docs_src.path_params.tutorial005_py39 import app
@ -27,31 +26,17 @@ def test_get_enums_resnet():
def test_get_enums_invalid(): def test_get_enums_invalid():
response = client.get("/models/foo") response = client.get("/models/foo")
assert response.status_code == 422 assert response.status_code == 422
assert response.json() == IsDict( assert response.json() == {
{ "detail": [
"detail": [ {
{ "type": "enum",
"type": "enum", "loc": ["path", "model_name"],
"loc": ["path", "model_name"], "msg": "Input should be 'alexnet', 'resnet' or 'lenet'",
"msg": "Input should be 'alexnet', 'resnet' or 'lenet'", "input": "foo",
"input": "foo", "ctx": {"expected": "'alexnet', 'resnet' or 'lenet'"},
"ctx": {"expected": "'alexnet', 'resnet' or 'lenet'"}, }
} ]
] }
}
) | IsDict(
# TODO: remove when deprecating Pydantic v1
{
"detail": [
{
"ctx": {"enum_values": ["alexnet", "resnet", "lenet"]},
"loc": ["path", "model_name"],
"msg": "value is not a valid enumeration member; permitted: 'alexnet', 'resnet', 'lenet'",
"type": "type_error.enum",
}
]
}
)
def test_openapi_schema(): def test_openapi_schema():
@ -106,22 +91,11 @@ def test_openapi_schema():
} }
}, },
}, },
"ModelName": IsDict( "ModelName": {
{ "title": "ModelName",
"title": "ModelName", "enum": ["alexnet", "resnet", "lenet"],
"enum": ["alexnet", "resnet", "lenet"], "type": "string",
"type": "string", },
}
)
| IsDict(
{
# TODO: remove when deprecating Pydantic v1
"title": "ModelName",
"enum": ["alexnet", "resnet", "lenet"],
"type": "string",
"description": "An enumeration.",
}
),
"ValidationError": { "ValidationError": {
"title": "ValidationError", "title": "ValidationError",
"required": ["loc", "msg", "type"], "required": ["loc", "msg", "type"],

View File

@ -1,7 +1,6 @@
import importlib import importlib
import pytest import pytest
from dirty_equals import IsDict
from fastapi.testclient import TestClient from fastapi.testclient import TestClient
from inline_snapshot import snapshot from inline_snapshot import snapshot
@ -65,61 +64,31 @@ def test_query_param_model_invalid(client: TestClient):
) )
assert response.status_code == 422 assert response.status_code == 422
assert response.json() == snapshot( assert response.json() == snapshot(
IsDict( {
{ "detail": [
"detail": [ {
{ "type": "less_than_equal",
"type": "less_than_equal", "loc": ["query", "limit"],
"loc": ["query", "limit"], "msg": "Input should be less than or equal to 100",
"msg": "Input should be less than or equal to 100", "input": "150",
"input": "150", "ctx": {"le": 100},
"ctx": {"le": 100}, },
}, {
{ "type": "greater_than_equal",
"type": "greater_than_equal", "loc": ["query", "offset"],
"loc": ["query", "offset"], "msg": "Input should be greater than or equal to 0",
"msg": "Input should be greater than or equal to 0", "input": "-1",
"input": "-1", "ctx": {"ge": 0},
"ctx": {"ge": 0}, },
}, {
{ "type": "literal_error",
"type": "literal_error", "loc": ["query", "order_by"],
"loc": ["query", "order_by"], "msg": "Input should be 'created_at' or 'updated_at'",
"msg": "Input should be 'created_at' or 'updated_at'", "input": "invalid",
"input": "invalid", "ctx": {"expected": "'created_at' or 'updated_at'"},
"ctx": {"expected": "'created_at' or 'updated_at'"}, },
}, ]
] }
}
)
| IsDict(
# TODO: remove when deprecating Pydantic v1
{
"detail": [
{
"type": "value_error.number.not_le",
"loc": ["query", "limit"],
"msg": "ensure this value is less than or equal to 100",
"ctx": {"limit_value": 100},
},
{
"type": "value_error.number.not_ge",
"loc": ["query", "offset"],
"msg": "ensure this value is greater than or equal to 0",
"ctx": {"limit_value": 0},
},
{
"type": "value_error.const",
"loc": ["query", "order_by"],
"msg": "unexpected value; permitted: 'created_at', 'updated_at'",
"ctx": {
"given": "invalid",
"permitted": ["created_at", "updated_at"],
},
},
]
}
)
) )

View File

@ -1,7 +1,6 @@
import importlib import importlib
import pytest import pytest
from dirty_equals import IsDict
from fastapi.testclient import TestClient from fastapi.testclient import TestClient
from inline_snapshot import snapshot from inline_snapshot import snapshot
@ -65,61 +64,31 @@ def test_query_param_model_invalid(client: TestClient):
) )
assert response.status_code == 422 assert response.status_code == 422
assert response.json() == snapshot( assert response.json() == snapshot(
IsDict( {
{ "detail": [
"detail": [ {
{ "type": "less_than_equal",
"type": "less_than_equal", "loc": ["query", "limit"],
"loc": ["query", "limit"], "msg": "Input should be less than or equal to 100",
"msg": "Input should be less than or equal to 100", "input": "150",
"input": "150", "ctx": {"le": 100},
"ctx": {"le": 100}, },
}, {
{ "type": "greater_than_equal",
"type": "greater_than_equal", "loc": ["query", "offset"],
"loc": ["query", "offset"], "msg": "Input should be greater than or equal to 0",
"msg": "Input should be greater than or equal to 0", "input": "-1",
"input": "-1", "ctx": {"ge": 0},
"ctx": {"ge": 0}, },
}, {
{ "type": "literal_error",
"type": "literal_error", "loc": ["query", "order_by"],
"loc": ["query", "order_by"], "msg": "Input should be 'created_at' or 'updated_at'",
"msg": "Input should be 'created_at' or 'updated_at'", "input": "invalid",
"input": "invalid", "ctx": {"expected": "'created_at' or 'updated_at'"},
"ctx": {"expected": "'created_at' or 'updated_at'"}, },
}, ]
] }
}
)
| IsDict(
# TODO: remove when deprecating Pydantic v1
{
"detail": [
{
"type": "value_error.number.not_le",
"loc": ["query", "limit"],
"msg": "ensure this value is less than or equal to 100",
"ctx": {"limit_value": 100},
},
{
"type": "value_error.number.not_ge",
"loc": ["query", "offset"],
"msg": "ensure this value is greater than or equal to 0",
"ctx": {"limit_value": 0},
},
{
"type": "value_error.const",
"loc": ["query", "order_by"],
"msg": "unexpected value; permitted: 'created_at', 'updated_at'",
"ctx": {
"given": "invalid",
"permitted": ["created_at", "updated_at"],
},
},
]
}
)
) )
@ -138,22 +107,12 @@ def test_query_param_model_extra(client: TestClient):
assert response.json() == snapshot( assert response.json() == snapshot(
{ {
"detail": [ "detail": [
IsDict( {
{ "type": "extra_forbidden",
"type": "extra_forbidden", "loc": ["query", "tool"],
"loc": ["query", "tool"], "msg": "Extra inputs are not permitted",
"msg": "Extra inputs are not permitted", "input": "plumbus",
"input": "plumbus", }
}
)
| IsDict(
# TODO: remove when deprecating Pydantic v1
{
"type": "value_error.extra",
"loc": ["query", "tool"],
"msg": "extra fields not permitted",
}
)
] ]
} }
) )

View File

@ -1,4 +1,3 @@
from dirty_equals import IsDict
from fastapi.testclient import TestClient from fastapi.testclient import TestClient
from docs_src.query_params.tutorial005_py39 import app from docs_src.query_params.tutorial005_py39 import app
@ -15,29 +14,16 @@ def test_foo_needy_very():
def test_foo_no_needy(): def test_foo_no_needy():
response = client.get("/items/foo") response = client.get("/items/foo")
assert response.status_code == 422 assert response.status_code == 422
assert response.json() == IsDict( assert response.json() == {
{ "detail": [
"detail": [ {
{ "type": "missing",
"type": "missing", "loc": ["query", "needy"],
"loc": ["query", "needy"], "msg": "Field required",
"msg": "Field required", "input": None,
"input": None, }
} ]
] }
}
) | IsDict(
# TODO: remove when deprecating Pydantic v1
{
"detail": [
{
"loc": ["query", "needy"],
"msg": "field required",
"type": "value_error.missing",
}
]
}
)
def test_openapi_schema(): def test_openapi_schema():

View File

@ -1,7 +1,6 @@
import importlib import importlib
import pytest import pytest
from dirty_equals import IsDict
from fastapi.testclient import TestClient from fastapi.testclient import TestClient
from ...utils import needs_py310 from ...utils import needs_py310
@ -35,51 +34,28 @@ def test_foo_needy_very(client: TestClient):
def test_foo_no_needy(client: TestClient): def test_foo_no_needy(client: TestClient):
response = client.get("/items/foo?skip=a&limit=b") response = client.get("/items/foo?skip=a&limit=b")
assert response.status_code == 422 assert response.status_code == 422
assert response.json() == IsDict( assert response.json() == {
{ "detail": [
"detail": [ {
{ "type": "missing",
"type": "missing", "loc": ["query", "needy"],
"loc": ["query", "needy"], "msg": "Field required",
"msg": "Field required", "input": None,
"input": None, },
}, {
{ "type": "int_parsing",
"type": "int_parsing", "loc": ["query", "skip"],
"loc": ["query", "skip"], "msg": "Input should be a valid integer, unable to parse string as an integer",
"msg": "Input should be a valid integer, unable to parse string as an integer", "input": "a",
"input": "a", },
}, {
{ "type": "int_parsing",
"type": "int_parsing", "loc": ["query", "limit"],
"loc": ["query", "limit"], "msg": "Input should be a valid integer, unable to parse string as an integer",
"msg": "Input should be a valid integer, unable to parse string as an integer", "input": "b",
"input": "b", },
}, ]
] }
}
) | IsDict(
# TODO: remove when deprecating Pydantic v1
{
"detail": [
{
"loc": ["query", "needy"],
"msg": "field required",
"type": "value_error.missing",
},
{
"loc": ["query", "skip"],
"msg": "value is not a valid integer",
"type": "type_error.integer",
},
{
"loc": ["query", "limit"],
"msg": "value is not a valid integer",
"type": "type_error.integer",
},
]
}
)
def test_openapi_schema(client: TestClient): def test_openapi_schema(client: TestClient):
@ -134,16 +110,10 @@ def test_openapi_schema(client: TestClient):
}, },
{ {
"required": False, "required": False,
"schema": IsDict( "schema": {
{ "anyOf": [{"type": "integer"}, {"type": "null"}],
"anyOf": [{"type": "integer"}, {"type": "null"}], "title": "Limit",
"title": "Limit", },
}
)
| IsDict(
# TODO: remove when deprecating Pydantic v1
{"title": "Limit", "type": "integer"}
),
"name": "limit", "name": "limit",
"in": "query", "in": "query",
}, },

View File

@ -1,7 +1,6 @@
import importlib import importlib
import pytest import pytest
from dirty_equals import IsDict
from fastapi._compat import PYDANTIC_VERSION_MINOR_TUPLE from fastapi._compat import PYDANTIC_VERSION_MINOR_TUPLE
from fastapi.testclient import TestClient from fastapi.testclient import TestClient
@ -50,31 +49,17 @@ def test_query_params_str_validations_q_fixedquery(client: TestClient):
def test_query_params_str_validations_item_query_nonregexquery(client: TestClient): def test_query_params_str_validations_item_query_nonregexquery(client: TestClient):
response = client.get("/items/", params={"item-query": "nonregexquery"}) response = client.get("/items/", params={"item-query": "nonregexquery"})
assert response.status_code == 422 assert response.status_code == 422
assert response.json() == IsDict( assert response.json() == {
{ "detail": [
"detail": [ {
{ "type": "string_pattern_mismatch",
"type": "string_pattern_mismatch", "loc": ["query", "item-query"],
"loc": ["query", "item-query"], "msg": "String should match pattern '^fixedquery$'",
"msg": "String should match pattern '^fixedquery$'", "input": "nonregexquery",
"input": "nonregexquery", "ctx": {"pattern": "^fixedquery$"},
"ctx": {"pattern": "^fixedquery$"}, }
} ]
] }
}
) | IsDict(
# TODO: remove when deprecating Pydantic v1
{
"detail": [
{
"ctx": {"pattern": "^fixedquery$"},
"loc": ["query", "item-query"],
"msg": 'string does not match regex "^fixedquery$"',
"type": "value_error.str.regex",
}
]
}
)
def test_openapi_schema(client: TestClient): def test_openapi_schema(client: TestClient):
@ -109,38 +94,25 @@ def test_openapi_schema(client: TestClient):
"description": "Query string for the items to search in the database that have a good match", "description": "Query string for the items to search in the database that have a good match",
"required": False, "required": False,
"deprecated": True, "deprecated": True,
"schema": IsDict( "schema": {
{ "anyOf": [
"anyOf": [ {
{ "type": "string",
"type": "string", "minLength": 3,
"minLength": 3, "maxLength": 50,
"maxLength": 50, "pattern": "^fixedquery$",
"pattern": "^fixedquery$", },
}, {"type": "null"},
{"type": "null"}, ],
], "title": "Query string",
"title": "Query string", "description": "Query string for the items to search in the database that have a good match",
"description": "Query string for the items to search in the database that have a good match", # See https://github.com/pydantic/pydantic/blob/80353c29a824c55dea4667b328ba8f329879ac9f/tests/test_fastapi.sh#L25-L34.
# See https://github.com/pydantic/pydantic/blob/80353c29a824c55dea4667b328ba8f329879ac9f/tests/test_fastapi.sh#L25-L34. **(
**( {"deprecated": True}
{"deprecated": True} if PYDANTIC_VERSION_MINOR_TUPLE >= (2, 10)
if PYDANTIC_VERSION_MINOR_TUPLE >= (2, 10) else {}
else {} ),
), },
}
)
| IsDict(
# TODO: remove when deprecating Pydantic v1
{
"title": "Query string",
"maxLength": 50,
"minLength": 3,
"pattern": "^fixedquery$",
"type": "string",
"description": "Query string for the items to search in the database that have a good match",
}
),
"name": "item-query", "name": "item-query",
"in": "query", "in": "query",
} }

View File

@ -1,7 +1,6 @@
import importlib import importlib
import pytest import pytest
from dirty_equals import IsDict
from fastapi.testclient import TestClient from fastapi.testclient import TestClient
from ...utils import needs_py310 from ...utils import needs_py310
@ -69,23 +68,13 @@ def test_openapi_schema(client: TestClient):
"parameters": [ "parameters": [
{ {
"required": False, "required": False,
"schema": IsDict( "schema": {
{ "anyOf": [
"anyOf": [ {"type": "array", "items": {"type": "string"}},
{"type": "array", "items": {"type": "string"}}, {"type": "null"},
{"type": "null"}, ],
], "title": "Q",
"title": "Q", },
}
)
| IsDict(
# TODO: remove when deprecating Pydantic v1
{
"title": "Q",
"type": "array",
"items": {"type": "string"},
}
),
"name": "q", "name": "q",
"in": "query", "in": "query",
} }

View File

@ -1,7 +1,6 @@
import importlib import importlib
import pytest import pytest
from dirty_equals import IsDict
from fastapi.testclient import TestClient from fastapi.testclient import TestClient
@ -22,57 +21,31 @@ def get_client(request: pytest.FixtureRequest):
def test_post_form_no_body(client: TestClient): def test_post_form_no_body(client: TestClient):
response = client.post("/files/") response = client.post("/files/")
assert response.status_code == 422, response.text assert response.status_code == 422, response.text
assert response.json() == IsDict( assert response.json() == {
{ "detail": [
"detail": [ {
{ "type": "missing",
"type": "missing", "loc": ["body", "file"],
"loc": ["body", "file"], "msg": "Field required",
"msg": "Field required", "input": None,
"input": None, }
} ]
] }
}
) | IsDict(
# TODO: remove when deprecating Pydantic v1
{
"detail": [
{
"loc": ["body", "file"],
"msg": "field required",
"type": "value_error.missing",
}
]
}
)
def test_post_body_json(client: TestClient): def test_post_body_json(client: TestClient):
response = client.post("/files/", json={"file": "Foo"}) response = client.post("/files/", json={"file": "Foo"})
assert response.status_code == 422, response.text assert response.status_code == 422, response.text
assert response.json() == IsDict( assert response.json() == {
{ "detail": [
"detail": [ {
{ "type": "missing",
"type": "missing", "loc": ["body", "file"],
"loc": ["body", "file"], "msg": "Field required",
"msg": "Field required", "input": None,
"input": None, }
} ]
] }
}
) | IsDict(
# TODO: remove when deprecating Pydantic v1
{
"detail": [
{
"loc": ["body", "file"],
"msg": "field required",
"type": "value_error.missing",
}
]
}
)
def test_post_file(tmp_path, client: TestClient): def test_post_file(tmp_path, client: TestClient):

View File

@ -2,8 +2,8 @@ import importlib
from pathlib import Path from pathlib import Path
import pytest import pytest
from dirty_equals import IsDict
from fastapi.testclient import TestClient from fastapi.testclient import TestClient
from inline_snapshot import snapshot
from ...utils import needs_py310 from ...utils import needs_py310
@ -59,166 +59,132 @@ def test_post_upload_file(tmp_path: Path, client: TestClient):
def test_openapi_schema(client: TestClient): def test_openapi_schema(client: TestClient):
response = client.get("/openapi.json") response = client.get("/openapi.json")
assert response.status_code == 200, response.text assert response.status_code == 200, response.text
assert response.json() == { assert response.json() == snapshot(
"openapi": "3.1.0", {
"info": {"title": "FastAPI", "version": "0.1.0"}, "openapi": "3.1.0",
"paths": { "info": {"title": "FastAPI", "version": "0.1.0"},
"/files/": { "paths": {
"post": { "/files/": {
"summary": "Create File", "post": {
"operationId": "create_file_files__post", "summary": "Create File",
"requestBody": { "operationId": "create_file_files__post",
"content": { "requestBody": {
"multipart/form-data": { "content": {
"schema": IsDict( "multipart/form-data": {
{ "schema": {
"allOf": [
{
"$ref": "#/components/schemas/Body_create_file_files__post"
}
],
"title": "Body",
}
)
| IsDict(
# TODO: remove when deprecating Pydantic v1
{
"$ref": "#/components/schemas/Body_create_file_files__post" "$ref": "#/components/schemas/Body_create_file_files__post"
} }
)
}
}
},
"responses": {
"200": {
"description": "Successful Response",
"content": {"application/json": {"schema": {}}},
},
"422": {
"description": "Validation Error",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/HTTPValidationError"
}
} }
}
},
"responses": {
"200": {
"description": "Successful Response",
"content": {"application/json": {"schema": {}}},
},
"422": {
"description": "Validation Error",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/HTTPValidationError"
}
}
},
}, },
}, },
}, }
} },
}, "/uploadfile/": {
"/uploadfile/": { "post": {
"post": { "summary": "Create Upload File",
"summary": "Create Upload File", "operationId": "create_upload_file_uploadfile__post",
"operationId": "create_upload_file_uploadfile__post", "requestBody": {
"requestBody": { "content": {
"content": { "multipart/form-data": {
"multipart/form-data": { "schema": {
"schema": IsDict(
{
"allOf": [
{
"$ref": "#/components/schemas/Body_create_upload_file_uploadfile__post"
}
],
"title": "Body",
}
)
| IsDict(
# TODO: remove when deprecating Pydantic v1
{
"$ref": "#/components/schemas/Body_create_upload_file_uploadfile__post" "$ref": "#/components/schemas/Body_create_upload_file_uploadfile__post"
} }
)
}
}
},
"responses": {
"200": {
"description": "Successful Response",
"content": {"application/json": {"schema": {}}},
},
"422": {
"description": "Validation Error",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/HTTPValidationError"
}
} }
}
},
"responses": {
"200": {
"description": "Successful Response",
"content": {"application/json": {"schema": {}}},
}, },
"422": {
"description": "Validation Error",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/HTTPValidationError"
}
}
},
},
},
}
},
},
"components": {
"schemas": {
"Body_create_file_files__post": {
"title": "Body_create_file_files__post",
"type": "object",
"properties": {
"file": {
"title": "File",
"anyOf": [
{"type": "string", "format": "binary"},
{"type": "null"},
],
}
},
},
"Body_create_upload_file_uploadfile__post": {
"title": "Body_create_upload_file_uploadfile__post",
"type": "object",
"properties": {
"file": {
"title": "File",
"anyOf": [
{"type": "string", "format": "binary"},
{"type": "null"},
],
}
},
},
"HTTPValidationError": {
"title": "HTTPValidationError",
"type": "object",
"properties": {
"detail": {
"title": "Detail",
"type": "array",
"items": {
"$ref": "#/components/schemas/ValidationError"
},
}
},
},
"ValidationError": {
"title": "ValidationError",
"required": ["loc", "msg", "type"],
"type": "object",
"properties": {
"loc": {
"title": "Location",
"type": "array",
"items": {
"anyOf": [{"type": "string"}, {"type": "integer"}]
},
},
"msg": {"title": "Message", "type": "string"},
"type": {"title": "Error Type", "type": "string"},
}, },
}, },
} }
}, },
}, }
"components": { )
"schemas": {
"Body_create_file_files__post": {
"title": "Body_create_file_files__post",
"type": "object",
"properties": {
"file": IsDict(
{
"title": "File",
"anyOf": [
{"type": "string", "format": "binary"},
{"type": "null"},
],
}
)
| IsDict(
# TODO: remove when deprecating Pydantic v1
{"title": "File", "type": "string", "format": "binary"}
)
},
},
"Body_create_upload_file_uploadfile__post": {
"title": "Body_create_upload_file_uploadfile__post",
"type": "object",
"properties": {
"file": IsDict(
{
"title": "File",
"anyOf": [
{"type": "string", "format": "binary"},
{"type": "null"},
],
}
)
| IsDict(
# TODO: remove when deprecating Pydantic v1
{"title": "File", "type": "string", "format": "binary"}
)
},
},
"HTTPValidationError": {
"title": "HTTPValidationError",
"type": "object",
"properties": {
"detail": {
"title": "Detail",
"type": "array",
"items": {"$ref": "#/components/schemas/ValidationError"},
}
},
},
"ValidationError": {
"title": "ValidationError",
"required": ["loc", "msg", "type"],
"type": "object",
"properties": {
"loc": {
"title": "Location",
"type": "array",
"items": {
"anyOf": [{"type": "string"}, {"type": "integer"}]
},
},
"msg": {"title": "Message", "type": "string"},
"type": {"title": "Error Type", "type": "string"},
},
},
}
},
}

View File

@ -1,7 +1,6 @@
import importlib import importlib
import pytest import pytest
from dirty_equals import IsDict
from fastapi import FastAPI from fastapi import FastAPI
from fastapi.testclient import TestClient from fastapi.testclient import TestClient
@ -28,57 +27,31 @@ def get_client(app: FastAPI):
def test_post_form_no_body(client: TestClient): def test_post_form_no_body(client: TestClient):
response = client.post("/files/") response = client.post("/files/")
assert response.status_code == 422, response.text assert response.status_code == 422, response.text
assert response.json() == IsDict( assert response.json() == {
{ "detail": [
"detail": [ {
{ "type": "missing",
"type": "missing", "loc": ["body", "files"],
"loc": ["body", "files"], "msg": "Field required",
"msg": "Field required", "input": None,
"input": None, }
} ]
] }
}
) | IsDict(
# TODO: remove when deprecating Pydantic v1
{
"detail": [
{
"loc": ["body", "files"],
"msg": "field required",
"type": "value_error.missing",
}
]
}
)
def test_post_body_json(client: TestClient): def test_post_body_json(client: TestClient):
response = client.post("/files/", json={"file": "Foo"}) response = client.post("/files/", json={"file": "Foo"})
assert response.status_code == 422, response.text assert response.status_code == 422, response.text
assert response.json() == IsDict( assert response.json() == {
{ "detail": [
"detail": [ {
{ "type": "missing",
"type": "missing", "loc": ["body", "files"],
"loc": ["body", "files"], "msg": "Field required",
"msg": "Field required", "input": None,
"input": None, }
} ]
] }
}
) | IsDict(
# TODO: remove when deprecating Pydantic v1
{
"detail": [
{
"loc": ["body", "files"],
"msg": "field required",
"type": "value_error.missing",
}
]
}
)
def test_post_files(tmp_path, app: FastAPI): def test_post_files(tmp_path, app: FastAPI):

View File

@ -1,7 +1,6 @@
import importlib import importlib
import pytest import pytest
from dirty_equals import IsDict
from fastapi.testclient import TestClient from fastapi.testclient import TestClient
@ -28,135 +27,73 @@ def test_post_body_form(client: TestClient):
def test_post_body_form_no_password(client: TestClient): def test_post_body_form_no_password(client: TestClient):
response = client.post("/login/", data={"username": "Foo"}) response = client.post("/login/", data={"username": "Foo"})
assert response.status_code == 422 assert response.status_code == 422
assert response.json() == IsDict( assert response.json() == {
{ "detail": [
"detail": [ {
{ "type": "missing",
"type": "missing", "loc": ["body", "password"],
"loc": ["body", "password"], "msg": "Field required",
"msg": "Field required", "input": {"username": "Foo"},
"input": {"username": "Foo"}, }
} ]
] }
}
) | IsDict(
# TODO: remove when deprecating Pydantic v1
{
"detail": [
{
"loc": ["body", "password"],
"msg": "field required",
"type": "value_error.missing",
}
]
}
)
def test_post_body_form_no_username(client: TestClient): def test_post_body_form_no_username(client: TestClient):
response = client.post("/login/", data={"password": "secret"}) response = client.post("/login/", data={"password": "secret"})
assert response.status_code == 422 assert response.status_code == 422
assert response.json() == IsDict( assert response.json() == {
{ "detail": [
"detail": [ {
{ "type": "missing",
"type": "missing", "loc": ["body", "username"],
"loc": ["body", "username"], "msg": "Field required",
"msg": "Field required", "input": {"password": "secret"},
"input": {"password": "secret"}, }
} ]
] }
}
) | IsDict(
# TODO: remove when deprecating Pydantic v1
{
"detail": [
{
"loc": ["body", "username"],
"msg": "field required",
"type": "value_error.missing",
}
]
}
)
def test_post_body_form_no_data(client: TestClient): def test_post_body_form_no_data(client: TestClient):
response = client.post("/login/") response = client.post("/login/")
assert response.status_code == 422 assert response.status_code == 422
assert response.json() == IsDict( assert response.json() == {
{ "detail": [
"detail": [ {
{ "type": "missing",
"type": "missing", "loc": ["body", "username"],
"loc": ["body", "username"], "msg": "Field required",
"msg": "Field required", "input": {},
"input": {}, },
}, {
{ "type": "missing",
"type": "missing", "loc": ["body", "password"],
"loc": ["body", "password"], "msg": "Field required",
"msg": "Field required", "input": {},
"input": {}, },
}, ]
] }
}
) | IsDict(
# TODO: remove when deprecating Pydantic v1
{
"detail": [
{
"loc": ["body", "username"],
"msg": "field required",
"type": "value_error.missing",
},
{
"loc": ["body", "password"],
"msg": "field required",
"type": "value_error.missing",
},
]
}
)
def test_post_body_json(client: TestClient): def test_post_body_json(client: TestClient):
response = client.post("/login/", json={"username": "Foo", "password": "secret"}) response = client.post("/login/", json={"username": "Foo", "password": "secret"})
assert response.status_code == 422, response.text assert response.status_code == 422, response.text
assert response.json() == IsDict( assert response.json() == {
{ "detail": [
"detail": [ {
{ "type": "missing",
"type": "missing", "loc": ["body", "username"],
"loc": ["body", "username"], "msg": "Field required",
"msg": "Field required", "input": {},
"input": {}, },
}, {
{ "type": "missing",
"type": "missing", "loc": ["body", "password"],
"loc": ["body", "password"], "msg": "Field required",
"msg": "Field required", "input": {},
"input": {}, },
}, ]
] }
}
) | IsDict(
# TODO: remove when deprecating Pydantic v1
{
"detail": [
{
"loc": ["body", "username"],
"msg": "field required",
"type": "value_error.missing",
},
{
"loc": ["body", "password"],
"msg": "field required",
"type": "value_error.missing",
},
]
}
)
def test_openapi_schema(client: TestClient): def test_openapi_schema(client: TestClient):

View File

@ -1,7 +1,6 @@
import importlib import importlib
import pytest import pytest
from dirty_equals import IsDict
from fastapi.testclient import TestClient from fastapi.testclient import TestClient
@ -28,135 +27,73 @@ def test_post_body_form(client: TestClient):
def test_post_body_form_no_password(client: TestClient): def test_post_body_form_no_password(client: TestClient):
response = client.post("/login/", data={"username": "Foo"}) response = client.post("/login/", data={"username": "Foo"})
assert response.status_code == 422 assert response.status_code == 422
assert response.json() == IsDict( assert response.json() == {
{ "detail": [
"detail": [ {
{ "type": "missing",
"type": "missing", "loc": ["body", "password"],
"loc": ["body", "password"], "msg": "Field required",
"msg": "Field required", "input": None,
"input": None, }
} ]
] }
}
) | IsDict(
# TODO: remove when deprecating Pydantic v1
{
"detail": [
{
"loc": ["body", "password"],
"msg": "field required",
"type": "value_error.missing",
}
]
}
)
def test_post_body_form_no_username(client: TestClient): def test_post_body_form_no_username(client: TestClient):
response = client.post("/login/", data={"password": "secret"}) response = client.post("/login/", data={"password": "secret"})
assert response.status_code == 422 assert response.status_code == 422
assert response.json() == IsDict( assert response.json() == {
{ "detail": [
"detail": [ {
{ "type": "missing",
"type": "missing", "loc": ["body", "username"],
"loc": ["body", "username"], "msg": "Field required",
"msg": "Field required", "input": None,
"input": None, }
} ]
] }
}
) | IsDict(
# TODO: remove when deprecating Pydantic v1
{
"detail": [
{
"loc": ["body", "username"],
"msg": "field required",
"type": "value_error.missing",
}
]
}
)
def test_post_body_form_no_data(client: TestClient): def test_post_body_form_no_data(client: TestClient):
response = client.post("/login/") response = client.post("/login/")
assert response.status_code == 422 assert response.status_code == 422
assert response.json() == IsDict( assert response.json() == {
{ "detail": [
"detail": [ {
{ "type": "missing",
"type": "missing", "loc": ["body", "username"],
"loc": ["body", "username"], "msg": "Field required",
"msg": "Field required", "input": None,
"input": None, },
}, {
{ "type": "missing",
"type": "missing", "loc": ["body", "password"],
"loc": ["body", "password"], "msg": "Field required",
"msg": "Field required", "input": None,
"input": None, },
}, ]
] }
}
) | IsDict(
# TODO: remove when deprecating Pydantic v1
{
"detail": [
{
"loc": ["body", "username"],
"msg": "field required",
"type": "value_error.missing",
},
{
"loc": ["body", "password"],
"msg": "field required",
"type": "value_error.missing",
},
]
}
)
def test_post_body_json(client: TestClient): def test_post_body_json(client: TestClient):
response = client.post("/login/", json={"username": "Foo", "password": "secret"}) response = client.post("/login/", json={"username": "Foo", "password": "secret"})
assert response.status_code == 422, response.text assert response.status_code == 422, response.text
assert response.json() == IsDict( assert response.json() == {
{ "detail": [
"detail": [ {
{ "type": "missing",
"type": "missing", "loc": ["body", "username"],
"loc": ["body", "username"], "msg": "Field required",
"msg": "Field required", "input": None,
"input": None, },
}, {
{ "type": "missing",
"type": "missing", "loc": ["body", "password"],
"loc": ["body", "password"], "msg": "Field required",
"msg": "Field required", "input": None,
"input": None, },
}, ]
] }
}
) | IsDict(
# TODO: remove when deprecating Pydantic v1
{
"detail": [
{
"loc": ["body", "username"],
"msg": "field required",
"type": "value_error.missing",
},
{
"loc": ["body", "password"],
"msg": "field required",
"type": "value_error.missing",
},
]
}
)
def test_openapi_schema(client: TestClient): def test_openapi_schema(client: TestClient):

View File

@ -1,7 +1,6 @@
import importlib import importlib
import pytest import pytest
from dirty_equals import IsDict
from fastapi import FastAPI from fastapi import FastAPI
from fastapi.testclient import TestClient from fastapi.testclient import TestClient
@ -28,140 +27,76 @@ def get_client(app: FastAPI):
def test_post_form_no_body(client: TestClient): def test_post_form_no_body(client: TestClient):
response = client.post("/files/") response = client.post("/files/")
assert response.status_code == 422, response.text assert response.status_code == 422, response.text
assert response.json() == IsDict( assert response.json() == {
{ "detail": [
"detail": [ {
{ "type": "missing",
"type": "missing", "loc": ["body", "file"],
"loc": ["body", "file"], "msg": "Field required",
"msg": "Field required", "input": None,
"input": None, },
}, {
{ "type": "missing",
"type": "missing", "loc": ["body", "fileb"],
"loc": ["body", "fileb"], "msg": "Field required",
"msg": "Field required", "input": None,
"input": None, },
}, {
{ "type": "missing",
"type": "missing", "loc": ["body", "token"],
"loc": ["body", "token"], "msg": "Field required",
"msg": "Field required", "input": None,
"input": None, },
}, ]
] }
}
) | IsDict(
# TODO: remove when deprecating Pydantic v1
{
"detail": [
{
"loc": ["body", "file"],
"msg": "field required",
"type": "value_error.missing",
},
{
"loc": ["body", "fileb"],
"msg": "field required",
"type": "value_error.missing",
},
{
"loc": ["body", "token"],
"msg": "field required",
"type": "value_error.missing",
},
]
}
)
def test_post_form_no_file(client: TestClient): def test_post_form_no_file(client: TestClient):
response = client.post("/files/", data={"token": "foo"}) response = client.post("/files/", data={"token": "foo"})
assert response.status_code == 422, response.text assert response.status_code == 422, response.text
assert response.json() == IsDict( assert response.json() == {
{ "detail": [
"detail": [ {
{ "type": "missing",
"type": "missing", "loc": ["body", "file"],
"loc": ["body", "file"], "msg": "Field required",
"msg": "Field required", "input": None,
"input": None, },
}, {
{ "type": "missing",
"type": "missing", "loc": ["body", "fileb"],
"loc": ["body", "fileb"], "msg": "Field required",
"msg": "Field required", "input": None,
"input": None, },
}, ]
] }
}
) | IsDict(
# TODO: remove when deprecating Pydantic v1
{
"detail": [
{
"loc": ["body", "file"],
"msg": "field required",
"type": "value_error.missing",
},
{
"loc": ["body", "fileb"],
"msg": "field required",
"type": "value_error.missing",
},
]
}
)
def test_post_body_json(client: TestClient): def test_post_body_json(client: TestClient):
response = client.post("/files/", json={"file": "Foo", "token": "Bar"}) response = client.post("/files/", json={"file": "Foo", "token": "Bar"})
assert response.status_code == 422, response.text assert response.status_code == 422, response.text
assert response.json() == IsDict( assert response.json() == {
{ "detail": [
"detail": [ {
{ "type": "missing",
"type": "missing", "loc": ["body", "file"],
"loc": ["body", "file"], "msg": "Field required",
"msg": "Field required", "input": None,
"input": None, },
}, {
{ "type": "missing",
"type": "missing", "loc": ["body", "fileb"],
"loc": ["body", "fileb"], "msg": "Field required",
"msg": "Field required", "input": None,
"input": None, },
}, {
{ "type": "missing",
"type": "missing", "loc": ["body", "token"],
"loc": ["body", "token"], "msg": "Field required",
"msg": "Field required", "input": None,
"input": None, },
}, ]
] }
}
) | IsDict(
# TODO: remove when deprecating Pydantic v1
{
"detail": [
{
"loc": ["body", "file"],
"msg": "field required",
"type": "value_error.missing",
},
{
"loc": ["body", "fileb"],
"msg": "field required",
"type": "value_error.missing",
},
{
"loc": ["body", "token"],
"msg": "field required",
"type": "value_error.missing",
},
]
}
)
def test_post_file_no_token(tmp_path, app: FastAPI): def test_post_file_no_token(tmp_path, app: FastAPI):
@ -172,40 +107,22 @@ def test_post_file_no_token(tmp_path, app: FastAPI):
with path.open("rb") as file: with path.open("rb") as file:
response = client.post("/files/", files={"file": file}) response = client.post("/files/", files={"file": file})
assert response.status_code == 422, response.text assert response.status_code == 422, response.text
assert response.json() == IsDict( assert response.json() == {
{ "detail": [
"detail": [ {
{ "type": "missing",
"type": "missing", "loc": ["body", "fileb"],
"loc": ["body", "fileb"], "msg": "Field required",
"msg": "Field required", "input": None,
"input": None, },
}, {
{ "type": "missing",
"type": "missing", "loc": ["body", "token"],
"loc": ["body", "token"], "msg": "Field required",
"msg": "Field required", "input": None,
"input": None, },
}, ]
] }
}
) | IsDict(
# TODO: remove when deprecating Pydantic v1
{
"detail": [
{
"loc": ["body", "fileb"],
"msg": "field required",
"type": "value_error.missing",
},
{
"loc": ["body", "token"],
"msg": "field required",
"type": "value_error.missing",
},
]
}
)
def test_post_files_and_token(tmp_path, app: FastAPI): def test_post_files_and_token(tmp_path, app: FastAPI):

View File

@ -1,8 +1,8 @@
import importlib import importlib
import pytest import pytest
from dirty_equals import IsDict, IsOneOf
from fastapi.testclient import TestClient from fastapi.testclient import TestClient
from inline_snapshot import snapshot
from ...utils import needs_py310 from ...utils import needs_py310
@ -42,125 +42,115 @@ def test_post_user(client: TestClient):
def test_openapi_schema(client: TestClient): def test_openapi_schema(client: TestClient):
response = client.get("/openapi.json") response = client.get("/openapi.json")
assert response.status_code == 200, response.text assert response.status_code == 200, response.text
assert response.json() == { assert response.json() == snapshot(
"openapi": "3.1.0", {
"info": {"title": "FastAPI", "version": "0.1.0"}, "openapi": "3.1.0",
"paths": { "info": {"title": "FastAPI", "version": "0.1.0"},
"/user/": { "paths": {
"post": { "/user/": {
"responses": { "post": {
"200": { "responses": {
"description": "Successful Response", "200": {
"content": { "description": "Successful Response",
"application/json": { "content": {
"schema": {"$ref": "#/components/schemas/UserOut"} "application/json": {
} "schema": {
"$ref": "#/components/schemas/UserOut"
}
}
},
},
"422": {
"description": "Validation Error",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/HTTPValidationError"
}
}
},
}, },
}, },
"422": { "summary": "Create User",
"description": "Validation Error", "operationId": "create_user_user__post",
"requestBody": {
"content": { "content": {
"application/json": { "application/json": {
"schema": { "schema": {"$ref": "#/components/schemas/UserIn"}
"$ref": "#/components/schemas/HTTPValidationError"
}
} }
}, },
"required": True,
},
}
}
},
"components": {
"schemas": {
"UserOut": {
"title": "UserOut",
"required": ["username", "email"],
"type": "object",
"properties": {
"username": {"title": "Username", "type": "string"},
"email": {
"title": "Email",
"type": "string",
"format": "email",
},
"full_name": {
"title": "Full Name",
"anyOf": [{"type": "string"}, {"type": "null"}],
},
}, },
}, },
"summary": "Create User", "UserIn": {
"operationId": "create_user_user__post", "title": "UserIn",
"requestBody": { "required": ["username", "password", "email"],
"content": { "type": "object",
"application/json": { "properties": {
"schema": {"$ref": "#/components/schemas/UserIn"} "username": {"title": "Username", "type": "string"},
"password": {"title": "Password", "type": "string"},
"email": {
"title": "Email",
"type": "string",
"format": "email",
},
"full_name": {
"title": "Full Name",
"anyOf": [{"type": "string"}, {"type": "null"}],
},
},
},
"ValidationError": {
"title": "ValidationError",
"required": ["loc", "msg", "type"],
"type": "object",
"properties": {
"loc": {
"title": "Location",
"type": "array",
"items": {
"anyOf": [{"type": "string"}, {"type": "integer"}]
},
},
"msg": {"title": "Message", "type": "string"},
"type": {"title": "Error Type", "type": "string"},
},
},
"HTTPValidationError": {
"title": "HTTPValidationError",
"type": "object",
"properties": {
"detail": {
"title": "Detail",
"type": "array",
"items": {
"$ref": "#/components/schemas/ValidationError"
},
} }
}, },
"required": True,
}, },
} }
} },
}, }
"components": { )
"schemas": {
"UserOut": {
"title": "UserOut",
"required": IsOneOf(
["username", "email", "full_name"],
# TODO: remove when deprecating Pydantic v1
["username", "email"],
),
"type": "object",
"properties": {
"username": {"title": "Username", "type": "string"},
"email": {
"title": "Email",
"type": "string",
"format": "email",
},
"full_name": IsDict(
{
"title": "Full Name",
"anyOf": [{"type": "string"}, {"type": "null"}],
}
)
| IsDict(
# TODO: remove when deprecating Pydantic v1
{"title": "Full Name", "type": "string"}
),
},
},
"UserIn": {
"title": "UserIn",
"required": ["username", "password", "email"],
"type": "object",
"properties": {
"username": {"title": "Username", "type": "string"},
"password": {"title": "Password", "type": "string"},
"email": {
"title": "Email",
"type": "string",
"format": "email",
},
"full_name": IsDict(
{
"title": "Full Name",
"anyOf": [{"type": "string"}, {"type": "null"}],
}
)
| IsDict(
# TODO: remove when deprecating Pydantic v1
{"title": "Full Name", "type": "string"}
),
},
},
"ValidationError": {
"title": "ValidationError",
"required": ["loc", "msg", "type"],
"type": "object",
"properties": {
"loc": {
"title": "Location",
"type": "array",
"items": {
"anyOf": [{"type": "string"}, {"type": "integer"}]
},
},
"msg": {"title": "Message", "type": "string"},
"type": {"title": "Error Type", "type": "string"},
},
},
"HTTPValidationError": {
"title": "HTTPValidationError",
"type": "object",
"properties": {
"detail": {
"title": "Detail",
"type": "array",
"items": {"$ref": "#/components/schemas/ValidationError"},
}
},
},
}
},
}

View File

@ -1,8 +1,8 @@
import importlib import importlib
import pytest import pytest
from dirty_equals import IsDict, IsOneOf
from fastapi.testclient import TestClient from fastapi.testclient import TestClient
from inline_snapshot import snapshot
from ...utils import needs_py310 from ...utils import needs_py310
@ -42,125 +42,115 @@ def test_post_user(client: TestClient):
def test_openapi_schema(client: TestClient): def test_openapi_schema(client: TestClient):
response = client.get("/openapi.json") response = client.get("/openapi.json")
assert response.status_code == 200, response.text assert response.status_code == 200, response.text
assert response.json() == { assert response.json() == snapshot(
"openapi": "3.1.0", {
"info": {"title": "FastAPI", "version": "0.1.0"}, "openapi": "3.1.0",
"paths": { "info": {"title": "FastAPI", "version": "0.1.0"},
"/user/": { "paths": {
"post": { "/user/": {
"summary": "Create User", "post": {
"operationId": "create_user_user__post", "summary": "Create User",
"requestBody": { "operationId": "create_user_user__post",
"content": { "requestBody": {
"application/json": { "content": {
"schema": {"$ref": "#/components/schemas/UserIn"} "application/json": {
"schema": {"$ref": "#/components/schemas/UserIn"}
}
},
"required": True,
},
"responses": {
"200": {
"description": "Successful Response",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/BaseUser"
}
}
},
},
"422": {
"description": "Validation Error",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/HTTPValidationError"
}
}
},
},
},
}
}
},
"components": {
"schemas": {
"BaseUser": {
"title": "BaseUser",
"required": ["username", "email"],
"type": "object",
"properties": {
"username": {"title": "Username", "type": "string"},
"email": {
"title": "Email",
"type": "string",
"format": "email",
},
"full_name": {
"title": "Full Name",
"anyOf": [{"type": "string"}, {"type": "null"}],
},
},
},
"HTTPValidationError": {
"title": "HTTPValidationError",
"type": "object",
"properties": {
"detail": {
"title": "Detail",
"type": "array",
"items": {
"$ref": "#/components/schemas/ValidationError"
},
} }
}, },
"required": True,
}, },
"responses": { "UserIn": {
"200": { "title": "UserIn",
"description": "Successful Response", "required": ["username", "email", "password"],
"content": { "type": "object",
"application/json": { "properties": {
"schema": {"$ref": "#/components/schemas/BaseUser"} "username": {"title": "Username", "type": "string"},
} "email": {
"title": "Email",
"type": "string",
"format": "email",
}, },
"full_name": {
"title": "Full Name",
"anyOf": [{"type": "string"}, {"type": "null"}],
},
"password": {"title": "Password", "type": "string"},
}, },
"422": { },
"description": "Validation Error", "ValidationError": {
"content": { "title": "ValidationError",
"application/json": { "required": ["loc", "msg", "type"],
"schema": { "type": "object",
"$ref": "#/components/schemas/HTTPValidationError" "properties": {
} "loc": {
} "title": "Location",
"type": "array",
"items": {
"anyOf": [{"type": "string"}, {"type": "integer"}]
},
}, },
"msg": {"title": "Message", "type": "string"},
"type": {"title": "Error Type", "type": "string"},
}, },
}, },
} }
} },
}, }
"components": { )
"schemas": {
"BaseUser": {
"title": "BaseUser",
"required": IsOneOf(
["username", "email", "full_name"],
# TODO: remove when deprecating Pydantic v1
["username", "email"],
),
"type": "object",
"properties": {
"username": {"title": "Username", "type": "string"},
"email": {
"title": "Email",
"type": "string",
"format": "email",
},
"full_name": IsDict(
{
"title": "Full Name",
"anyOf": [{"type": "string"}, {"type": "null"}],
}
)
| IsDict(
# TODO: remove when deprecating Pydantic v1
{"title": "Full Name", "type": "string"}
),
},
},
"HTTPValidationError": {
"title": "HTTPValidationError",
"type": "object",
"properties": {
"detail": {
"title": "Detail",
"type": "array",
"items": {"$ref": "#/components/schemas/ValidationError"},
}
},
},
"UserIn": {
"title": "UserIn",
"required": ["username", "email", "password"],
"type": "object",
"properties": {
"username": {"title": "Username", "type": "string"},
"email": {
"title": "Email",
"type": "string",
"format": "email",
},
"full_name": IsDict(
{
"title": "Full Name",
"anyOf": [{"type": "string"}, {"type": "null"}],
}
)
| IsDict(
# TODO: remove when deprecating Pydantic v1
{"title": "Full Name", "type": "string"}
),
"password": {"title": "Password", "type": "string"},
},
},
"ValidationError": {
"title": "ValidationError",
"required": ["loc", "msg", "type"],
"type": "object",
"properties": {
"loc": {
"title": "Location",
"type": "array",
"items": {
"anyOf": [{"type": "string"}, {"type": "integer"}]
},
},
"msg": {"title": "Message", "type": "string"},
"type": {"title": "Error Type", "type": "string"},
},
},
}
},
}

View File

@ -1,8 +1,8 @@
import importlib import importlib
import pytest import pytest
from dirty_equals import IsDict, IsOneOf
from fastapi.testclient import TestClient from fastapi.testclient import TestClient
from inline_snapshot import snapshot
from ...utils import needs_py310 from ...utils import needs_py310
@ -50,104 +50,98 @@ def test_get(url, data, client: TestClient):
def test_openapi_schema(client: TestClient): def test_openapi_schema(client: TestClient):
response = client.get("/openapi.json") response = client.get("/openapi.json")
assert response.status_code == 200, response.text assert response.status_code == 200, response.text
assert response.json() == { assert response.json() == snapshot(
"openapi": "3.1.0", {
"info": {"title": "FastAPI", "version": "0.1.0"}, "openapi": "3.1.0",
"paths": { "info": {"title": "FastAPI", "version": "0.1.0"},
"/items/{item_id}": { "paths": {
"get": { "/items/{item_id}": {
"responses": { "get": {
"200": { "responses": {
"description": "Successful Response", "200": {
"content": { "description": "Successful Response",
"application/json": { "content": {
"schema": {"$ref": "#/components/schemas/Item"} "application/json": {
} "schema": {"$ref": "#/components/schemas/Item"}
},
},
"422": {
"description": "Validation Error",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/HTTPValidationError"
} }
} },
},
"422": {
"description": "Validation Error",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/HTTPValidationError"
}
}
},
}, },
}, },
}, "summary": "Read Item",
"summary": "Read Item", "operationId": "read_item_items__item_id__get",
"operationId": "read_item_items__item_id__get", "parameters": [
"parameters": [
{
"required": True,
"schema": {"title": "Item Id", "type": "string"},
"name": "item_id",
"in": "path",
}
],
}
}
},
"components": {
"schemas": {
"Item": {
"title": "Item",
"required": IsOneOf(
["name", "description", "price", "tax", "tags"],
# TODO: remove when deprecating Pydantic v1
["name", "price"],
),
"type": "object",
"properties": {
"name": {"title": "Name", "type": "string"},
"price": {"title": "Price", "type": "number"},
"description": IsDict(
{ {
"required": True,
"schema": {"title": "Item Id", "type": "string"},
"name": "item_id",
"in": "path",
}
],
}
}
},
"components": {
"schemas": {
"Item": {
"title": "Item",
"required": ["name", "price"],
"type": "object",
"properties": {
"name": {"title": "Name", "type": "string"},
"price": {"title": "Price", "type": "number"},
"description": {
"title": "Description", "title": "Description",
"anyOf": [{"type": "string"}, {"type": "null"}], "anyOf": [{"type": "string"}, {"type": "null"}],
} },
) "tax": {"title": "Tax", "type": "number", "default": 10.5},
| IsDict( "tags": {
# TODO: remove when deprecating Pydantic v1 "title": "Tags",
{"title": "Description", "type": "string"} "type": "array",
), "items": {"type": "string"},
"tax": {"title": "Tax", "type": "number", "default": 10.5}, "default": [],
"tags": {
"title": "Tags",
"type": "array",
"items": {"type": "string"},
"default": [],
},
},
},
"ValidationError": {
"title": "ValidationError",
"required": ["loc", "msg", "type"],
"type": "object",
"properties": {
"loc": {
"title": "Location",
"type": "array",
"items": {
"anyOf": [{"type": "string"}, {"type": "integer"}]
}, },
}, },
"msg": {"title": "Message", "type": "string"},
"type": {"title": "Error Type", "type": "string"},
}, },
}, "ValidationError": {
"HTTPValidationError": { "title": "ValidationError",
"title": "HTTPValidationError", "required": ["loc", "msg", "type"],
"type": "object", "type": "object",
"properties": { "properties": {
"detail": { "loc": {
"title": "Detail", "title": "Location",
"type": "array", "type": "array",
"items": {"$ref": "#/components/schemas/ValidationError"}, "items": {
} "anyOf": [{"type": "string"}, {"type": "integer"}]
},
},
"msg": {"title": "Message", "type": "string"},
"type": {"title": "Error Type", "type": "string"},
},
}, },
}, "HTTPValidationError": {
} "title": "HTTPValidationError",
}, "type": "object",
} "properties": {
"detail": {
"title": "Detail",
"type": "array",
"items": {
"$ref": "#/components/schemas/ValidationError"
},
}
},
},
}
},
}
)

View File

@ -1,8 +1,8 @@
import importlib import importlib
import pytest import pytest
from dirty_equals import IsDict, IsOneOf
from fastapi.testclient import TestClient from fastapi.testclient import TestClient
from inline_snapshot import snapshot
from ...utils import needs_py310 from ...utils import needs_py310
@ -40,132 +40,126 @@ def test_read_item_public_data(client: TestClient):
def test_openapi_schema(client: TestClient): def test_openapi_schema(client: TestClient):
response = client.get("/openapi.json") response = client.get("/openapi.json")
assert response.status_code == 200, response.text assert response.status_code == 200, response.text
assert response.json() == { assert response.json() == snapshot(
"openapi": "3.1.0", {
"info": {"title": "FastAPI", "version": "0.1.0"}, "openapi": "3.1.0",
"paths": { "info": {"title": "FastAPI", "version": "0.1.0"},
"/items/{item_id}/name": { "paths": {
"get": { "/items/{item_id}/name": {
"responses": { "get": {
"200": { "responses": {
"description": "Successful Response", "200": {
"content": { "description": "Successful Response",
"application/json": { "content": {
"schema": {"$ref": "#/components/schemas/Item"} "application/json": {
} "schema": {"$ref": "#/components/schemas/Item"}
},
},
"422": {
"description": "Validation Error",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/HTTPValidationError"
} }
} },
}, },
}, "422": {
}, "description": "Validation Error",
"summary": "Read Item Name", "content": {
"operationId": "read_item_name_items__item_id__name_get", "application/json": {
"parameters": [ "schema": {
{ "$ref": "#/components/schemas/HTTPValidationError"
"required": True, }
"schema": {"title": "Item Id", "type": "string"},
"name": "item_id",
"in": "path",
}
],
}
},
"/items/{item_id}/public": {
"get": {
"responses": {
"200": {
"description": "Successful Response",
"content": {
"application/json": {
"schema": {"$ref": "#/components/schemas/Item"}
}
},
},
"422": {
"description": "Validation Error",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/HTTPValidationError"
} }
} },
}, },
}, },
}, "summary": "Read Item Name",
"summary": "Read Item Public Data", "operationId": "read_item_name_items__item_id__name_get",
"operationId": "read_item_public_data_items__item_id__public_get", "parameters": [
"parameters": [
{
"required": True,
"schema": {"title": "Item Id", "type": "string"},
"name": "item_id",
"in": "path",
}
],
}
},
},
"components": {
"schemas": {
"Item": {
"title": "Item",
"required": IsOneOf(
["name", "description", "price", "tax"],
# TODO: remove when deprecating Pydantic v1
["name", "price"],
),
"type": "object",
"properties": {
"name": {"title": "Name", "type": "string"},
"price": {"title": "Price", "type": "number"},
"description": IsDict(
{ {
"required": True,
"schema": {"title": "Item Id", "type": "string"},
"name": "item_id",
"in": "path",
}
],
}
},
"/items/{item_id}/public": {
"get": {
"responses": {
"200": {
"description": "Successful Response",
"content": {
"application/json": {
"schema": {"$ref": "#/components/schemas/Item"}
}
},
},
"422": {
"description": "Validation Error",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/HTTPValidationError"
}
}
},
},
},
"summary": "Read Item Public Data",
"operationId": "read_item_public_data_items__item_id__public_get",
"parameters": [
{
"required": True,
"schema": {"title": "Item Id", "type": "string"},
"name": "item_id",
"in": "path",
}
],
}
},
},
"components": {
"schemas": {
"Item": {
"title": "Item",
"required": ["name", "price"],
"type": "object",
"properties": {
"name": {"title": "Name", "type": "string"},
"price": {"title": "Price", "type": "number"},
"description": {
"title": "Description", "title": "Description",
"anyOf": [{"type": "string"}, {"type": "null"}], "anyOf": [{"type": "string"}, {"type": "null"}],
}
)
| IsDict(
# TODO: remove when deprecating Pydantic v1
{"title": "Description", "type": "string"}
),
"tax": {"title": "Tax", "type": "number", "default": 10.5},
},
},
"ValidationError": {
"title": "ValidationError",
"required": ["loc", "msg", "type"],
"type": "object",
"properties": {
"loc": {
"title": "Location",
"type": "array",
"items": {
"anyOf": [{"type": "string"}, {"type": "integer"}]
}, },
"tax": {"title": "Tax", "type": "number", "default": 10.5},
}, },
"msg": {"title": "Message", "type": "string"},
"type": {"title": "Error Type", "type": "string"},
}, },
}, "ValidationError": {
"HTTPValidationError": { "title": "ValidationError",
"title": "HTTPValidationError", "required": ["loc", "msg", "type"],
"type": "object", "type": "object",
"properties": { "properties": {
"detail": { "loc": {
"title": "Detail", "title": "Location",
"type": "array", "type": "array",
"items": {"$ref": "#/components/schemas/ValidationError"}, "items": {
} "anyOf": [{"type": "string"}, {"type": "integer"}]
},
},
"msg": {"title": "Message", "type": "string"},
"type": {"title": "Error Type", "type": "string"},
},
}, },
}, "HTTPValidationError": {
} "title": "HTTPValidationError",
}, "type": "object",
} "properties": {
"detail": {
"title": "Detail",
"type": "array",
"items": {
"$ref": "#/components/schemas/ValidationError"
},
}
},
},
}
},
}
)

View File

@ -1,8 +1,8 @@
import importlib import importlib
import pytest import pytest
from dirty_equals import IsDict, IsOneOf
from fastapi.testclient import TestClient from fastapi.testclient import TestClient
from inline_snapshot import snapshot
from ...utils import needs_py310 from ...utils import needs_py310
@ -40,132 +40,126 @@ def test_read_item_public_data(client: TestClient):
def test_openapi_schema(client: TestClient): def test_openapi_schema(client: TestClient):
response = client.get("/openapi.json") response = client.get("/openapi.json")
assert response.status_code == 200, response.text assert response.status_code == 200, response.text
assert response.json() == { assert response.json() == snapshot(
"openapi": "3.1.0", {
"info": {"title": "FastAPI", "version": "0.1.0"}, "openapi": "3.1.0",
"paths": { "info": {"title": "FastAPI", "version": "0.1.0"},
"/items/{item_id}/name": { "paths": {
"get": { "/items/{item_id}/name": {
"responses": { "get": {
"200": { "responses": {
"description": "Successful Response", "200": {
"content": { "description": "Successful Response",
"application/json": { "content": {
"schema": {"$ref": "#/components/schemas/Item"} "application/json": {
} "schema": {"$ref": "#/components/schemas/Item"}
},
},
"422": {
"description": "Validation Error",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/HTTPValidationError"
} }
} },
}, },
}, "422": {
}, "description": "Validation Error",
"summary": "Read Item Name", "content": {
"operationId": "read_item_name_items__item_id__name_get", "application/json": {
"parameters": [ "schema": {
{ "$ref": "#/components/schemas/HTTPValidationError"
"required": True, }
"schema": {"title": "Item Id", "type": "string"},
"name": "item_id",
"in": "path",
}
],
}
},
"/items/{item_id}/public": {
"get": {
"responses": {
"200": {
"description": "Successful Response",
"content": {
"application/json": {
"schema": {"$ref": "#/components/schemas/Item"}
}
},
},
"422": {
"description": "Validation Error",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/HTTPValidationError"
} }
} },
}, },
}, },
}, "summary": "Read Item Name",
"summary": "Read Item Public Data", "operationId": "read_item_name_items__item_id__name_get",
"operationId": "read_item_public_data_items__item_id__public_get", "parameters": [
"parameters": [
{
"required": True,
"schema": {"title": "Item Id", "type": "string"},
"name": "item_id",
"in": "path",
}
],
}
},
},
"components": {
"schemas": {
"Item": {
"title": "Item",
"required": IsOneOf(
["name", "description", "price", "tax"],
# TODO: remove when deprecating Pydantic v1
["name", "price"],
),
"type": "object",
"properties": {
"name": {"title": "Name", "type": "string"},
"price": {"title": "Price", "type": "number"},
"description": IsDict(
{ {
"required": True,
"schema": {"title": "Item Id", "type": "string"},
"name": "item_id",
"in": "path",
}
],
}
},
"/items/{item_id}/public": {
"get": {
"responses": {
"200": {
"description": "Successful Response",
"content": {
"application/json": {
"schema": {"$ref": "#/components/schemas/Item"}
}
},
},
"422": {
"description": "Validation Error",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/HTTPValidationError"
}
}
},
},
},
"summary": "Read Item Public Data",
"operationId": "read_item_public_data_items__item_id__public_get",
"parameters": [
{
"required": True,
"schema": {"title": "Item Id", "type": "string"},
"name": "item_id",
"in": "path",
}
],
}
},
},
"components": {
"schemas": {
"Item": {
"title": "Item",
"required": ["name", "price"],
"type": "object",
"properties": {
"name": {"title": "Name", "type": "string"},
"price": {"title": "Price", "type": "number"},
"description": {
"title": "Description", "title": "Description",
"anyOf": [{"type": "string"}, {"type": "null"}], "anyOf": [{"type": "string"}, {"type": "null"}],
}
)
| IsDict(
# TODO: remove when deprecating Pydantic v1
{"title": "Description", "type": "string"}
),
"tax": {"title": "Tax", "type": "number", "default": 10.5},
},
},
"ValidationError": {
"title": "ValidationError",
"required": ["loc", "msg", "type"],
"type": "object",
"properties": {
"loc": {
"title": "Location",
"type": "array",
"items": {
"anyOf": [{"type": "string"}, {"type": "integer"}]
}, },
"tax": {"title": "Tax", "type": "number", "default": 10.5},
}, },
"msg": {"title": "Message", "type": "string"},
"type": {"title": "Error Type", "type": "string"},
}, },
}, "ValidationError": {
"HTTPValidationError": { "title": "ValidationError",
"title": "HTTPValidationError", "required": ["loc", "msg", "type"],
"type": "object", "type": "object",
"properties": { "properties": {
"detail": { "loc": {
"title": "Detail", "title": "Location",
"type": "array", "type": "array",
"items": {"$ref": "#/components/schemas/ValidationError"}, "items": {
} "anyOf": [{"type": "string"}, {"type": "integer"}]
},
},
"msg": {"title": "Message", "type": "string"},
"type": {"title": "Error Type", "type": "string"},
},
}, },
}, "HTTPValidationError": {
} "title": "HTTPValidationError",
}, "type": "object",
} "properties": {
"detail": {
"title": "Detail",
"type": "array",
"items": {
"$ref": "#/components/schemas/ValidationError"
},
}
},
},
}
},
}
)

View File

@ -1,7 +1,6 @@
import importlib import importlib
import pytest import pytest
from dirty_equals import IsDict
from fastapi.testclient import TestClient from fastapi.testclient import TestClient
from ...utils import needs_py310 from ...utils import needs_py310
@ -58,46 +57,22 @@ def test_openapi_schema(client: TestClient):
"requestBody": { "requestBody": {
"content": { "content": {
"application/json": { "application/json": {
"schema": IsDict( "schema": {
{ "$ref": "#/components/schemas/Item",
"$ref": "#/components/schemas/Item", "examples": [
"examples": [ {
{ "name": "Foo",
"name": "Foo", "description": "A very nice Item",
"description": "A very nice Item", "price": 35.4,
"price": 35.4, "tax": 3.2,
"tax": 3.2, },
}, {"name": "Bar", "price": "35.4"},
{"name": "Bar", "price": "35.4"}, {
{ "name": "Baz",
"name": "Baz", "price": "thirty five point four",
"price": "thirty five point four", },
}, ],
], }
}
)
| IsDict(
# TODO: remove when deprecating Pydantic v1
{
"allOf": [
{"$ref": "#/components/schemas/Item"}
],
"title": "Item",
"examples": [
{
"name": "Foo",
"description": "A very nice Item",
"price": 35.4,
"tax": 3.2,
},
{"name": "Bar", "price": "35.4"},
{
"name": "Baz",
"price": "thirty five point four",
},
],
}
)
} }
}, },
"required": True, "required": True,
@ -140,27 +115,15 @@ def test_openapi_schema(client: TestClient):
"type": "object", "type": "object",
"properties": { "properties": {
"name": {"title": "Name", "type": "string"}, "name": {"title": "Name", "type": "string"},
"description": IsDict( "description": {
{ "title": "Description",
"title": "Description", "anyOf": [{"type": "string"}, {"type": "null"}],
"anyOf": [{"type": "string"}, {"type": "null"}], },
}
)
| IsDict(
# TODO: remove when deprecating Pydantic v1
{"title": "Description", "type": "string"}
),
"price": {"title": "Price", "type": "number"}, "price": {"title": "Price", "type": "number"},
"tax": IsDict( "tax": {
{ "title": "Tax",
"title": "Tax", "anyOf": [{"type": "number"}, {"type": "null"}],
"anyOf": [{"type": "number"}, {"type": "null"}], },
}
)
| IsDict(
# TODO: remove when deprecating Pydantic v1
{"title": "Tax", "type": "number"}
),
}, },
}, },
"ValidationError": { "ValidationError": {

View File

@ -1,7 +1,6 @@
import importlib import importlib
import pytest import pytest
from dirty_equals import IsDict
from fastapi.testclient import TestClient from fastapi.testclient import TestClient
from ...utils import needs_py310 from ...utils import needs_py310
@ -58,16 +57,7 @@ def test_openapi_schema(client: TestClient) -> None:
"requestBody": { "requestBody": {
"content": { "content": {
"application/json": { "application/json": {
"schema": IsDict({"$ref": "#/components/schemas/Item"}) "schema": {"$ref": "#/components/schemas/Item"},
| IsDict(
# TODO: remove when deprecating Pydantic v1
{
"allOf": [
{"$ref": "#/components/schemas/Item"}
],
"title": "Item",
}
),
"examples": { "examples": {
"normal": { "normal": {
"summary": "A normal example", "summary": "A normal example",
@ -134,27 +124,15 @@ def test_openapi_schema(client: TestClient) -> None:
"type": "object", "type": "object",
"properties": { "properties": {
"name": {"title": "Name", "type": "string"}, "name": {"title": "Name", "type": "string"},
"description": IsDict( "description": {
{ "title": "Description",
"title": "Description", "anyOf": [{"type": "string"}, {"type": "null"}],
"anyOf": [{"type": "string"}, {"type": "null"}], },
}
)
| IsDict(
# TODO: remove when deprecating Pydantic v1
{"title": "Description", "type": "string"}
),
"price": {"title": "Price", "type": "number"}, "price": {"title": "Price", "type": "number"},
"tax": IsDict( "tax": {
{ "title": "Tax",
"title": "Tax", "anyOf": [{"type": "number"}, {"type": "null"}],
"anyOf": [{"type": "number"}, {"type": "null"}], },
}
)
| IsDict(
# TODO: remove when deprecating Pydantic v1
{"title": "Tax", "type": "number"}
),
}, },
}, },
"ValidationError": { "ValidationError": {

View File

@ -1,7 +1,6 @@
import importlib import importlib
import pytest import pytest
from dirty_equals import IsDict
from fastapi.testclient import TestClient from fastapi.testclient import TestClient
from ...utils import needs_py310 from ...utils import needs_py310
@ -144,23 +143,13 @@ def test_openapi_schema(client: TestClient):
"required": ["username", "password"], "required": ["username", "password"],
"type": "object", "type": "object",
"properties": { "properties": {
"grant_type": IsDict( "grant_type": {
{ "title": "Grant Type",
"title": "Grant Type", "anyOf": [
"anyOf": [ {"pattern": "^password$", "type": "string"},
{"pattern": "^password$", "type": "string"}, {"type": "null"},
{"type": "null"}, ],
], },
}
)
| IsDict(
# TODO: remove when deprecating Pydantic v1
{
"title": "Grant Type",
"pattern": "^password$",
"type": "string",
}
),
"username": {"title": "Username", "type": "string"}, "username": {"title": "Username", "type": "string"},
"password": { "password": {
"title": "Password", "title": "Password",
@ -168,31 +157,15 @@ def test_openapi_schema(client: TestClient):
"format": "password", "format": "password",
}, },
"scope": {"title": "Scope", "type": "string", "default": ""}, "scope": {"title": "Scope", "type": "string", "default": ""},
"client_id": IsDict( "client_id": {
{ "title": "Client Id",
"title": "Client Id", "anyOf": [{"type": "string"}, {"type": "null"}],
"anyOf": [{"type": "string"}, {"type": "null"}], },
} "client_secret": {
) "title": "Client Secret",
| IsDict( "anyOf": [{"type": "string"}, {"type": "null"}],
# TODO: remove when deprecating Pydantic v1 "format": "password",
{"title": "Client Id", "type": "string"} },
),
"client_secret": IsDict(
{
"title": "Client Secret",
"anyOf": [{"type": "string"}, {"type": "null"}],
"format": "password",
}
)
| IsDict(
# TODO: remove when deprecating Pydantic v1
{
"title": "Client Secret",
"type": "string",
"format": "password",
}
),
}, },
}, },
"ValidationError": { "ValidationError": {

View File

@ -2,8 +2,8 @@ import importlib
from types import ModuleType from types import ModuleType
import pytest import pytest
from dirty_equals import IsDict, IsOneOf
from fastapi.testclient import TestClient from fastapi.testclient import TestClient
from inline_snapshot import snapshot
from ...utils import needs_py310 from ...utils import needs_py310
@ -215,240 +215,200 @@ def test_openapi_schema(mod: ModuleType):
client = TestClient(mod.app) client = TestClient(mod.app)
response = client.get("/openapi.json") response = client.get("/openapi.json")
assert response.status_code == 200, response.text assert response.status_code == 200, response.text
assert response.json() == { assert response.json() == snapshot(
"openapi": "3.1.0", {
"info": {"title": "FastAPI", "version": "0.1.0"}, "openapi": "3.1.0",
"paths": { "info": {"title": "FastAPI", "version": "0.1.0"},
"/token": { "paths": {
"post": { "/token": {
"responses": { "post": {
"200": { "responses": {
"description": "Successful Response", "200": {
"content": { "description": "Successful Response",
"application/json": { "content": {
"schema": {"$ref": "#/components/schemas/Token"} "application/json": {
} "schema": {"$ref": "#/components/schemas/Token"}
}
},
},
"422": {
"description": "Validation Error",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/HTTPValidationError"
}
}
},
}, },
}, },
"422": { "summary": "Login For Access Token",
"description": "Validation Error", "operationId": "login_for_access_token_token_post",
"requestBody": {
"content": { "content": {
"application/json": { "application/x-www-form-urlencoded": {
"schema": { "schema": {
"$ref": "#/components/schemas/HTTPValidationError" "$ref": "#/components/schemas/Body_login_for_access_token_token_post"
} }
} }
}, },
"required": True,
}, },
}, }
"summary": "Login For Access Token", },
"operationId": "login_for_access_token_token_post", "/users/me/": {
"requestBody": { "get": {
"content": { "responses": {
"application/x-www-form-urlencoded": { "200": {
"schema": { "description": "Successful Response",
"$ref": "#/components/schemas/Body_login_for_access_token_token_post" "content": {
} "application/json": {
"schema": {"$ref": "#/components/schemas/User"}
}
},
} }
}, },
"required": True, "summary": "Read Users Me",
}, "operationId": "read_users_me_users_me__get",
} "security": [{"OAuth2PasswordBearer": ["me"]}],
}
},
"/users/me/items/": {
"get": {
"responses": {
"200": {
"description": "Successful Response",
"content": {"application/json": {"schema": {}}},
}
},
"summary": "Read Own Items",
"operationId": "read_own_items_users_me_items__get",
"security": [{"OAuth2PasswordBearer": ["items", "me"]}],
}
},
"/status/": {
"get": {
"responses": {
"200": {
"description": "Successful Response",
"content": {"application/json": {"schema": {}}},
}
},
"summary": "Read System Status",
"operationId": "read_system_status_status__get",
"security": [{"OAuth2PasswordBearer": []}],
}
},
}, },
"/users/me/": { "components": {
"get": { "schemas": {
"responses": { "User": {
"200": { "title": "User",
"description": "Successful Response", "required": ["username"],
"content": { "type": "object",
"application/json": { "properties": {
"schema": {"$ref": "#/components/schemas/User"} "username": {"title": "Username", "type": "string"},
} "email": {
},
}
},
"summary": "Read Users Me",
"operationId": "read_users_me_users_me__get",
"security": [{"OAuth2PasswordBearer": ["me"]}],
}
},
"/users/me/items/": {
"get": {
"responses": {
"200": {
"description": "Successful Response",
"content": {"application/json": {"schema": {}}},
}
},
"summary": "Read Own Items",
"operationId": "read_own_items_users_me_items__get",
"security": [{"OAuth2PasswordBearer": ["items", "me"]}],
}
},
"/status/": {
"get": {
"responses": {
"200": {
"description": "Successful Response",
"content": {"application/json": {"schema": {}}},
}
},
"summary": "Read System Status",
"operationId": "read_system_status_status__get",
"security": [{"OAuth2PasswordBearer": []}],
}
},
},
"components": {
"schemas": {
"User": {
"title": "User",
"required": IsOneOf(
["username", "email", "full_name", "disabled"],
# TODO: remove when deprecating Pydantic v1
["username"],
),
"type": "object",
"properties": {
"username": {"title": "Username", "type": "string"},
"email": IsDict(
{
"title": "Email", "title": "Email",
"anyOf": [{"type": "string"}, {"type": "null"}], "anyOf": [{"type": "string"}, {"type": "null"}],
} },
) "full_name": {
| IsDict(
# TODO: remove when deprecating Pydantic v1
{"title": "Email", "type": "string"}
),
"full_name": IsDict(
{
"title": "Full Name", "title": "Full Name",
"anyOf": [{"type": "string"}, {"type": "null"}], "anyOf": [{"type": "string"}, {"type": "null"}],
} },
) "disabled": {
| IsDict(
# TODO: remove when deprecating Pydantic v1
{"title": "Full Name", "type": "string"}
),
"disabled": IsDict(
{
"title": "Disabled", "title": "Disabled",
"anyOf": [{"type": "boolean"}, {"type": "null"}], "anyOf": [{"type": "boolean"}, {"type": "null"}],
} },
) },
| IsDict(
# TODO: remove when deprecating Pydantic v1
{"title": "Disabled", "type": "boolean"}
),
}, },
}, "Token": {
"Token": { "title": "Token",
"title": "Token", "required": ["access_token", "token_type"],
"required": ["access_token", "token_type"], "type": "object",
"type": "object", "properties": {
"properties": { "access_token": {"title": "Access Token", "type": "string"},
"access_token": {"title": "Access Token", "type": "string"}, "token_type": {"title": "Token Type", "type": "string"},
"token_type": {"title": "Token Type", "type": "string"}, },
}, },
}, "Body_login_for_access_token_token_post": {
"Body_login_for_access_token_token_post": { "title": "Body_login_for_access_token_token_post",
"title": "Body_login_for_access_token_token_post", "required": ["username", "password"],
"required": ["username", "password"], "type": "object",
"type": "object", "properties": {
"properties": { "grant_type": {
"grant_type": IsDict(
{
"title": "Grant Type", "title": "Grant Type",
"anyOf": [ "anyOf": [
{"pattern": "^password$", "type": "string"}, {"pattern": "^password$", "type": "string"},
{"type": "null"}, {"type": "null"},
], ],
} },
) "username": {"title": "Username", "type": "string"},
| IsDict( "password": {
# TODO: remove when deprecating Pydantic v1 "title": "Password",
{
"title": "Grant Type",
"pattern": "^password$",
"type": "string", "type": "string",
} "format": "password",
), },
"username": {"title": "Username", "type": "string"}, "scope": {
"password": { "title": "Scope",
"title": "Password", "type": "string",
"type": "string", "default": "",
"format": "password", },
}, "client_id": {
"scope": {"title": "Scope", "type": "string", "default": ""},
"client_id": IsDict(
{
"title": "Client Id", "title": "Client Id",
"anyOf": [{"type": "string"}, {"type": "null"}], "anyOf": [{"type": "string"}, {"type": "null"}],
} },
) "client_secret": {
| IsDict(
# TODO: remove when deprecating Pydantic v1
{"title": "Client Id", "type": "string"}
),
"client_secret": IsDict(
{
"title": "Client Secret", "title": "Client Secret",
"anyOf": [{"type": "string"}, {"type": "null"}], "anyOf": [{"type": "string"}, {"type": "null"}],
"format": "password", "format": "password",
}
)
| IsDict(
# TODO: remove when deprecating Pydantic v1
{
"title": "Client Secret",
"type": "string",
"format": "password",
}
),
},
},
"ValidationError": {
"title": "ValidationError",
"required": ["loc", "msg", "type"],
"type": "object",
"properties": {
"loc": {
"title": "Location",
"type": "array",
"items": {
"anyOf": [{"type": "string"}, {"type": "integer"}]
}, },
}, },
"msg": {"title": "Message", "type": "string"},
"type": {"title": "Error Type", "type": "string"},
}, },
}, "ValidationError": {
"HTTPValidationError": { "title": "ValidationError",
"title": "HTTPValidationError", "required": ["loc", "msg", "type"],
"type": "object", "type": "object",
"properties": { "properties": {
"detail": { "loc": {
"title": "Detail", "title": "Location",
"type": "array", "type": "array",
"items": {"$ref": "#/components/schemas/ValidationError"}, "items": {
} "anyOf": [{"type": "string"}, {"type": "integer"}]
}, },
},
},
"securitySchemes": {
"OAuth2PasswordBearer": {
"type": "oauth2",
"flows": {
"password": {
"scopes": {
"me": "Read information about the current user.",
"items": "Read items.",
}, },
"tokenUrl": "token", "msg": {"title": "Message", "type": "string"},
} "type": {"title": "Error Type", "type": "string"},
},
}, },
} "HTTPValidationError": {
"title": "HTTPValidationError",
"type": "object",
"properties": {
"detail": {
"title": "Detail",
"type": "array",
"items": {
"$ref": "#/components/schemas/ValidationError"
},
}
},
},
},
"securitySchemes": {
"OAuth2PasswordBearer": {
"type": "oauth2",
"flows": {
"password": {
"scopes": {
"me": "Read information about the current user.",
"items": "Read items.",
},
"tokenUrl": "token",
}
},
}
},
}, },
}, }
} )

View File

@ -2,7 +2,7 @@ import importlib
import warnings import warnings
import pytest import pytest
from dirty_equals import IsDict, IsInt from dirty_equals import IsInt
from fastapi.testclient import TestClient from fastapi.testclient import TestClient
from inline_snapshot import snapshot from inline_snapshot import snapshot
from sqlalchemy import StaticPool from sqlalchemy import StaticPool
@ -318,33 +318,15 @@ def test_openapi_schema(client: TestClient):
}, },
"Hero": { "Hero": {
"properties": { "properties": {
"id": IsDict( "id": {
{ "anyOf": [{"type": "integer"}, {"type": "null"}],
"anyOf": [{"type": "integer"}, {"type": "null"}], "title": "Id",
"title": "Id", },
}
)
| IsDict(
# TODO: remove when deprecating Pydantic v1
{
"type": "integer",
"title": "Id",
}
),
"name": {"type": "string", "title": "Name"}, "name": {"type": "string", "title": "Name"},
"age": IsDict( "age": {
{ "anyOf": [{"type": "integer"}, {"type": "null"}],
"anyOf": [{"type": "integer"}, {"type": "null"}], "title": "Age",
"title": "Age", },
}
)
| IsDict(
# TODO: remove when deprecating Pydantic v1
{
"type": "integer",
"title": "Age",
}
),
"secret_name": {"type": "string", "title": "Secret Name"}, "secret_name": {"type": "string", "title": "Secret Name"},
}, },
"type": "object", "type": "object",

Some files were not shown because too many files have changed in this diff Show More