Ejemplo n.º 1
0
def test_union_with_union_in_nested_types():
    @deserialize
    @serialize
    @dataclass
    class A:
        v: Union[UUID, List[Union[UUID, int]]]

    a_uuid = A([UUID("00611ee9-7ca3-41d3-9607-ea7268e264ea")])
    assert to_dict(a_uuid, reuse_instances=False) == {
        "v": ["00611ee9-7ca3-41d3-9607-ea7268e264ea"]
    }
    assert a_uuid == from_dict(A,
                               to_dict(a_uuid, reuse_instances=False),
                               reuse_instances=False)
    assert a_uuid == from_dict(A,
                               to_dict(a_uuid, reuse_instances=True),
                               reuse_instances=True)

    a_int = A([1])
    assert to_dict(a_int) == {"v": [1]}
    assert a_int == from_dict(A,
                              to_dict(a_int, reuse_instances=False),
                              reuse_instances=False)
    assert a_int == from_dict(A,
                              to_dict(a_int, reuse_instances=True),
                              reuse_instances=True)
Ejemplo n.º 2
0
def test_dataclass_inheritance():
    @deserialize
    @serialize
    @dataclass
    class Base:
        i: int
        s: str

    @deserialize
    @serialize
    @dataclass
    class DerivedA(Base):
        j: int

    @deserialize
    @serialize
    @dataclass
    class DerivedB(Base):
        k: float

    # each class should have own scope
    # ensure the generated code of DerivedB does not overwrite the earlier generated code from DerivedA
    assert getattr(Base, serde.core.SERDE_SCOPE) is not getattr(DerivedA, serde.core.SERDE_SCOPE)
    assert getattr(DerivedA, serde.core.SERDE_SCOPE) is not getattr(DerivedB, serde.core.SERDE_SCOPE)

    base = Base(i=0, s="foo")
    assert base == from_dict(Base, to_dict(base))

    a = DerivedA(i=0, s="foo", j=42)
    assert a == from_dict(DerivedA, to_dict(a))

    b = DerivedB(i=0, s="foo", k=42.0)
    assert b == from_dict(DerivedB, to_dict(b))
Ejemplo n.º 3
0
def test_skip_if_default(se, de):
    @serde.serde
    class Foo:
        a: str = serde.field(default='foo', skip_if_default=True)

    f = Foo()
    assert f == de(Foo, se(f))

    assert serde.to_dict(Foo()) == {}
    assert serde.to_dict(Foo('bar')) == {'a': 'bar'}
    assert serde.from_dict(Foo, {}) == Foo()
    assert serde.from_dict(Foo, {'a': 'bar'}) == Foo('bar')
Ejemplo n.º 4
0
def test_serde_with_lazy_type_annotations():
    a = A(1, Status.ERR, ["foo"])
    a_dict = {"a": 1, "b": "err", "c": ["foo"]}

    assert a == from_dict(A, a_dict)
    assert a_dict == to_dict(a)

    b = B(a, ("foo", a), Status.OK)
    b_dict = {"a": a_dict, "b": ("foo", a_dict), "c": "ok"}

    assert b == from_dict(B, b_dict)
    assert b_dict == to_dict(b)
Ejemplo n.º 5
0
def test_union_in_other_type():
    @serde
    class A:
        v: Dict[str, Union[UUID, int]]

    a_uuid = A({"key": UUID("00611ee9-7ca3-41d3-9607-ea7268e264ea")})
    assert a_uuid == from_dict(A, to_dict(a_uuid, reuse_instances=False), reuse_instances=False)
    assert a_uuid == from_dict(A, to_dict(a_uuid, reuse_instances=True), reuse_instances=True)

    a_int = A({"key": 1})
    assert a_int == from_dict(A, to_dict(a_int, reuse_instances=False), reuse_instances=False)
    assert a_int == from_dict(A, to_dict(a_int, reuse_instances=True), reuse_instances=True)
