예제 #1
0
def test_with_typed_dict_fail():
    @dataclass
    class TypedDictTest:
        sub: List[TypedDict('sub', {'key1': str, 'key2': int})]

    data = {'sub': [{'key1': 'hello'}]}
    with pytest.raises(TypeError):
        howard.from_dict(data, TypedDictTest)
예제 #2
0
def test_extra_dict_value_fields_raise():
    d = {
        'party_id': 1,
        'players': {
            'John': {
                'hand_id': 2,
                'cards': [],
                'extra': 'foo'
            }
        }
    }
    with pytest.raises(TypeError):
        howard.from_dict(d, Party, ignore_extras=False)
예제 #3
0
def test_with_union():
    @dataclass
    class SomeType:
        a: Union[str, bool]
        b: Union[str, int]

    result = howard.from_dict({'a': 'a', 'b': 'b'}, SomeType)
    assert isinstance(result, SomeType)
    assert isinstance(result.b, str)
    assert isinstance(result.a, str)

    result = howard.from_dict({'a': 'a', 'b': 5}, SomeType)
    assert isinstance(result, SomeType)
    assert isinstance(result.b, int)

    result = howard.from_dict({'a': 'a', 'b': False}, SomeType)
    assert isinstance(result, SomeType)
    assert isinstance(result.b, int)
    assert result.b == 0

    with pytest.raises(TypeError):
        howard.from_dict({'a': 'a', 'b': ['list']}, SomeType)

    with pytest.raises(TypeError):
        howard.from_dict({'a': 1, 'b': 'b'}, SomeType)

    result = howard.from_dict({'a': True, 'b': 'b'}, SomeType)
    assert isinstance(result, SomeType)
    assert isinstance(result.a, bool)
예제 #4
0
def test_dict_of_hands():
    hand1 = {
        'hand_id':
        1,
        'cards': [{
            'rank': 10,
            'suit': 'h'
        }, {
            'rank': 9,
            'suit': 's'
        }, {
            'rank': 1,
            'suit': 'c'
        }]
    }
    hand2 = {
        'hand_id': 2,
        'cards': [{
            'rank': 2,
            'suit': 'c'
        }, {
            'rank': 10,
            'suit': 'h'
        }]
    }
    d = {'party_id': 1, 'players': {'John': hand1, 'Joe': hand2}}

    obj = howard.from_dict(d, Party)

    assert isinstance(obj, Party)
    assert obj.party_id == 1
    assert len(obj.players.items()) == 2
    assert 'John' in obj.players.keys()
    assert isinstance(obj.players['John'], Hand)
    assert len(obj.players['John'].cards) == 3
예제 #5
0
def test_with_any():
    # Any type should basically bypass howard
    @dataclass
    class SomeType:
        a: dict  # dict is the same as Dict[Any, Any]
        b: list  # list is the same as List[Any]
        c: Dict[str, Any]
        d: List[Any]
        e: Any

    result = howard.from_dict(
        {
            'a': {
                'foo': 'bar'
            },
            'b': [1, '2', True],
            'c': {
                'foo': 'bar'
            },
            'd': ['hello', False],
            'e': 1
        }, SomeType)
    assert isinstance(result, SomeType)
    assert isinstance(result.a, dict)
    assert isinstance(result.b, list)
    assert isinstance(result.c, dict)
    assert isinstance(result.d, list)
    assert isinstance(result.e, int)
예제 #6
0
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)
예제 #7
0
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)
예제 #8
0
def test_vanity_types():
    UserID = NewType('UniqueID', str)

    @dataclass
    class MyTestDC:
        id: UserID

    result = howard.from_dict({'id': '123'}, MyTestDC)
    assert isinstance(result, MyTestDC)
    assert isinstance(result.id, str)
예제 #9
0
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)
예제 #10
0
def test_subclass():
    class MyStr(str):
        # while not a "type" its still valid
        pass

    @dataclass
    class SomeType:
        a: MyStr

    result = howard.from_dict({'a': 'cabbages'}, SomeType)
    assert isinstance(result, SomeType)
    assert isinstance(result.a, str)
