Remove xfail for defaul_factory in openapi

This commit is contained in:
Yurii Motov 2026-02-05 15:15:00 +01:00
parent 27cc340880
commit d90bcc8569
5 changed files with 71 additions and 64 deletions

View File

@ -2,7 +2,7 @@ from typing import Annotated, Any, Union
from unittest.mock import Mock, patch from unittest.mock import Mock, patch
import pytest import pytest
from dirty_equals import IsList, IsOneOf from dirty_equals import IsList, IsOneOf, IsPartialDict
from fastapi import Body, FastAPI from fastapi import Body, FastAPI
from fastapi.testclient import TestClient from fastapi.testclient import TestClient
from pydantic import BaseModel, BeforeValidator, field_validator from pydantic import BaseModel, BeforeValidator, field_validator
@ -811,20 +811,16 @@ async def read_nullable_with_non_null_default_no_embed_list(
@pytest.mark.parametrize( @pytest.mark.parametrize(
"path", "path",
[ [
pytest.param( "/nullable-with-non-null-default",
"/nullable-with-non-null-default",
marks=pytest.mark.xfail(
reason="`default_factory` is not reflected in OpenAPI schema"
),
),
"/model-nullable-with-non-null-default", "/model-nullable-with-non-null-default",
], ],
) )
def test_nullable_with_non_null_default_schema(path: str): def test_nullable_with_non_null_default_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)
body_model = app.openapi()["components"]["schemas"][body_model_name]
assert app.openapi()["components"]["schemas"][body_model_name] == { assert body_model == {
"properties": { "properties": {
"int_val": { "int_val": {
"title": "Int Val", "title": "Int Val",
@ -836,19 +832,25 @@ def test_nullable_with_non_null_default_schema(path: str):
"anyOf": [{"type": "string"}, {"type": "null"}], "anyOf": [{"type": "string"}, {"type": "null"}],
"default": "default", "default": "default",
}, },
"list_val": { "list_val": IsPartialDict(
"title": "List Val", {
"anyOf": [ "title": "List Val",
{"type": "array", "items": {"type": "integer"}}, "anyOf": [
{"type": "null"}, {"type": "array", "items": {"type": "integer"}},
], {"type": "null"},
"default": [0], # default_factory is not reflected in OpenAPI schema ],
}, },
),
}, },
"title": body_model_name, "title": body_model_name,
"type": "object", "type": "object",
} }
if path == "/model-nullable-with-non-null-default":
# Check default value for list_val param for model-based Body parameters only.
# default_factory is not reflected in OpenAPI schema
assert body_model["properties"]["list_val"]["default"] == [0]
@pytest.mark.parametrize( @pytest.mark.parametrize(
("path", "schema"), ("path", "schema"),
@ -869,7 +871,7 @@ def test_nullable_with_non_null_default_schema(path: str):
"default": -1, "default": -1,
}, },
), ),
pytest.param( (
"/nullable-with-non-null-default-list", "/nullable-with-non-null-default-list",
{ {
"anyOf": [ "anyOf": [
@ -877,11 +879,7 @@ def test_nullable_with_non_null_default_schema(path: str):
{"type": "null"}, {"type": "null"},
], ],
"title": "List Val", "title": "List Val",
"default": [0], # default_factory is not reflected in OpenAPI schema
}, },
marks=pytest.mark.xfail(
reason="`default_factory` is not reflected in OpenAPI schema"
),
), ),
], ],
) )

View File

@ -393,7 +393,6 @@ def test_nullable_with_non_null_default_schema(path: str):
{"type": "array", "items": {"type": "string", "format": "binary"}}, {"type": "array", "items": {"type": "string", "format": "binary"}},
{"type": "null"}, {"type": "null"},
], ],
# "default": None, # default_factory is not reflected in OpenAPI schema
}, },
}, },
"title": body_model_name, "title": body_model_name,

View File

