Browse Source

♻️ Refactor types for lenient_issubclass

pull/14860/head
Sebastián Ramírez 5 months ago
parent
commit
ee707dd54b
  1. 13
      fastapi/_compat/shared.py
  2. 12
      fastapi/_compat/v2.py

13
fastapi/_compat/shared.py

@ -8,6 +8,7 @@ from dataclasses import is_dataclass
from typing import (
Annotated,
Any,
TypeVar,
Union,
)
@ -15,7 +16,9 @@ from fastapi.types import UnionType
from pydantic import BaseModel
from pydantic.version import VERSION as PYDANTIC_VERSION
from starlette.datastructures import UploadFile
from typing_extensions import get_args, get_origin
from typing_extensions import TypeGuard, get_args, get_origin
_T = TypeVar("_T")
# Copy from Pydantic: pydantic/_internal/_typing_extra.py
if sys.version_info < (3, 10):
@ -39,13 +42,13 @@ sequence_annotation_to_type = {
deque: deque,
}
sequence_types = tuple(sequence_annotation_to_type.keys())
sequence_types: tuple[type[Any], ...] = tuple(sequence_annotation_to_type.keys())
# Copy of Pydantic: pydantic/_internal/_utils.py
# Copy of Pydantic: pydantic/_internal/_utils.py with added TypeGuard
def lenient_issubclass(
cls: Any, class_or_tuple: Union[type[Any], tuple[type[Any], ...], None]
) -> bool:
cls: Any, class_or_tuple: Union[type[_T], tuple[type[_T], ...], None]
) -> TypeGuard[type[_T]]:
try:
return isinstance(cls, type) and issubclass(cls, class_or_tuple) # type: ignore[arg-type]
except TypeError: # pragma: no cover

12
fastapi/_compat/v2.py

@ -12,7 +12,7 @@ from typing import (
cast,
)
from fastapi._compat import shared
from fastapi._compat import lenient_issubclass, shared
from fastapi.openapi.constants import REF_TEMPLATE
from fastapi.types import IncEx, ModelNameMap, UnionType
from pydantic import BaseModel, ConfigDict, Field, TypeAdapter, create_model
@ -23,7 +23,6 @@ from pydantic._internal._schema_generation_shared import ( # type: ignore[attr-
GetJsonSchemaHandler as GetJsonSchemaHandler,
)
from pydantic._internal._typing_extra import eval_type_lenient
from pydantic._internal._utils import lenient_issubclass as lenient_issubclass
from pydantic.fields import FieldInfo as FieldInfo
from pydantic.json_schema import GenerateJsonSchema as GenerateJsonSchema
from pydantic.json_schema import JsonSchemaValue as JsonSchemaValue
@ -416,10 +415,11 @@ def get_flat_models_from_annotation(
origin = get_origin(annotation)
if origin is not None:
for arg in get_args(annotation):
if lenient_issubclass(arg, (BaseModel, Enum)) and arg not in known_models:
known_models.add(arg)
if lenient_issubclass(arg, BaseModel):
get_flat_models_from_model(arg, known_models=known_models)
if lenient_issubclass(arg, (BaseModel, Enum)):
if arg not in known_models:
known_models.add(arg) # type: ignore[arg-type]
if lenient_issubclass(arg, BaseModel):
get_flat_models_from_model(arg, known_models=known_models)
else:
get_flat_models_from_annotation(arg, known_models=known_models)
return known_models

Loading…
Cancel
Save