def test_serialize_invalid_mapper_type(): class Foo(Structure): i = Integer with raises(TypeError) as excinfo: serialize(Foo(i=1), mapper=[1, 2]) assert 'Mapper must be a mapping' in str(excinfo.value)
def test_serialize_set_err(): class Foo(Structure): a = Set() foo = Foo(a={1, 2, 3}) with raises(TypeError) as excinfo: serialize(foo) assert "a: Serialization unsupported for set, tuple" in str(excinfo.value)
def test_serialize_with_mapper_error(): def my_func(): pass class Foo(Structure): function = Function i = Integer foo = Foo(function=my_func, i=1) mapper = {'function': 5, 'i': FunctionCall(func=lambda x: x + 5)} with raises(TypeError) as excinfo: serialize(foo, mapper=mapper) assert 'mapper must have a FunctionCall or a string' in str(excinfo.value)
def test_serializable_serialize_and_deserialize_of_a_non_serializable_value(): from datetime import datetime class Foo(Structure): d = DateTime i = Integer atime = datetime(2020, 1, 30, 5, 35, 35) foo = Foo(d=atime, i=3, x=atime) with raises(ValueError) as excinfo: serialize(foo) # this is to cater to Python 3.6 assert "x: cannot serialize value" in str(excinfo.value) assert "not JSON serializable" in str(excinfo.value)
def test_date_alternative_format_serialization(): class Example(Structure): d = DateString(date_format="%Y%m%d") i = Integer e = Example(d="19900530", i=5) assert deserialize_structure(Example, serialize(e)) == e
def test_string_field_wrapper_not_compact(): class Foo(Structure): st = String _additionalProperties = False foo = Foo(st='abcde') assert serialize(foo, compact=False) == {'st': 'abcde'}
def test_serializable_deserialize(): class MySerializable(SerializableField): def __init__(self, *args, some_param="xxx", **kwargs): self._some_param = some_param super().__init__(*args, **kwargs) def deserialize(self, value): return { "mykey": "my custom deserialization: {}, {}".format( self._some_param, str(value)) } def serialize(self, value): return 123 class Foo(Structure): d = Array[MySerializable(some_param="abcde")] i = Integer deserialized = deserialize_structure(Foo, { 'd': ["191204", "191205"], 'i': 3 }) assert deserialized == Foo(i=3, d=[{ 'mykey': 'my custom deserialization: abcde, 191204' }, { 'mykey': 'my custom deserialization: abcde, 191205' }]) assert serialize(deserialized) == {'d': [123, 123], 'i': 3}
def test_set_field_wrapper_compact(): class Foo(Structure): s = Array[AnyOf[String, Number]] _additionalProperties = False foo = Foo(s=['abcde', 234]) assert serialize(foo, compact=True) == ['abcde', 234]
def test_serialize_with_deep_mapper(): class Foo(Structure): a = String i = Integer class Bar(Structure): foo = Foo array = Array class Example(Structure): bar = Bar number = Integer example = Example(number=1, bar=Bar(foo=Foo(a="string", i=5), array=[1, 2])) mapper = { 'bar._mapper': { 'foo._mapper': { "i": FunctionCall(func=lambda x: x * 2) } } } serialized = serialize(example, mapper=mapper) assert serialized == \ { "number": 1, "bar": { "foo": { "a": "string", "i": 10 }, "array": [1, 2] } }
def test_deserialize_deque(): class Example(Structure): d = Deque[Array] original = {'d': [[1, 2], [3, 4]]} deserialized = deserialize_structure(Example, original) assert deserialized == Example(d=deque([[1, 2], [3, 4]])) assert serialize(deserialized) == original
def test_some_empty_fields(): class Foo(Structure): a = Integer b = String _required = [] foo = Foo(a=5) assert serialize(foo) == {'a': 5}
def test_null_fields(): class Foo(Structure): a = Integer b = String _required = [] foo = Foo(a=5, c=None) assert serialize(foo) == {'a': 5}
def test_serialize_with_mapper_to_different_keys(): class Foo(Structure): a = String i = Integer foo = Foo(a='string', i=1) mapper = {'a': 'aaa', 'i': 'iii'} assert serialize(foo, mapper=mapper) == {'aaa': 'string', 'iii': 1}
def test_serialize_non_typedpy_attribute(): class Foo(Structure): a = String i = Integer foo = Foo(a='a', i=1) foo.x = {'x': 1, 's': 'abc'} assert serialize(foo)['x'] == {'x': 1, 's': 'abc'}
def test_serialize_with_anything_field(): class Foo(Structure): m = Map[String, Anything] original = {'a': [1, 2, 3], 'b': 1} foo = Foo(m=original) assert serialize(foo.m) == original
def test_serialize_map(): class Foo(Structure): m1 = Map[String, Anything] m2 = Map i = Integer foo = Foo(m1={'a': [1, 2, 3], 'b': 1}, m2={1: 2, 'x': 'b'}, i=5) serialized = serialize(foo) assert serialized['m1'] == {'a': [1, 2, 3], 'b': 1}
def test_serialize_with_mapper_with_function_with_args(): class Foo(Structure): f = Float i = Integer foo = Foo(f=5.5, i=999) mapper = { 'f': FunctionCall(func=lambda f: [int(f)], args=['i']), 'i': FunctionCall(func=lambda x: str(x), args=['f']) } assert serialize(foo, mapper=mapper) == {'f': [999], 'i': '5.5'}
def test_serialize_enum_field_directly(): class Values(enum.Enum): ABC = enum.auto() DEF = enum.auto() GHI = enum.auto() class Foo(Structure): arr = Array[Enum[Values]] foo = Foo(arr=[Values.ABC, Values.DEF]) assert serialize(foo.arr[0]) == 'ABC'
def test_serialize_map_without_any_type_definition(): class Bar(Structure): m = Map() a = Integer original = Bar(a=3, m={'abc': Bar(a=2, m={"x": "xx"}), 'bcd': 2}) serialized = serialize(original) pickled = pickle.dumps(serialized) assert type(serialized['m']) == dict assert type(serialized['m']['abc']) == dict assert type(serialized['m']['abc']['m']) == dict
def test_serialize_with_mapper_with_function_converting_types(): class Foo(Structure): num = Float i = Integer foo = Foo(num=5.5, i=999) mapper = { 'num': FunctionCall(func=lambda f: [int(f)]), 'i': FunctionCall(func=lambda x: str(x)) } assert serialize(foo, mapper=mapper) == {'num': [5], 'i': '999'}
def test_serialize_with_mapper_to_different_keys_in_array(): class Foo(Structure): a = String i = Integer class Bar(Structure): wrapped = Array[Foo] bar = Bar(wrapped=[Foo(a='string1', i=1), Foo(a='string2', i=2)]) mapper = {'wrapped._mapper': {'a': 'aaa', 'i': 'iii'}, 'wrapped': 'other'} serialized = serialize(bar, mapper=mapper) assert serialized == \ {'other': [{'aaa': 'string1', 'iii': 1}, {'aaa': 'string2', 'iii': 2}]}
def test_serializable_serialize_and_deserialize(): from datetime import date class Foo(Structure): d = Array[DateField(date_format="%y%m%d")] i = Integer foo = Foo(d=[date(2019, 12, 4), "191205"], i=3) serialized = serialize(foo) assert serialized == {'d': ["191204", "191205"], 'i': 3} deserialized = deserialize_structure(Foo, serialized) assert deserialized == Foo(i=3, d=[date(2019, 12, 4), date(2019, 12, 5)])
def test_pickle_with_map_without_any_type_definition(): class Bar(Structure): m = Map() a = Integer original = Bar(a=3, m={'abc': Bar(a=2, m={"x": "xx"}), 'bcd': 2}) serialized = serialize(original) unpickeled = pickle.loads(pickle.dumps(serialized)) deserialized = Deserializer(target_class=Bar).deserialize(unpickeled) # there is no info on the fact that deserialized.m['abc'] should be converted to a Bar instance, so # we convert it to a simple dict, to make it straight forward to compare original.m['abc'] = Serializer(original.m['abc']).serialize() assert deserialized == original
def test_serialize_with_mapper_with_functions(): def my_func(): pass class Foo(Structure): function = Function i = Integer foo = Foo(function=my_func, i=1) mapper = { 'function': FunctionCall(func=lambda f: f.__name__), 'i': FunctionCall(func=lambda x: x + 5) } assert serialize(foo, mapper=mapper) == {'function': 'my_func', 'i': 6}
def test_serialization_with_implicit_wrappers_best_effort_can_work(): @dataclass class SimplePoint: x: int y: int class Foo(Structure): points = Array[SimplePoint] foo = Foo(points=[SimplePoint(1, 2), SimplePoint(2, 3)]) serialized = serialize(foo) assert serialized['points'][0] == {"x": 1, "y": 2} deserialized = deserialize_structure(Foo, serialized) assert deserialized == foo
def test_serializable_serialize_and_deserialize2(): from datetime import datetime class Foo(Structure): d = Array[DateTime] i = Integer atime = datetime(2020, 1, 30, 5, 35, 35) atime_as_string = atime.strftime('%m/%d/%y %H:%M:%S') foo = Foo(d=[atime, "01/30/20 05:35:35"], i=3) serialized = serialize(foo) assert serialized == {'d': [atime_as_string, '01/30/20 05:35:35'], 'i': 3} deserialized = deserialize_structure(Foo, serialized) assert str(deserialized) == str( Foo(i=3, d=[atime, datetime(2020, 1, 30, 5, 35, 35)]))
def test_successful_deserialization_and_serialization_with_many_types1(): original = { 'anything': ['a', 'b', 'c'], 'i': 5, 's': 'test', 'complex_allof': { 'name': 'john', 'ssid': '123' }, 'array': [10, 7], 'any': [{ 'name': 'john', 'ssid': '123' }], 'embedded': { 'a1': 8, 'a2': 0.5 }, 'people': [{ 'name': 'john', 'ssid': '123' }], 'simplestruct': { 'name': 'danny' }, 'array_of_one_of': [{ 'a1': 8, 'a2': 0.5 }, 0.5, 4, { 'name': 'john', 'ssid': '123' }], 'all': 5, 'enum': 3 } deserialized: Example = deserialize_structure(Example, original) deserialized.anything = Person(name="abc", ssid="123123123123123123") serialized = serialize(deserialized) original['anything'] = {'name': 'abc', 'ssid': '123123123123123123'} assert serialized == original
def test_successful_deserialization_and_serialization_with_many_types(): original = { 'anything': ['a', 'b', 'c'], 'i': 5, 's': 'test', 'complex_allof': { 'name': 'john', 'ssid': '123' }, 'array': [10, 7], 'any': [{ 'name': 'john', 'ssid': '123' }], 'embedded': { 'a1': 8, 'a2': 0.5 }, 'people': [{ 'name': 'john', 'ssid': '123' }], 'simplestruct': { 'name': 'danny' }, 'array_of_one_of': [{ 'a1': 8, 'a2': 0.5 }, 0.5, 4, { 'name': 'john', 'ssid': '123' }], 'all': 5, 'enum': 3 } serialized = serialize(deserialize_structure(Example, original)) sorted_serialized = OrderedDict(sorted(serialized.items())) sorted_original = OrderedDict(sorted(original.items())) assert sorted_serialized == sorted_original
def test_successful_deserialization_with_many_types(): source = { 'i': 5, 's': 'test', 'array': [10, 7], 'embedded': { 'a1': 8, 'a2': 0.5 }, 'simplestruct': { 'name': 'danny' }, 'all': 5, 'enum': 3 } example = deserialize_structure(Example, source) result = serialize(example) assert result == source
def test_serialize_with_deep_mapper_camel_case(): class Foo(Structure): a = String i_num = Integer c_d = Integer class Bar(Structure): foo_bar = Foo array_one = Array class Example(Structure): bar = Bar number = Integer example = Example(number=1, bar=Bar(foo_bar=Foo(a="string", i_num=5, c_d=2), array_one=[1, 2])) mapper = { 'bar._mapper': { 'foo_bar._mapper': { "c_d": "cccc", "i_num": FunctionCall(func=lambda x: x * 2) } } } serialized = serialize(example, mapper=mapper, camel_case_convert=True) assert serialized == \ { "number": 1, "bar": { "fooBar": { "a": "string", "iNum": 10, "cccc": 2 }, "arrayOne": [1, 2] } }