Ejemplo n.º 6
0
def test_optional_union_with_complex_types():
    @serde
    class A:
        v: Optional[Union[int, IPv4Address, UUID]]

    a = A(123)
    assert a == from_dict(A, to_dict(a, reuse_instances=False), reuse_instances=False)
    assert a == from_dict(A, to_dict(a, reuse_instances=True), reuse_instances=True)

    a_none = A(None)
    assert a_none == from_dict(A, to_dict(a_none, reuse_instances=False), reuse_instances=False)
    assert a_none == from_dict(A, to_dict(a_none, reuse_instances=True), reuse_instances=True)
Ejemplo n.º 7
0
def test_default(se, de):
    p = PriDefault()
    assert p == de(PriDefault, se(p))

    p = PriDefault()
    assert p == from_dict(PriDefault, {})
    assert p == from_dict(PriDefault, {'i': 10})
    assert p == from_dict(PriDefault, {'i': 10, 's': 'foo'})
    assert p == from_dict(PriDefault, {'i': 10, 's': 'foo', 'f': 100.0})
    assert p == from_dict(PriDefault, {'i': 10, 's': 'foo', 'f': 100.0, 'b': True})

    assert 10 == dataclasses.fields(PriDefault)[0].default
    assert 'foo' == dataclasses.fields(PriDefault)[1].default
    assert 100.0 == dataclasses.fields(PriDefault)[2].default
    assert True is dataclasses.fields(PriDefault)[3].default
Ejemplo n.º 8
0
def test_exception_on_not_supported_types():
    class UnsupportedClass:
        def __init__(self):
            pass

    @serde.serde
    class Foo:
        b: UnsupportedClass

    with pytest.raises(serde.SerdeError) as se_ex:
        serde.to_dict(Foo(UnsupportedClass()))
    assert str(se_ex.value).startswith("Unsupported type: UnsupportedClass")

    with pytest.raises(serde.SerdeError) as de_ex:
        serde.from_dict(Foo, {"b": UnsupportedClass()})
    assert str(de_ex.value).startswith("Unsupported type: UnsupportedClass")
Ejemplo n.º 9
0
def test_union_rename_all():
    @serde(rename_all='pascalcase')
    class Foo:
        bar_baz: Union[int, str]

    assert to_dict(Foo(10)) == {'BarBaz': 10}
    assert from_dict(Foo, {'BarBaz': 'foo'}) == Foo('foo')
Ejemplo n.º 10
0
def test_union_with_complex_types_and_reuse_instances():
    @serde(reuse_instances_default=True)
    class A:
        v: Union[int, IPv4Address, UUID]

    a_int = A(1)
    a_int_roundtrip = from_dict(A, to_dict(a_int))
    assert a_int == a_int_roundtrip
    assert a_int.v is a_int_roundtrip.v

    a_ip = A(IPv4Address("127.0.0.1"))
    a_ip_roundtrip = from_dict(A, to_dict(a_ip))
    assert a_ip == a_ip_roundtrip
    assert a_ip.v is a_ip_roundtrip.v

    a_uid = A(UUID("a317958e-4cbb-4213-9f23-eaff1563c472"))
    a_uid_roundtrip = from_dict(A, to_dict(a_uid))
    assert a_uid == a_uid_roundtrip
    assert a_uid.v is a_uid_roundtrip.v
Ejemplo n.º 11
0
def test_union_with_union_in_nested_tuple():
    @serde
    class A:
        v: Union[bool, Tuple[Union[str, int]]]

    a_bool = A(False)
    a_bool_dict = {"v": False}
    assert to_dict(a_bool) == a_bool_dict
    assert from_dict(A, a_bool_dict) == a_bool

    a_str = A(("a",))
    a_str_dict = {"v": ("a",)}
    assert to_dict(a_str) == a_str_dict
    assert from_dict(A, a_str_dict) == a_str

    a_int = A((1,))
    a_int_dict = {"v": (1,)}
    assert to_dict(a_int) == a_int_dict
    assert from_dict(A, a_int_dict) == a_int
Ejemplo n.º 12
0
def test_dataclass_default_factory(se, de):
    @serde.serde
    class Foo:
        foo: str
        items: Dict[str, int] = serde.field(default_factory=dict)

    f = Foo('bar')
    assert f == de(Foo, se(f))

    assert {'foo': 'bar', 'items': {}} == serde.to_dict(f)
    assert f == serde.from_dict(Foo, {'foo': 'bar'})