@ -2,7 +2,7 @@ from typing import Annotated, Any, Union
from unittest.mock import Mock, patch from unittest.mock import Mock, patch
import pytest import pytest
from dirty_equals import IsList, IsOneOf from dirty_equals import IsList, IsOneOf, IsPartialDict
from fastapi import FastAPI, Form from fastapi import FastAPI, Form
from fastapi.testclient import TestClient from fastapi.testclient import TestClient
from pydantic import BaseModel, BeforeValidator, field_validator from pydantic import BaseModel, BeforeValidator, field_validator
@ -462,20 +462,16 @@ async def read_model_nullable_with_non_null_default(
@pytest.mark.parametrize( @pytest.mark.parametrize(
"path", "path",
[ [
pytest.param( "/nullable-with-non-null-default",
"/nullable-with-non-null-default",
marks=pytest.mark.xfail(
reason="`default_factory` is not reflected in OpenAPI schema"
),
),
"/model-nullable-with-non-null-default", "/model-nullable-with-non-null-default",
], ],
) )
def test_nullable_with_non_null_default_schema(path: str): def test_nullable_with_non_null_default_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)
body_model = app.openapi()["components"]["schemas"][body_model_name]
assert app.openapi()["components"]["schemas"][body_model_name] == { assert body_model == {
"properties": { "properties": {
"int_val": { "int_val": {
"title": "Int Val", "title": "Int Val",
@ -487,19 +483,25 @@ def test_nullable_with_non_null_default_schema(path: str):
"anyOf": [{"type": "string"}, {"type": "null"}], "anyOf": [{"type": "string"}, {"type": "null"}],
"default": "default", "default": "default",
}, },
"list_val": { "list_val": IsPartialDict(
"title": "List Val", {
"anyOf": [ "title": "List Val",
{"type": "array", "items": {"type": "integer"}}, "anyOf": [
{"type": "null"}, {"type": "array", "items": {"type": "integer"}},
], {"type": "null"},
"default": [0], # default_factory is not reflected in OpenAPI schema ],
}, }
),
}, },
"title": body_model_name, "title": body_model_name,
"type": "object", "type": "object",
} }
if path == "/model-nullable-with-non-null-default":
# Check default value for list_val param for model-based Body parameters only.
# default_factory is not reflected in OpenAPI schema
assert body_model["properties"]["list_val"]["default"] == [0]
@pytest.mark.parametrize( @pytest.mark.parametrize(
"path", "path",

View File

@ -2,7 +2,7 @@ from typing import Annotated, Any, Union
from unittest.mock import Mock, patch from unittest.mock import Mock, patch
import pytest import pytest
from dirty_equals import AnyThing, IsList, IsOneOf from dirty_equals import AnyThing, IsList, 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, BeforeValidator, field_validator from pydantic import BaseModel, BeforeValidator, field_validator
@ -420,7 +420,8 @@ async def read_model_nullable_with_non_null_default(
], ],
) )
def test_nullable_with_non_null_default_schema(path: str): def test_nullable_with_non_null_default_schema(path: str):
assert app.openapi()["paths"][path]["get"]["parameters"] == [ parameters = app.openapi()["paths"][path]["get"]["parameters"]
assert parameters == [
{ {
"required": False, "required": False,
"schema": { "schema": {
@ -443,19 +444,25 @@ def test_nullable_with_non_null_default_schema(path: str):
}, },
{ {
"required": False, "required": False,
"schema": { "schema": IsPartialDict(
"title": "List Val", {
"anyOf": [ "title": "List Val",
{"type": "array", "items": {"type": "integer"}}, "anyOf": [
{"type": "null"}, {"type": "array", "items": {"type": "integer"}},
], {"type": "null"},
"default": [0], ],
}, }
),
"name": "list-val", "name": "list-val",
"in": "header", "in": "header",
}, },
] ]
if path == "/model-nullable-with-non-null-default":
# Check default value for list_val param for model-based Body parameters only.
# default_factory is not reflected in OpenAPI schema
assert parameters[2]["schema"]["default"] == [0]
@pytest.mark.parametrize( @pytest.mark.parametrize(
"path", "path",

View File

@ -2,7 +2,7 @@ from typing import Annotated, Any, Union
from unittest.mock import Mock, patch from unittest.mock import Mock, patch
import pytest import pytest
from dirty_equals import IsList, IsOneOf from dirty_equals import IsList, IsOneOf, IsPartialDict
from fastapi import FastAPI, Query from fastapi import FastAPI, Query
from fastapi.testclient import TestClient from fastapi.testclient import TestClient
from pydantic import BaseModel, BeforeValidator, field_validator from pydantic import BaseModel, BeforeValidator, field_validator
@ -378,17 +378,13 @@ async def read_model_nullable_with_non_null_default(
@pytest.mark.parametrize( @pytest.mark.parametrize(
"path", "path",
[ [
pytest.param( "/nullable-with-non-null-default",
"/nullable-with-non-null-default",
marks=pytest.mark.xfail(
reason="`default_factory` is not reflected in OpenAPI schema"
),
),
"/model-nullable-with-non-null-default", "/model-nullable-with-non-null-default",
], ],
) )
def test_nullable_with_non_null_default_schema(path: str): def test_nullable_with_non_null_default_schema(path: str):
assert app.openapi()["paths"][path]["get"]["parameters"] == [ parameters = app.openapi()["paths"][path]["get"]["parameters"]
assert parameters == [
{ {
"required": False, "required": False,
"schema": { "schema": {
@ -413,17 +409,22 @@ def test_nullable_with_non_null_default_schema(path: str):
"in": "query", "in": "query",
"name": "list_val", "name": "list_val",
"required": False, "required": False,
"schema": { "schema": IsPartialDict(
"anyOf": [ {
{"items": {"type": "integer"}, "type": "array"}, "anyOf": [
{"type": "null"}, {"items": {"type": "integer"}, "type": "array"},
], {"type": "null"},
"title": "List Val", ],
"default": [0], # `default_factory` is not reflected in OpenAPI schema "title": "List Val",
}, }
),
}, },
] ]
if path == "/model-nullable-with-non-null-default":
# Check default value for list_val param for model-based Body parameters only.
# default_factory is not reflected in OpenAPI schema
assert parameters[2]["schema"]["default"] == [0]
@pytest.mark.parametrize( @pytest.mark.parametrize(
"path", "path",