def test_optional_specified_null_deserializer() -> None: # note: type_deserializers dont specify the type of the dynamically loaded value, # they specify the type specified by the namedtuple. # so cant do something like # loaded = json.loads("{}") # none_deserializer = {type(None): lambda _x: 0} # x = autotui.deserialize_namedtuple(loaded, X_OPT, type_deserializers=none_deserializer) # assert x.a == 0 # in this case, because it expects int. The none_deserializer is never used, because # None is not a type on X_OPT. Could do it against int, # should use an attr_deserializer in this case loaded = json.loads('{"a": null}') attr_deserializers = {"a": deserialize_a} x = autotui.deserialize_namedtuple(loaded, X_OPT, attr_deserializers=attr_deserializers) assert x.a == 0 # could also do like loaded = json.loads('{"a": null}') type_deserializers = {int: deserialize_a} # specify int, not NoneType x = autotui.deserialize_namedtuple(loaded, X_OPT, type_deserializers=type_deserializers) assert x.a == 0
def test_enum_serialization() -> None: d = DAT(choice=En.x) d2 = DAT(choice=En.z) ds = autotui.serialize_namedtuple(d) ds2 = autotui.serialize_namedtuple(d2) assert ds["choice"] == 1 assert ds2["choice"] == "something" assert d == autotui.deserialize_namedtuple(ds, DAT) assert d2 == autotui.deserialize_namedtuple(ds2, DAT)
def test_expected_key_warning() -> None: loaded = json.loads("{}") with warnings.catch_warnings(record=True) as record: x = autotui.deserialize_namedtuple(loaded, X) assert len(record) == 2 assert "Expected key a on non-optional field" in str(record[0].message) assert x.a == None assert "For value None, expected type int, found NoneType" == str( record[1].message)
def test_supply_serializer_deserializer() -> None: cur: datetime = datetime.now() timestamp: int = int(cur.timestamp()) w = WeightData(when=cur, data=Weight("20lbs")) wd = autotui.serialize_namedtuple( w, type_serializers={Weight: weight_serializer}) assert type(wd) == dict assert wd["data"] == 20.0 assert wd["when"] == timestamp # test dumping to JSON assert json.dumps(wd) == '{"when": ' + str(timestamp) + ', "data": 20.0}' # JSON, there and back w_jsonstr: str = json.dumps(wd) w_loaded: Json = json.loads(w_jsonstr) w_loaded_obj: Json = autotui.deserialize_namedtuple( w_loaded, WeightData, type_deserializers={Weight: weight_deserializer}) assert int(w_loaded_obj.when.timestamp()) == timestamp assert w_loaded_obj.data == Weight("20lbs") wd = autotui.serialize_namedtuple( w, attr_serializers={"data": weight_serializer}) assert type(wd) == dict assert wd["data"] == 20.0 assert wd["when"] == timestamp bw = autotui.deserialize_namedtuple( wd, WeightData, type_deserializers={Weight: weight_deserializer}) assert type(bw) == type(w) # annoyig because of tz_info # assert bw.when == cur assert int(bw.when.timestamp()) == timestamp assert bw.data == Weight("20lbs") # supply attr_deserializers instead bw = autotui.deserialize_namedtuple( wd, WeightData, attr_deserializers={"data": weight_deserializer}) assert type(bw) == type(w) # annoyig because of tz_info # assert bw.when == cur assert int(bw.when.timestamp()) == timestamp assert bw.data == Weight("20lbs")
def test_default_value_on_non_optional_collection(): loaded: Json = json.loads("{}") with warnings.catch_warnings(record=True) as record: l = autotui.deserialize_namedtuple(loaded, L) assert len(record) == 2 assert ( "Expected key b on non-optional field, no such key existed in loaded data" == str(record[0].message)) assert ( "No value loaded for non-optional type b, defaulting to empty container" in str(record[1].message)) assert l.a == None assert l.b == set()
def test_int_converts_to_float_no_warning() -> None: p = P(a=5, b=5, c="test", d=datetime.now()) with warnings.catch_warnings(record=True) as record: serialized = autotui.serialize_namedtuple(p) # not converted when serialized assert serialized["b"] == 5 # since the type hint specifies a float, convert # the 5 to a float deserialized: P = autotui.deserialize_namedtuple(serialized, to=P) assert isinstance(deserialized.b, float) assert deserialized.b == 5.0 assert len(record) == 0
def test_enum_fails() -> None: ds = {"choice": "xx"} with pytest.raises(ValueError, match=r"Could not find xx on Enumeration"): autotui.deserialize_namedtuple(ds, DAT)
def test_enum_use_key() -> None: d = DAT(choice=En.y) ds = {"choice": "y"} # use key name instead of value assert autotui.deserialize_namedtuple(ds, DAT) == d
def test_null_in_containers_warns() -> None: loaded = json.loads('{"a": [1,null,3]}') with pytest.warns(Warning, match=r"expected type int, found NoneType"): x = autotui.deserialize_namedtuple(loaded, LL) assert x.a == [1, None, 3]
def test_optional_key_loads_with_no_warnings() -> None: loaded = json.loads("{}") x = autotui.deserialize_namedtuple(loaded, X_OPT) assert x.a is None
def test_leave_optional_collection_none() -> None: loaded: Json = json.loads('{"b": [true]}') l = autotui.deserialize_namedtuple(loaded, L) # shouldnt warn, just serializes to None assert l.a == None assert l.b == {True}
def test_basic_iterable_deserialize() -> None: loaded: Json = json.loads('{"a": [1, 2, 3], "b": [true]}') l = autotui.deserialize_namedtuple(loaded, L) l.a == [1, 2, 3] l.b == {True}