Ejemplo n.º 13
0
def test_from_dict():
    p = Pri(10, 'foo', 100.0, True)
    d = {'i': 10, 's': 'foo', 'f': 100.0, 'b': True}
    assert d == asdict(p)
    assert p == from_dict(Pri, d)

    p = {'p': Pri(10, 'foo', 100.0, True)}
    d = {'p': {'i': 10, 's': 'foo', 'f': 100.0, 'b': True}}
    assert d == asdict(p)
    assert p == from_dict(Dict[str, Pri], d)

    p = [Pri(10, 'foo', 100.0, True)]
    d = ({'i': 10, 's': 'foo', 'f': 100.0, 'b': True}, )
    assert d == asdict(p)
    assert p == from_dict(List[Pri], d)

    p = (Pri(10, 'foo', 100.0, True), )
    d = ({'i': 10, 's': 'foo', 'f': 100.0, 'b': True}, )
    assert d == asdict(p)
    assert p == from_dict(Tuple[Pri], d)
Ejemplo n.º 14
0
def test_make_serialize_deserialize(se):
    fields = [('i', int, dataclasses.field())]
    Foo = make_serde('Foo', se, fields)

    f = Foo(10)
    assert serde.to_dict(f) == {'i': 10}
    assert str(f) == 'Foo(i=10)'
    assert serde.from_dict(Foo, {'i': 10}) == f

    # Test class attribute
    fields = [('int_field', int, dataclasses.field())]
    Foo = make_serde('Foo', se, fields, rename_all='pascalcase')
    f = Foo(10)
    assert serde.to_dict(f) == {'IntField': 10}

    # Test field attribute
    fields = [('i', int, dataclasses.field(metadata={'serde_skip': True})),
              ('j', float, dataclasses.field())]
    Foo = make_serde('Foo', se, fields)
    f = Foo(10, 100.0)
    assert serde.to_dict(f) == {'j': 100.0}

    # Test class/field attributes at the same time
    fields = [
        ('int_field', int,
         dataclasses.field(metadata={'serde_rename': 'renamed_field'})),
        ('float_field', float, dataclasses.field()),
    ]
    Foo = make_serde('Foo', se, fields, rename_all='pascalcase')
    f = Foo(10, 100.0)
    assert serde.to_dict(f) == {'renamed_field': 10, 'FloatField': 100.0}

    # Nested
    fields = [('v', int, dataclasses.field())]
    Bar = make_serde('Bar', se, fields)

    fields = [('bar', Bar, dataclasses.field())]
    Foo = make_serde('Foo', se, fields)
    f = Foo(Bar(10))
    assert serde.to_dict(f) == {'bar': {'v': 10}}
    assert serde.from_dict(Foo, {'bar': {'v': 10}}) == f
Ejemplo n.º 15
0
def test_union_with_complex_types_in_containers():
    @deserialize
    @serialize
    @dataclass
    class A:
        v: Union[List[IPv4Address], List[UUID]]

    a_ips = A([IPv4Address("127.0.0.1"), IPv4Address("10.0.0.1")])
    assert a_ips == from_dict(A,
                              to_dict(a_ips, reuse_instances=False),
                              reuse_instances=False)
    assert a_ips == from_dict(A,
                              to_dict(a_ips, reuse_instances=True),
                              reuse_instances=True)

    a_uids = A([
        UUID("9c244009-c60d-452b-a378-b8afdc0c2d90"),
        UUID("5831dc09-20fe-4433-b476-5866b7143364")
    ])
    assert a_uids == from_dict(A,
                               to_dict(a_uids, reuse_instances=False),
                               reuse_instances=False)
    assert a_uids == from_dict(A,
                               to_dict(a_uids, reuse_instances=True),
                               reuse_instances=True)

    a_empty = A([])
    assert a_empty == from_dict(A,
                                to_dict(a_empty, reuse_instances=False),
                                reuse_instances=False)
    assert a_empty == from_dict(A,
                                to_dict(a_empty, reuse_instances=True),
                                reuse_instances=True)
