def test_attrs_classes_disregards(): "Test that attrs_classes disregards unknown verbs and types." assert at.attrs_classes(verb=PY2JSON, typ=int, ctx=Fail()) is None assert at.attrs_classes(verb=INSP_PY, typ=int, ctx=Fail()) is None assert at.attrs_classes(verb=JSON2PY, typ=object, ctx=Fail()) is None assert at.attrs_classes(verb="dummy", typ=Flat, ctx=Fail()) is None
def test_attrs_hooks(HookCls): "Test that attrs_classes enables hooks." encoder = at.attrs_classes(verb=PY2JSON, typ=HookCls, ctx=Ctx()) assert encoder(HookCls(33, "foo")) == { "_type_": "Hook", "a": 33, "b": "foo" } assert encoder(HookCls(33, "default")) == {"_type_": "Hook", "a": 33} decoder = at.attrs_classes(verb=JSON2PY, typ=HookCls, ctx=Ctx()) assert decoder([33, "foo"]) == HookCls(33, "foo") assert decoder({"a": 33, "b": "foo"}) == HookCls(33, "foo") assert decoder({"a": 33}) == HookCls(33) inspect = at.attrs_classes(verb=INSP_PY, typ=HookCls, ctx=Ctx()) assert inspect(HookCls(33, "foo")) assert inspect(HookCls("str", "foo")) assert not inspect({"a": 33, "b": "foo"}) inspect = at.attrs_classes(verb=INSP_JSON, typ=HookCls, ctx=Ctx()) assert inspect({"_type_": "Hook", "a": "str", "b": "foo"}) assert not inspect({"a": 33, "b": "foo"}) assert inspect({"_type_": "Hook", "a": 33, "b": "foo"}) assert inspect({"_type_": "Hook"})
def test_attrs_generic(GenClass): if GenClass is None: pytest.skip() @attr.s class Top: nested = attr.ib(type=GenClass[GenClass[str, str], str]) list_of = attr.ib(type=List[GenClass[Tuple[Flat, ...], int]]) rules = Rules(at.attrs_classes, std.atoms, std.lists) py_val = Top( nested=GenClass( body=GenClass(body="body", count=5, messages=["msg1", "msg2"]), count=3, messages=["msg3", "msg4"], ), list_of=[ GenClass(body=(Flat(a=1), Flat(a=2, b="three")), count=4, messages=[6, 7]) ], ) j_val = { "list_of": [{ "body": [{ "a": 1 }, { "a": 2, "b": "three" }], "count": 4, "messages": [6, 7] }], "nested": { "body": { "body": "body", "count": 5, "messages": ["msg1", "msg2"] }, "count": 3, "messages": ["msg3", "msg4"], }, } encoder = at.attrs_classes(verb=PY2JSON, typ=Top, ctx=rules) assert encoder(py_val) == j_val decoder = at.attrs_classes(verb=JSON2PY, typ=Top, ctx=rules) assert decoder(j_val) == py_val inspect = at.attrs_classes(verb=INSP_PY, typ=Top, ctx=rules) assert inspect(py_val) inspect = at.attrs_classes(verb=INSP_JSON, typ=Top, ctx=rules) assert inspect(j_val)
def test_attrs_private(PrivateCls): "Test that attrs_classes encode and decode classes with private fields correctly." if PrivateCls is None: pytest.skip("Annotations unavailable") original = PrivateCls("value", 77) encoder = at.attrs_classes(verb=PY2JSON, typ=PrivateCls, ctx=Ctx()) encoded = encoder(original) assert encoded["pub"] == "value" assert encoded["_priv"] == 77 decoder = at.attrs_classes(verb=JSON2PY, typ=PrivateCls, ctx=Ctx()) decoded = decoder(encoded) assert decoded == original
def test_encode_incomparable(): "Test that encoding doesn't fail if a field's __eq__ method throws." rules = Rules(at.attrs_classes, std.atoms, std.lists) encoder = at.attrs_classes(verb=PY2JSON, typ=IncomparableContainer, ctx=rules) assert encoder(IncomparableContainer(Incomparable())) == {"field1": {}} assert encoder(IncomparableContainer(Incomparable(), 4)) == { "field1": {}, "field2": 4 } decoder = at.attrs_classes(verb=JSON2PY, typ=IncomparableContainer, ctx=rules) actual = decoder({"field1": {}}) assert isinstance(actual.field1, Incomparable) assert actual.field2 == 3
def test_attrs_encoding(FlatCls): "Test that attrs_classes encodes and decodes a flat class." encoder = at.attrs_classes(verb=PY2JSON, typ=FlatCls, ctx=Ctx()) assert encoder(FlatCls(33, "foo")) == {"a": 33, "b": "foo"} assert encoder(FlatCls(33, "default")) == {"a": 33} decoder = at.attrs_classes(verb=JSON2PY, typ=FlatCls, ctx=Ctx()) assert decoder({"a": 33, "b": "foo"}) == FlatCls(33, "foo") assert decoder({"a": 33}) == FlatCls(33) inspect = at.attrs_classes(verb=INSP_PY, typ=FlatCls, ctx=Ctx()) assert inspect(FlatCls(33, "foo")) assert inspect(FlatCls("str", "foo")) assert not inspect({"a": 33, "b": "foo"}) inspect = at.attrs_classes(verb=INSP_JSON, typ=FlatCls, ctx=Ctx()) assert not inspect(FlatCls(33, "foo")) assert not inspect({"a": "str", "b": "foo"}) assert inspect({"a": 33}) assert inspect({"a": 33, "b": "foo"}) assert not inspect({"b": "foo"})
def test_attrs_encoding(con, FlatCls): "Test that attrs_classes encodes and decodes a flat class." if FlatCls is None: pytest.skip("Annotations unavailable") encoder = at.attrs_classes(verb=PY2JSON, typ=FlatCls, ctx=Ctx()) assert encoder(con(33, "foo")) == {"a": 33, "b": "foo"} assert encoder(con(33, "default")) == {"a": 33} decoder = at.attrs_classes(verb=JSON2PY, typ=FlatCls, ctx=Ctx()) assert decoder({"a": 33, "b": "foo"}) == FlatCls(33, "foo") assert decoder({"a": 33}) == FlatCls(33) inspect = at.attrs_classes(verb=INSP_PY, typ=FlatCls, ctx=Ctx()) assert inspect(con(33, "foo")) assert inspect(con("str", "foo")) assert not inspect({"a": 33, "b": "foo"}) inspect = at.attrs_classes(verb=INSP_JSON, typ=FlatCls, ctx=Ctx()) assert not inspect(con(33, "foo")) assert not inspect({"a": "str", "b": "foo"}) assert inspect({"a": 33}) assert inspect({"a": 33, "b": "foo"}) assert not inspect({"b": "foo"})