From 0a1b71920183021a8a865af4472d3e9e7838e8c2 Mon Sep 17 00:00:00 2001 From: PrettyWood Date: Thu, 21 Jan 2021 22:32:03 +0100 Subject: [PATCH] feat: support schema for NamedTuple --- pydantic/annotated_types.py | 2 +- pydantic/validators.py | 1 + tests/test_annotated_types.py | 29 +++++++++++++++++++++++++++++ 3 files changed, 31 insertions(+), 1 deletion(-) diff --git a/pydantic/annotated_types.py b/pydantic/annotated_types.py index 436f1db0a7c..9049ca0dd62 100644 --- a/pydantic/annotated_types.py +++ b/pydantic/annotated_types.py @@ -56,4 +56,4 @@ def create_model_from_namedtuple(namedtuple_cls: Type['NamedTuple'], **kwargs: A field_definitions: Dict[str, Any] = { field_name: (field_type, Required) for field_name, field_type in namedtuple_annotations.items() } - return create_model(f'{namedtuple_cls.__name__}Model', **kwargs, **field_definitions) + return create_model(namedtuple_cls.__name__, **kwargs, **field_definitions) diff --git a/pydantic/validators.py b/pydantic/validators.py index 43ba2a37e39..6e734441333 100644 --- a/pydantic/validators.py +++ b/pydantic/validators.py @@ -547,6 +547,7 @@ def make_namedtuple_validator(namedtuple_cls: Type[NamedTupleT]) -> Callable[[Tu from .annotated_types import create_model_from_namedtuple NamedTupleModel = create_model_from_namedtuple(namedtuple_cls) + namedtuple_cls.__pydantic_model__ = NamedTupleModel # type: ignore[attr-defined] def namedtuple_validator(values: Tuple[Any, ...]) -> NamedTupleT: dict_values: Dict[str, Any] = dict(zip(NamedTupleModel.__annotations__, values)) diff --git a/tests/test_annotated_types.py b/tests/test_annotated_types.py index 6e763af083e..2507f2696d7 100644 --- a/tests/test_annotated_types.py +++ b/tests/test_annotated_types.py @@ -58,6 +58,35 @@ class Model(BaseModel): } ] + assert Model.schema() == { + 'title': 'Model', + 'type': 'object', + 'properties': { + 'pos': {'$ref': '#/definitions/Pos'}, + 'events': {'type': 'array', 'title': 'Events', 'items': {'$ref': '#/definitions/Event'}}, + }, + 'required': ['pos', 'events'], + 'definitions': { + 'Pos': { + 'type': 'object', + 'title': 'Pos', + 'properties': {'x': {'title': 'X'}, 'y': {'title': 'Y'}}, + 'required': ['x', 'y'], + }, + 'Event': { + 'type': 'object', + 'title': 'Event', + 'properties': { + 'a': {'title': 'A', 'type': 'integer'}, + 'b': {'title': 'B', 'type': 'integer'}, + 'c': {'title': 'C', 'type': 'integer'}, + 'd': {'title': 'D', 'type': 'string'}, + }, + 'required': ['a', 'b', 'c', 'd'], + }, + }, + } + @pytest.mark.skipif(not TypedDict, reason='typing_extensions not installed') def test_typeddict():