import logging import pytest from core.concept import Concept, ConceptParts from sheerkapickle import tags from sheerkapickle.SheerkaPickler import SheerkaPickler from sheerkapickle.SheerkaUnpickler import SheerkaUnpickler from tests.TestUsingFileBasedSheerka import TestUsingFileBasedSheerka class Obj: def __init__(self, a, b, c): self.a = a self.b = b self.c = c def __eq__(self, other): if id(self) == id(other): return True if not isinstance(other, Obj): return False return self.a == other.a and self.b == other.b and self.c == other.c def __hash__(self): return hash((self.a, self.b, self.c)) class TestSheerkaPickler(TestUsingFileBasedSheerka): @pytest.mark.parametrize("obj, expected", [ (1, 1), (3.14, 3.14), ("a string", "a string"), (True, True), (None, None), ([1, 3.14, "a string"], [1, 3.14, "a string"]), ((1, 3.14, "a string"), {tags.TUPLE: [1, 3.14, "a string"]}), ({1}, {tags.SET: [1]}), ({"a": "a", "b": 3.14, "c": True}, {"a": "a", "b": 3.14, "c": True}), ({1: "a", 2: 3.14, 3: True}, {1: "a", 2: 3.14, 3: True}), ([1, [3.14, "a string"]], [1, [3.14, "a string"]]), ([1, (3.14, "a string")], [1, {tags.TUPLE: [3.14, "a string"]}]), ([], []), (ConceptParts.BODY, {tags.ENUM: "core.concept.ConceptParts.BODY"}), ]) def test_i_can_flatten_and_restore_primitives(self, obj, expected): sheerka = self.get_sheerka() flatten = SheerkaPickler(sheerka).flatten(obj) assert flatten == expected decoded = SheerkaUnpickler(sheerka).restore(flatten) assert decoded == obj def test_i_can_flatten_and_restore_instances(self): sheerka = self.get_sheerka() obj1 = Obj(1, "b", True) obj2 = Obj(3.14, ("a", "b"), obj1) flatten = SheerkaPickler(sheerka).flatten(obj2) assert flatten == {'_sheerka/obj': 'tests.sheerkapickle.test_SheerkaPickler.Obj', 'a': 3.14, 'b': {'_sheerka/tuple': ['a', 'b']}, 'c': {'_sheerka/obj': 'tests.sheerkapickle.test_SheerkaPickler.Obj', 'a': 1, 'b': 'b', 'c': True}} decoded = SheerkaUnpickler(sheerka).restore(flatten) assert decoded == obj2 def test_i_can_manage_circular_reference(self): sheerka = self.get_sheerka() obj1 = Obj(1, "b", True) obj1.c = obj1 flatten = SheerkaPickler(sheerka).flatten(obj1) assert flatten == {'_sheerka/obj': 'tests.sheerkapickle.test_SheerkaPickler.Obj', 'a': 1, 'b': 'b', 'c': {'_sheerka/id': 0}} decoded = SheerkaUnpickler(sheerka).restore(flatten) assert decoded.a == obj1.a assert decoded.b == obj1.b assert decoded.c == decoded def test_i_can_flatten_obj_with_new_props(self): sheerka = self.get_sheerka() obj = Obj(1, "b", True) obj.z = "new prop" flatten = SheerkaPickler(sheerka).flatten(obj) assert flatten == {'_sheerka/obj': 'tests.sheerkapickle.test_SheerkaPickler.Obj', 'a': 1, 'b': 'b', 'c': True, 'z': "new prop"} decoded = SheerkaUnpickler(sheerka).restore(flatten) assert decoded == obj @pytest.mark.parametrize("obj, expected", [ ({None: "a"}, {'null': "a"}), ({ConceptParts.BODY: "a"}, {'core.concept.ConceptParts.BODY': 'a'}), ({(1, 2): "a"}, {(1, 2): "a"}), ]) def test_i_can_manage_specific_keys_in_dictionaries(self, obj, expected): sheerka = self.get_sheerka() flatten = SheerkaPickler(sheerka).flatten(obj) assert flatten == expected decoded = SheerkaUnpickler(sheerka).restore(flatten) assert decoded == obj def test_i_can_use_concept_as_dictionary_key(self): sheerka = self.get_sheerka() concept = Concept("foo").init_key() sheerka.set_id_if_needed(concept, False) sheerka.add_in_cache(concept) obj = {concept: "a"} flatten = SheerkaPickler(sheerka).flatten(obj) assert flatten == {'c:foo|1001:': 'a'} decoded = SheerkaUnpickler(sheerka).restore(flatten) assert decoded == obj def test_i_can_manage_references(self): sheerka = self.get_sheerka() foo = Obj("foo", "bar", "baz") obj = [ConceptParts.BODY, foo, ConceptParts.WHERE, ConceptParts.BODY, foo] flatten = SheerkaPickler(sheerka).flatten(obj) assert flatten == [{'_sheerka/enum': 'core.concept.ConceptParts.BODY'}, {'_sheerka/obj': 'tests.sheerkapickle.test_SheerkaPickler.Obj', 'a': 'foo', 'b': 'bar', 'c': 'baz'}, {'_sheerka/enum': 'core.concept.ConceptParts.WHERE'}, {'_sheerka/id': 0}, {'_sheerka/id': 1}] decoded = SheerkaUnpickler(sheerka).restore(flatten) assert decoded == obj def test_i_do_not_encode_logger(self): sheerka = self.get_sheerka() logger = logging.getLogger("log_name") logger2 = logging.getLogger("log_name2") obj = Obj("foo", logger, {"a": logger, "b": logger2}) flatten = SheerkaPickler(sheerka).flatten(obj) decoded = SheerkaUnpickler(sheerka).restore(flatten) assert decoded == Obj("foo", None, {"a": None, "b": None})