Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
17 changes: 11 additions & 6 deletions src/aiopenapi3/model.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,11 +7,11 @@
from typing import Annotated, Any, ClassVar, Literal, Optional, TypeGuard, TypeVar, Union, cast

import pydantic
from pydantic import BaseModel, ConfigDict, Field, RootModel
from pydantic import BaseModel, ConfigDict, Field, RootModel, create_model

from . import me
from .base import ReferenceBase, SchemaBase
from .pydanticv2 import create_model, field_class_to_schema
from .pydanticv2 import field_class_to_schema

if typing.TYPE_CHECKING:
from ._types import DiscriminatorType, ReferenceType, SchemaType
Expand Down Expand Up @@ -106,11 +106,16 @@ def validate(self):
assert len(report) == 0, report

@property
def fields(self):
r = []
def fields(self) -> dict[str, Any]:
f = [("__validators__", c := {})]
for k, v in self.properties.items():
r.append((k, (v.annotation, v.default)))
return dict(r)
if v.annotation:
f.append((k, (v.annotation, v.default)))
else:
# property, computed field, no annotation
# https://github.com/pydantic/pydantic/issues/11709
c[k] = v.default
return dict(f)

def createFields(self, schema: "SchemaType", overwrite=False):
if schema.type == "array":
Expand Down
78 changes: 0 additions & 78 deletions src/aiopenapi3/pydanticv2.py
Original file line number Diff line number Diff line change
Expand Up @@ -38,81 +38,3 @@
field_class_to_schema: tuple[tuple[Any, dict[str, Any]], ...] = tuple(
(field_class, TypeAdapter(field_class).json_schema()) for field_class in field_classes_to_support
)

import sys
import types
from collections.abc import Callable
from typing import cast

from pydantic import BaseModel, ConfigDict, PydanticUserError
from pydantic.main import ModelT


def create_model(
model_name: str,
/,
*,
__config__: ConfigDict | None = None,
__doc__: str | None = None,
__base__: type[ModelT] | tuple[type[ModelT], ...] | None = None,
__module__: str | None = None,
__validators__: dict[str, Callable[..., Any]] | None = None,
__cls_kwargs__: dict[str, Any] | None = None,
# TODO PEP 747: replace `Any` by the TypeForm:
**field_definitions: Any | tuple[str, Any],
) -> type[ModelT]:
"""
unfortunate this is required, but …
c.f. https://github.com/pydantic/pydantic/pull/11032#issuecomment-2797667916
"""
if __base__ is None:
__base__ = (cast("type[ModelT]", BaseModel),)
elif not isinstance(__base__, tuple):
__base__ = (__base__,)

__cls_kwargs__ = __cls_kwargs__ or {}

fields: dict[str, Any] = {}
annotations: dict[str, Any] = {}

for f_name, f_def in field_definitions.items():
if isinstance(f_def, tuple):
if len(f_def) != 2:
raise PydanticUserError(
f"Field definition for {f_name!r} should a single element representing the type or a two-tuple, the first element "
"being the type and the second element the assigned value (either a default or the `Field()` function).",
code="create-model-field-definitions",
)

if f_def[0]:
annotations[f_name] = f_def[0]
fields[f_name] = f_def[1]
else:
annotations[f_name] = f_def

if __module__ is None:
f = sys._getframe(1)
__module__ = f.f_globals["__name__"]

namespace: dict[str, Any] = {"__annotations__": annotations, "__module__": __module__}
if __doc__:
namespace.update({"__doc__": __doc__})
if __validators__:
namespace.update(__validators__)
namespace.update(fields)
if __config__:
namespace["model_config"] = __config__
resolved_bases = types.resolve_bases(__base__)
meta, ns, kwds = types.prepare_class(model_name, resolved_bases, kwds=__cls_kwargs__)
if resolved_bases is not __base__:
ns["__orig_bases__"] = __base__
namespace.update(ns)

return meta(
model_name,
resolved_bases,
namespace,
__pydantic_reset_parent_namespace__=False,
_create_model_module=__module__,
**kwds,
)
Loading