Add support for InitVar (#591)

* Add support for InitVar

* Annotate *initvars as Any

* Simplify tests

* Add line to HISTORY.rst

* Use dataclasses.fields which also ignores ClassVars

* tweak history
This commit is contained in:
pfrederiks
2019-06-14 17:56:08 +02:00
committed by Samuel Colvin
parent f5b054b9fc
commit b77da1ec9e
3 changed files with 50 additions and 4 deletions
+4
View File
@@ -3,6 +3,10 @@
History
-------
v0.29 (unreleased)
..................
* support dataclasses.InitVar, #592 by @pfrederiks
v0.28 (2019-06-06)
..................
* fix support for JSON Schema generation when using models with circular references in Python 3.7, #572 by @tiangolo
+4 -4
View File
@@ -25,9 +25,9 @@ if TYPE_CHECKING: # pragma: no cover
pass
def _pydantic_post_init(self: 'DataclassType') -> None:
def _pydantic_post_init(self: 'DataclassType', *initvars: Any) -> None:
if self.__post_init_original__:
self.__post_init_original__()
self.__post_init_original__(*initvars)
d = validate_model(self.__pydantic_model__, self.__dict__, cls=self.__class__)[0]
object.__setattr__(self, '__dict__', d)
object.__setattr__(self, '__initialised__', True)
@@ -79,8 +79,8 @@ def _process_class(
cls = dataclasses._process_class(_cls, init, repr, eq, order, unsafe_hash, frozen) # type: ignore
fields: Dict[str, Any] = {
name: (field.type, field.default if field.default != dataclasses.MISSING else Required)
for name, field in cls.__dataclass_fields__.items()
field.name: (field.type, field.default if field.default != dataclasses.MISSING else Required)
for field in dataclasses.fields(cls)
}
cls.__post_init_original__ = post_init_original
cls.__post_init_post_parse__ = post_init_post_parse
+42
View File
@@ -1,5 +1,6 @@
import dataclasses
from datetime import datetime
from typing import ClassVar
import pytest
@@ -380,3 +381,44 @@ def test_nested_schema():
}
},
}
def test_initvar():
InitVar = dataclasses.InitVar
@pydantic.dataclasses.dataclass
class TestInitVar:
x: int
y: InitVar
tiv = TestInitVar(1, 2)
assert tiv.x == 1
with pytest.raises(AttributeError):
tiv.y
def test_derived_field_from_initvar():
InitVar = dataclasses.InitVar
@pydantic.dataclasses.dataclass
class DerivedWithInitVar:
plusone: int = dataclasses.field(init=False)
number: InitVar[int]
def __post_init__(self, number):
self.plusone = number + 1
derived = DerivedWithInitVar(1)
assert derived.plusone == 2
with pytest.raises(TypeError):
DerivedWithInitVar("Not A Number")
def test_classvar():
@pydantic.dataclasses.dataclass
class TestClassVar:
klassvar: ClassVar = "I'm a Class variable"
x: int
tcv = TestClassVar(2)
assert tcv.klassvar == "I'm a Class variable"