diff --git a/HISTORY.rst b/HISTORY.rst index dfd938b..03c5954 100644 --- a/HISTORY.rst +++ b/HISTORY.rst @@ -7,6 +7,7 @@ v0.21.1 (unreleased) .................... * add ``IPv{4,6,Any}Network`` and ``IPv{4,6,Any}Interface`` types from ``ipaddress`` stdlib, #333 by @pilosus * add docs for ``datetime`` types, #386 by @pilosus +* fix to schema generation in dataclass-based models, #408 by @pilosus v0.21.0 (2019-03-15) diff --git a/pydantic/dataclasses.py b/pydantic/dataclasses.py index 8b2b09a..4b6af0f 100644 --- a/pydantic/dataclasses.py +++ b/pydantic/dataclasses.py @@ -3,6 +3,7 @@ from typing import TYPE_CHECKING, Any, Callable, Dict, Generator, Optional, Type from .error_wrappers import ValidationError from .errors import DataclassTypeError +from .fields import Required from .main import create_model, validate_model from .utils import AnyType @@ -72,7 +73,10 @@ def _process_class( _cls.__post_init__ = _pydantic_post_init cls = dataclasses._process_class(_cls, init, repr, eq, order, unsafe_hash, frozen) # type: ignore - fields: Dict[str, Any] = {name: (field.type, field.default) for name, field in cls.__dataclass_fields__.items()} + fields: Dict[str, Any] = { + name: (field.type, field.default if field.default != dataclasses.MISSING else Required) + for name, field in cls.__dataclass_fields__.items() + } cls.__post_init_original__ = post_init_original cls.__pydantic_model__ = create_model(cls.__name__, __config__=config, __module__=_cls.__module__, **fields) diff --git a/tests/test_dataclasses.py b/tests/test_dataclasses.py index 8487e2c..0d0dd55 100644 --- a/tests/test_dataclasses.py +++ b/tests/test_dataclasses.py @@ -1,4 +1,5 @@ import dataclasses +from datetime import datetime import pytest @@ -260,3 +261,43 @@ def test_nested_dataclass_model(): navbar = Outer(n=Nested(number='1')) assert navbar.n.number == 1 + + +def test_fields(): + @pydantic.dataclasses.dataclass + class User: + id: int + name: str = 'John Doe' + signup_ts: datetime = None + + user = User(id=123) + fields = user.__pydantic_model__.__fields__ + + assert fields['id'].required is True + assert fields['id'].default is None + + assert fields['name'].required is False + assert fields['name'].default == 'John Doe' + + assert fields['signup_ts'].required is False + assert fields['signup_ts'].default is None + + +def test_schema(): + @pydantic.dataclasses.dataclass + class User: + id: int + name: str = 'John Doe' + signup_ts: datetime = None + + user = User(id=123) + assert user.__pydantic_model__.schema() == { + 'title': 'User', + 'type': 'object', + 'properties': { + 'id': {'title': 'Id', 'type': 'integer'}, + 'name': {'title': 'Name', 'default': 'John Doe', 'type': 'string'}, + 'signup_ts': {'title': 'Signup_Ts', 'type': 'string', 'format': 'date-time'}, + }, + 'required': ['id'], + }