예제 #11
0
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)
예제 #12
0
def test_custom_field_decoding():
    def decode_date(s: str) -> date:
        return date.fromisoformat(s)

    @dataclass
    class Person:
        name: str
        dob: date = field(metadata=dict(howard=dict(decoder=decode_date)))

    data = {'name': 'Bob', 'dob': '2020-01-01'}
    expected_dob = date(2020, 1, 1)
    bob = howard.from_dict(data, Person)

    assert bob.dob == expected_dob
예제 #13
0
def test_extra_dict_value_fields_are_ignored():
    d = {
        'party_id': 1,
        'players': {
            'John': {
                'hand_id': 2,
                'cards': [],
                'extra': 'foo'
            }
        }
    }
    obj = howard.from_dict(d, Party)
    assert isinstance(obj, Party)
    assert not hasattr(obj.players['John'], 'extra')
예제 #14
0
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')
예제 #15
0
def test_hand_is_what_we_expect():
    d = {
        'hand_id': 2,
        'cards': [{
            'rank': 2,
            'suit': 'c'
        }, {
            'rank': 10,
            'suit': 'h'
        }]
    }
    obj = howard.from_dict(d, Hand)

    assert isinstance(obj, Hand)
    assert obj.hand_id == 2
    assert len(obj.cards) == 2
    assert isinstance(obj.cards[0], Card)
    assert obj.cards[0].suit == Suit.club
예제 #16
0
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
예제 #17
0
def test_unsupported_type():
    with pytest.raises(TypeError):
        howard.from_dict({'t': (1, 2, 3)}, UnsupportedTuple)
예제 #18
0
def test_dict_is_same_coming_back(d, t):
    obj = howard.from_dict(d, t)
    assert obj
    assert d == howard.to_dict(obj)
예제 #19
0
def test_nested_extra_fields_are_ignored():
    d = {'inner': {'val': 'inner_value', 'extra': 'foo'}}
    obj = howard.from_dict(d, Outer)
    assert isinstance(obj, Outer)
    assert isinstance(obj.inner, Inner)
    assert not hasattr(obj.inner, 'extra')
예제 #20
0
def test_listed_extra_fields_are_ignored():
    d = {'hand_id': 2, 'cards': [{'rank': 10, 'suit': 'h', 'extra': 'foo'}]}
    obj = howard.from_dict(d, Hand)
    assert isinstance(obj, Hand)
    assert obj.cards[0].rank == 10
    assert not hasattr(obj.cards[0], 'extra')
예제 #21
0
def test_extra_fields_raise():
    d = {'rank': 2, 'suit': 'h', 'extra': 'foo'}
    with pytest.raises(TypeError):
        howard.from_dict(d, Card, ignore_extras=False)
예제 #22
0
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)
예제 #23
0
def test_field_validation():
    data = {'suit': 'h', 'rank': 20}
    with pytest.raises(ValueError):
        howard.from_dict(data, Card)
예제 #24
0
def test_nested_extra_fields_raise():
    d = {'inner': {'val': 'inner_value', 'extra': 'foo'}}
    with pytest.raises(TypeError):
        howard.from_dict(d, Outer, ignore_extras=False)
예제 #25
0
def test_optional_type_not_set():
    drink = {'name': 'tequila'}
    obj = howard.from_dict(drink, Drink)
    assert isinstance(obj, Drink)
    assert obj.glass_type is None
예제 #26
0
def test_normal_dict():
    d = {'scores': {'John': 3, 'Joe': -1}}
    obj = howard.from_dict(d, Score)

    assert isinstance(obj, Score)
    assert obj.scores['John'] == 3
예제 #27
0
def test_dict_instead_of_list_in_hand():
    d = {'cards': {'1': {'rank': 2, 'suit': 'c'}}}

    with pytest.raises(TypeError):
        howard.from_dict(d, Hand)
예제 #28
0
def test_unknown_suit():
    d = {'rank': 2, 'suit': 'a'}

    with pytest.raises(Exception):
        howard.from_dict(d, Card)
예제 #29
0
def test_float_instead_of_int():
    d = {'hand_id': 2.5}
    with pytest.raises(TypeError):
        howard.from_dict(d, Hand)
예제 #30
0
def test_listed_extra_fields_raise():
    d = {'hand_id': 2, 'cards': [{'rank': 10, 'suit': 'h', 'extra': 'foo'}]}
    with pytest.raises(TypeError):
        howard.from_dict(d, Hand, ignore_extras=False)