def test_dict_to_dataclass_deserialization_func(self): @dataclass class ExampleDataclass: int_field: int with self.subTest("Invalid deserialization"), self.assertRaises( DeserializationError): dict_to_dataclass(ExampleDataclass, {'int_field': "1"}) with self.subTest("Using deserialization func"): self.assertEqual( ExampleDataclass(1), dict_to_dataclass( ExampleDataclass, {'int_field': "1"}, deserialization_func=lambda cls, obj: int(obj)))
def test_dict_to_dataclass_basic(self): @dataclass class ExampleDataclass: int_field: int str_field: str self.assertEqual( ExampleDataclass(1, "Hello, world"), dict_to_dataclass(ExampleDataclass, { 'int_field': 1, 'str_field': "Hello, world" }))
def test_dict_to_dataclass_inheritance(self): @dataclass class ExampleDataclass: int_field: int @dataclass class ChildDataclass(ExampleDataclass): str_field: str self.assertEqual( ChildDataclass(1, "Hello, world"), dict_to_dataclass(ChildDataclass, { "int_field": 1, "str_field": "Hello, world" }), )
def test_dict_to_dataclass_basic(self): @dataclass class ExampleDataclass: int_field: int str_field: str optional_field: str = "" with self.subTest("Deserialize basic dict"): self.assertEqual( ExampleDataclass(1, "Hello, world", "Lorem ipsum"), dict_to_dataclass( ExampleDataclass, { "int_field": 1, "str_field": "Hello, world", "optional_field": "Lorem ipsum", }, ), ) with self.subTest("Fill in optional field"): self.assertEqual( ExampleDataclass(1, "Hello, world"), dict_to_dataclass(ExampleDataclass, { "int_field": 1, "str_field": "Hello, world" }), ) with self.subTest("Fail missing field deserialization" ), self.assertRaises(DeserializationError): dict_to_dataclass(ExampleDataclass, {"int_field": 1}) with self.subTest("Fail non-dict deserialization"), self.assertRaises( DeserializationError): dict_to_dataclass(ExampleDataclass, 1)
def test_dict_to_dataclass_generics(self): T = TypeVar('T') @dataclass class ExampleRedundantGenericDataclass(Generic[T]): s: str @dataclass class ExampleGenericTypeVarDataclass(Generic[T]): t: T @dataclass class ExampleGenericCompoundDataclass(Generic[T]): t_dict: Dict[str, T] with self.subTest("Fail generic deserialization"): with self.assertRaises(DeserializationError): dict_to_dataclass(ExampleRedundantGenericDataclass, {'s': "a"}) with self.assertRaises(DeserializationError): dict_to_dataclass(ExampleGenericTypeVarDataclass, {'t': "a"}) with self.assertRaises(DeserializationError): dict_to_dataclass(ExampleGenericCompoundDataclass, {'t_dict': {}}) with self.subTest("Deserialize bound generics"): self.assertEqual( ExampleRedundantGenericDataclass("a"), dict_to_dataclass(ExampleRedundantGenericDataclass[int], {'s': "a"})) self.assertEqual( ExampleGenericTypeVarDataclass("a"), dict_to_dataclass(ExampleGenericTypeVarDataclass[str], {'t': "a"})) self.assertEqual( ExampleGenericTypeVarDataclass(1), dict_to_dataclass(ExampleGenericTypeVarDataclass[int], {'t': 1})) self.assertEqual( ExampleGenericCompoundDataclass({'a': "b"}), dict_to_dataclass(ExampleGenericCompoundDataclass[str], {'t_dict': { 'a': "b" }})) self.assertEqual( ExampleGenericCompoundDataclass({'a': 1}), dict_to_dataclass(ExampleGenericCompoundDataclass[int], {'t_dict': { 'a': 1 }})) with self.subTest("Deserialize indirectly bound generics"): self.assertEqual( ExampleGenericTypeVarDataclass(["a", "b"]), dict_to_dataclass(ExampleGenericTypeVarDataclass[List[T]][str], {'t': ["a", "b"]}, deserialization_func=list_deserialization)) self.assertEqual( ExampleGenericCompoundDataclass({'a': ["a", "b"]}), dict_to_dataclass( ExampleGenericCompoundDataclass[List[T]][str], {'t_dict': { 'a': ["a", "b"] }}, deserialization_func=dict_deserialization( value_deserialization_func=list_deserialization))) with self.subTest("Fail bound generic incorrect type"): with self.assertRaises(DeserializationError): dict_to_dataclass(ExampleGenericTypeVarDataclass[str], {'t': 1}) with self.assertRaises(DeserializationError): dict_to_dataclass(ExampleGenericCompoundDataclass[str], {'t_dict': { 'a': 1 }})
def test_dict_to_dataclass_generics(self): # Shadowing a non-identical TypeVar of the same name interacts strangely with postponing annotations # So use the one in outer scope (if it exists) T = globals().get("T", TypeVar("T")) @dataclass class ExampleRedundantGenericDataclass(Generic[T]): s: str @dataclass class ExampleGenericTypeVarDataclass(Generic[T]): t: T @dataclass class ExampleGenericCompoundDataclass(Generic[T]): t_dict: Dict[str, T] with self.subTest("Fail generic deserialization"): with self.assertRaises(DeserializationError): dict_to_dataclass(ExampleRedundantGenericDataclass, {"s": "a"}) with self.assertRaises(DeserializationError): dict_to_dataclass(ExampleGenericTypeVarDataclass, {"t": "a"}) with self.assertRaises(DeserializationError): dict_to_dataclass(ExampleGenericCompoundDataclass, {"t_dict": {}}) with self.subTest("Deserialize bound generics"): self.assertEqual( ExampleRedundantGenericDataclass("a"), dict_to_dataclass(ExampleRedundantGenericDataclass[int], {"s": "a"}), ) self.assertEqual( ExampleGenericTypeVarDataclass("a"), dict_to_dataclass(ExampleGenericTypeVarDataclass[str], {"t": "a"}), ) self.assertEqual( ExampleGenericTypeVarDataclass(1), dict_to_dataclass(ExampleGenericTypeVarDataclass[int], {"t": 1}), ) self.assertEqual( ExampleGenericCompoundDataclass({"a": "b"}), dict_to_dataclass(ExampleGenericCompoundDataclass[str], {"t_dict": { "a": "b" }}), ) self.assertEqual( ExampleGenericCompoundDataclass({"a": 1}), dict_to_dataclass(ExampleGenericCompoundDataclass[int], {"t_dict": { "a": 1 }}), ) with self.subTest("Deserialize indirectly bound generics"): self.assertEqual( ExampleGenericTypeVarDataclass(["a", "b"]), dict_to_dataclass( ExampleGenericTypeVarDataclass[List[T]][str], {"t": ["a", "b"]}, deserialization_func=list_deserialization, ), ) self.assertEqual( ExampleGenericCompoundDataclass({"a": ["a", "b"]}), dict_to_dataclass( ExampleGenericCompoundDataclass[List[T]][str], {"t_dict": { "a": ["a", "b"] }}, deserialization_func=dict_deserialization( value_deserialization_func=list_deserialization), ), ) with self.subTest("Fail bound generic incorrect type"): with self.assertRaises(DeserializationError): dict_to_dataclass(ExampleGenericTypeVarDataclass[str], {"t": 1}) with self.assertRaises(DeserializationError): dict_to_dataclass(ExampleGenericCompoundDataclass[str], {"t_dict": { "a": 1 }})