Ejemplo n.º 16
0
def test_union_in_union():
    @deserialize
    @serialize
    @dataclass
    class A:
        v: Union[UUID, Union[int, str]]

    a_uuid = A(UUID("00611ee9-7ca3-41d3-9607-ea7268e264ea"))
    assert a_uuid == from_dict(A,
                               to_dict(a_uuid, reuse_instances=False),
                               reuse_instances=False)
    assert a_uuid == from_dict(A,
                               to_dict(a_uuid, reuse_instances=True),
                               reuse_instances=True)

    a_int = A(1)
    assert a_int == from_dict(A,
                              to_dict(a_int, reuse_instances=False),
                              reuse_instances=False)
    assert a_int == from_dict(A,
                              to_dict(a_int, reuse_instances=True),
                              reuse_instances=True)

    a_str = A("hello")
    assert a_str == from_dict(A,
                              to_dict(a_str, reuse_instances=False),
                              reuse_instances=False)
    assert a_str == from_dict(A,
                              to_dict(a_str, reuse_instances=True),
                              reuse_instances=True)
Ejemplo n.º 17
0
def test_union_with_list_of_other_class():
    @serde
    class A:
        a: int

    @serde
    class B:
        b: Union[List[A], str]

    b = B([A(1)])
    b_dict = {"b": [{"a": 1}]}
    assert to_dict(b) == b_dict
    assert from_dict(B, b_dict) == b
Ejemplo n.º 18
0
def test_exception_on_not_supported_types():
    class UnsupportedClass:
        def __init__(self):
            pass

    @deserialize
    @serialize
    @dataclass
    class Foo:
        b: UnsupportedClass

    with pytest.raises(SerdeError) as se_ex:
        to_dict(Foo(UnsupportedClass()))
    assert str(se_ex.value).startswith(
        "Unsupported type: <class \'tests.test_basics.test_exception_on_not_supported_types.<locals>.UnsupportedClass\'>"
    )

    with pytest.raises(SerdeError) as de_ex:
        from_dict(Foo, {"b": UnsupportedClass()})
    assert str(de_ex.value).startswith(
        "Unsupported type: <class \'tests.test_basics.test_exception_on_not_supported_types.<locals>.UnsupportedClass\'>"
    )
Ejemplo n.º 19
0
def test_dataclass_default_factory(se, de):
    @deserialize
    @serialize
    @dataclass
    class Foo:
        foo: str
        items: Dict[str, int] = field(default_factory=dict)

    f = Foo('bar')
    assert f == de(Foo, se(f))

    assert {'foo': 'bar', 'items': {}} == to_dict(f)
    assert f == from_dict(Foo, {'foo': 'bar'})
Ejemplo n.º 20
0
def test_union_with_complex_types():
    @serde
    class A:
        v: Union[int, IPv4Address, UUID]

    a_int = A(1)
    a_int_json = '{"v": 1}'
    assert to_json(a_int) == a_int_json
    assert from_json(A, a_int_json) == a_int
    assert a_int == from_dict(A, to_dict(a_int))

    a_ip = A(IPv4Address("127.0.0.1"))
    a_ip_json = '{"v": "127.0.0.1"}'
    assert to_json(a_ip) == a_ip_json
    assert from_json(A, a_ip_json) == a_ip
    assert a_ip == from_dict(A, to_dict(a_ip))

    a_uid = A(UUID("a317958e-4cbb-4213-9f23-eaff1563c472"))
    a_uid_json = '{"v": "a317958e-4cbb-4213-9f23-eaff1563c472"}'
    assert to_json(a_uid) == a_uid_json
    assert from_json(A, a_uid_json) == a_uid
    assert a_uid == from_dict(A, to_dict(a_uid))
Ejemplo n.º 21
0
def get(model: Type[T], afqn: str) -> Optional[T]:
    """Create a Python object of type Type[T] deserializing configuration file of the class which fully qualified name is afqn.
    The path of the configuration file is compute by the config_file_name function

    :param model: Type use a model to create a Python object deserializing a configuration file
    :type model: Type[T]
    :param afqn: fully qualified name of the class to configure
    :type afqn: str
    :return: an instance of Type[T] created deserializing the configuration file
    :rtype: T
    """
    name = config_file_name(afqn)
    if not exists(name):
        return None
    with open(name) as c:
        return from_dict(model, TomlDeserializer.deserialize(c.read()))
