def test_none_with_none_as_default(): @dataclass class ProcMan: schedule: Union[str, None] = field(default=None) children_ids: List[str] = field(default_factory=list) node_context: dict = field(default_factory=dict) config = {'children_ids': []} process_config = howard.from_dict(config, ProcMan) # This would cause an error if a default value is actually "none howard.to_dict(process_config)
def test_with_advanced_typed_dict(): @dataclass class TypedDictTest: pair: List[TypedDict('pair', {'drink': Drink, 'card': Card})] data = { 'pair': [{ 'drink': { 'name': 'milk' }, 'card': { 'rank': 5, 'suit': 'h' } }, { 'drink': { 'name': 'gin' }, 'card': { 'rank': 12, 'suit': 's' } }] } result = howard.from_dict(data, TypedDictTest) assert isinstance(result, TypedDictTest) assert isinstance(result.pair, list) assert isinstance(result.pair[0], dict) assert isinstance(result.pair[0]['drink'], Drink) assert isinstance(result.pair[0]['card'], Card) test_dict = howard.to_dict(result) assert isinstance(test_dict, dict)
def test_strip_out_internal_fields(): @dataclass class Test3: a: int b: str = field(default='', metadata={'internal': True}) t = Test3(a=1, b='3') result = howard.to_dict(t) assert 'b' not in result
def test_strip_out_public(): @dataclass class Test2: a: int b: str _c: str t = Test2(a=1, b='2', _c='3') result = howard.to_dict(t, public_only=True) assert result.get('a') == 1 assert result.get('b') == '2' assert '_c' not in result
def test_with_typed_dict_total_false(): @dataclass class TypedDictTest: sub: List[TypedDict('sub', {'key1': str, 'key2': int}, total=False)] data = {'sub': [{'key1': 'hello'}]} result = howard.from_dict(data, TypedDictTest) assert isinstance(result, TypedDictTest) assert isinstance(result.sub, list) assert isinstance(result.sub[0], dict) test_dict = howard.to_dict(result) assert isinstance(test_dict, dict) assert isinstance(test_dict['sub'], list)
def test_datetime_to_from_dict(): @dataclass class DateTimeTest: my_date: datetime data = {'my_date': '1994-11-05T13:15:30Z'} # marshal into DateTimeTest object test_datetime = howard.from_dict(data, DateTimeTest) # make sure it is a datetime and the right year (should be right beyond that) assert type(test_datetime.my_date) is datetime assert test_datetime.my_date.year == 1994 # Then go back to a dict and make sure we didn't lose any data for the datetime. new_dict = howard.to_dict(test_datetime) assert '1994-11-05T13:15:30' in new_dict.get('my_date')
def test_custom_field_encoding(): def encode_date(d: date) -> str: return d.isoformat() @dataclass class Person: name: str dob: date = field(metadata=dict(howard=dict(encoder=encode_date))) bob = Person(name='Bob', dob=date(2020, 1, 1)) expected_dob = '2020-01-01' data = howard.to_dict(bob) assert data['dob'] == expected_dob
def test_with_literals(): @dataclass class LiteralCard: rank: int suit: Literal['heart', 'spade', 'diamond', 'club'] with pytest.raises(TypeError): # suit isn't valid howard.from_dict({'rank': 13, 'suit': 'other'}, LiteralCard) result = howard.from_dict({'rank': 13, 'suit': 'spade'}, LiteralCard) assert isinstance(result, LiteralCard) final = howard.to_dict(result) assert isinstance(final, dict) assert isinstance(final['suit'], str)
def test_multipart_field_encoding_decoding(): def seq_to_date(s: Sequence[int]) -> date: year, month, day = s return date(year, month, day) def date_to_seq(d: date) -> Sequence: return (d.year, d.month, d.day) date_field = field(metadata=dict( howard=dict(decoder=seq_to_date, encoder=date_to_seq))) @dataclass class Person: name: str dob: date = date_field data = {'name': 'Alice', 'dob': (2020, 1, 15)} expected_dob = date(2020, 1, 15) alice = howard.from_dict(data, Person) assert alice.dob == expected_dob # Test roundtrip: assert howard.to_dict(alice) == data
def test_dict_is_same_coming_back(d, t): obj = howard.from_dict(d, t) assert obj assert d == howard.to_dict(obj)
def test_optional_type_set(): drink = {'name': 'scotch', 'glass_type': 'lowball'} obj = howard.from_dict(drink, Drink) assert isinstance(obj, Drink) assert 'lowball' == obj.glass_type assert {'name': 'scotch', 'glass_type': 'lowball'} == howard.to_dict(obj)