Ejemplo n.º 22
0
def test_default(se, de):
    from serde import from_dict, from_tuple

    from .data import OptDefault, PriDefault

    p = PriDefault()
    assert p == de(PriDefault, se(p))

    p = PriDefault()
    assert p == from_dict(PriDefault, {})
    assert p == from_dict(PriDefault, {'i': 10})
    assert p == from_dict(PriDefault, {'i': 10, 's': 'foo'})
    assert p == from_dict(PriDefault, {'i': 10, 's': 'foo', 'f': 100.0})
    assert p == from_dict(PriDefault, {
        'i': 10,
        's': 'foo',
        'f': 100.0,
        'b': True
    })
    assert p == from_tuple(PriDefault, (10, 'foo', 100.0, True))

    o = OptDefault()
    assert o == de(OptDefault, se(o))

    o = OptDefault()
    assert o == from_dict(OptDefault, {})
    assert o == from_dict(OptDefault, {"n": None})
    assert o == from_dict(OptDefault, {"n": None, "i": 10})
    assert o == from_tuple(OptDefault, (None, 10))

    o = OptDefault(n=None, i=None)
    assert o == from_dict(OptDefault, {"n": None, "i": None})
    assert o == from_tuple(OptDefault, (None, None))

    assert 10 == dataclasses.fields(PriDefault)[0].default
    assert 'foo' == dataclasses.fields(PriDefault)[1].default
    assert 100.0 == dataclasses.fields(PriDefault)[2].default
    assert True is dataclasses.fields(PriDefault)[3].default
Ejemplo n.º 23
0
def test_union_exception_if_nothing_matches():
    @deserialize
    @serialize
    @dataclass
    class A:
        v: Union[IPv4Address, UUID]

    with pytest.raises(SerdeError) as ex1:
        from_dict(A, {"v": "not-ip-or-uuid"})
    assert str(ex1.value) == (
        "Can not deserialize 'not-ip-or-uuid' of type str into Union[IPv4Address, UUID].\n"
        "Reasons:\n"
        " Failed to deserialize into IPv4Address: Expected 4 octets in 'not-ip-or-uuid'\n"
        " Failed to deserialize into UUID: badly formed hexadecimal UUID string"
    )

    with pytest.raises(SerdeError) as ex2:
        from_dict(A, {"v": "not-ip-or-uuid"}, reuse_instances=True)
    assert str(ex2.value) == (
        "Can not deserialize 'not-ip-or-uuid' of type str into Union[IPv4Address, UUID].\n"
        "Reasons:\n"
        " Failed to deserialize into IPv4Address: Expected 4 octets in 'not-ip-or-uuid'\n"
        " Failed to deserialize into UUID: badly formed hexadecimal UUID string"
    )

    with pytest.raises(SerdeError) as ex3:
        from_dict(A, {"v": None})
    # omit reason because it is not the same for all python versions & operating systems
    assert str(ex3.value).startswith(
        "Can not deserialize None of type NoneType into Union[IPv4Address, UUID]."
    )

    with pytest.raises(SerdeError) as ex4:
        to_dict(A("not-ip-or-uuid"))
    assert str(
        ex4.value
    ) == "Can not serialize 'not-ip-or-uuid' of type str for Union[IPv4Address, UUID]"

    with pytest.raises(SerdeError) as ex5:
        to_dict(A("not-ip-or-uuid"), reuse_instances=True)
    assert str(
        ex5.value
    ) == "Can not serialize 'not-ip-or-uuid' of type str for Union[IPv4Address, UUID]"

    with pytest.raises(SerdeError) as ex6:
        to_dict(A(None), reuse_instances=True)
    assert str(
        ex6.value
    ) == "Can not serialize None of type NoneType for Union[IPv4Address, UUID]"
Ejemplo n.º 24
0
def test_string_forward_reference_works():
    h = ForwardReferenceFoo(bar=ForwardReferenceBar(i=10))
    h_dict = {"bar": {"i": 10}}

    assert to_dict(h) == h_dict
    assert from_dict(ForwardReferenceFoo, h_dict) == h