import pytest from core.builtin_concepts import BuiltinConcepts from core.concept import Concept from core.sheerka.services.SheerkaIsAManager import SheerkaIsAManager from tests.TestUsingFileBasedSheerka import TestUsingFileBasedSheerka from tests.TestUsingMemoryBasedSheerka import TestUsingMemoryBasedSheerka class TestSheerkaIsAManager(TestUsingMemoryBasedSheerka): def test_i_can_add_a_concept_to_a_set(self): sheerka, context, foo, group = self.init_concepts( Concept("foo"), Concept("group"), cache_only=False ) res = sheerka.add_concept_to_set(context, foo, group) assert res.status assert sheerka.isinstance(res.body, BuiltinConcepts.SUCCESS) group_elements = sheerka.om.get(SheerkaIsAManager.CONCEPTS_GROUPS_ENTRY, group.id) assert group_elements == {foo.id} # it can be persisted sheerka.om.commit(context) assert sheerka.om.current_sdp().get(SheerkaIsAManager.CONCEPTS_GROUPS_ENTRY, group.id) == {foo.id} def test_i_cannot_add_the_same_concept_twice_in_a_set(self): sheerka, context, foo, group = self.init_concepts(Concept("foo"), Concept("group")) sheerka.add_concept_to_set(context, foo, group) # add again res = sheerka.add_concept_to_set(context, foo, group) assert not res.status assert sheerka.isinstance(res.body, BuiltinConcepts.CONCEPT_ALREADY_IN_SET) assert res.body.body == foo assert res.body.concept_set == group all_entries = sheerka.om.get(SheerkaIsAManager.CONCEPTS_GROUPS_ENTRY, group.id) assert all_entries == {foo.id} def test_i_can_have_multiple_groups(self): sheerka, context, foo, bar, baz, group1, group2 = self.init_concepts( Concept("foo"), Concept("bar"), Concept("baz"), Concept("group1"), Concept("group2"), cache_only=False ) assert sheerka.add_concept_to_set(context, foo, group1).status assert sheerka.add_concept_to_set(context, bar, group1).status assert sheerka.add_concept_to_set(context, bar, group2).status assert sheerka.add_concept_to_set(context, baz, group2).status assert sheerka.om.get(SheerkaIsAManager.CONCEPTS_GROUPS_ENTRY, group1.id) == {foo.id, bar.id} assert sheerka.om.get(SheerkaIsAManager.CONCEPTS_GROUPS_ENTRY, group2.id) == {baz.id, bar.id} # I can save in db sheerka.om.commit(context) assert sheerka.om.current_sdp().get(SheerkaIsAManager.CONCEPTS_GROUPS_ENTRY) == { '1004': {'1001', '1002'}, '1005': {'1002', '1003'} } def test_i_get_elements_from_a_set(self): sheerka, context, one, two, three, number = self.init_concepts( Concept("one"), Concept("two"), Concept("three"), Concept("number")) for c in [one, two, three]: sheerka.add_concept_to_set(context, c, number) elements = sheerka.get_set_elements(context, number) assert set(elements) == {one, two, three} def test_i_cannot_get_elements_if_not_a_set(self): sheerka, context, one = self.init_concepts(Concept("one")) error = sheerka.get_set_elements(context, one) assert sheerka.isinstance(error, BuiltinConcepts.NOT_A_SET) assert error.body == one def test_isa_and_isa_group(self): sheerka, context, group, foo = self.init_concepts(Concept("group"), Concept("foo")) assert not sheerka.isaset(context, group) assert not sheerka.isinset(foo, group) context = self.get_context(sheerka) # another context ? sheerka.add_concept_to_set(context, foo, group) assert sheerka.isaset(context, group) assert sheerka.isinset(foo, group) def test_i_can_define_a_group_from_another_group(self): sheerka, context, foo, bar, group1, group2 = self.init_concepts( "foo", "bar", "group1", Concept("group2", body="group1")) service = sheerka.services[SheerkaIsAManager.NAME] service.add_concepts_to_set(context, [foo, bar], group1) assert sheerka.isaset(context, group2) assert set(sheerka.get_set_elements(context, group2)) == {foo, bar} def test_i_can_define_subset_of_another_group(self): sheerka, context, one, two, three, four, five, number, sub_number = self.init_concepts( Concept("one", body="1"), Concept("two", body="2"), Concept("three", body="3"), Concept("four", body="4"), Concept("five", body="5"), Concept("number"), Concept("sub_number", body="number", where="number < 4") ) service = sheerka.services[SheerkaIsAManager.NAME] service.add_concepts_to_set(context, [one, two, three, four, five], number) assert sheerka.isaset(context, sub_number) assert set(sheerka.get_set_elements(context, sub_number)) == {one, two, three} def test_i_can_define_subset_of_subset(self): sheerka, context, one, two, three, four, five, number, sub_number, sub_sub_number = self.init_concepts( Concept("one", body="1"), Concept("two", body="2"), Concept("three", body="3"), Concept("four", body="4"), Concept("five", body="5"), Concept("number"), Concept("sub_number", body="number", where="number < 4"), Concept("sub_sub_number", body="sub_number", where="sub_number > 2") ) service = sheerka.services[SheerkaIsAManager.NAME] service.add_concepts_to_set(context, [one, two, three, four, five], number) assert sheerka.isaset(context, sub_sub_number) assert set(sheerka.get_set_elements(context, sub_sub_number)) == {three} def test_i_can_define_subset_of_another_set_when_some_concept_do_not_have_a_defined_body(self): """ Example def concept unit from number where number <10 It implies that all elements in number have a (numeric) body What if its not the case ? :return: """ sheerka, context, one, two, three, four, five, number, sub_number = self.init_concepts( Concept("one", body="1"), Concept("two"), Concept("three", body="3"), Concept("four"), Concept("five", body="5"), Concept("number"), Concept("sub_number", body="number", where="number < 4") ) service = sheerka.services[SheerkaIsAManager.NAME] service.add_concepts_to_set(context, [one, two, three, four, five], number) assert sheerka.isaset(context, sub_number) assert set(sheerka.get_set_elements(context, sub_number)) == {one, three} def test_i_can_define_subset_of_another_set_when_some_concept_are_bnf(self): """ Other case: twenties isa number, but its body is a source code, not a constant numeric number is it included ? :return: """ sheerka, context, one, two, twenty, twenties, number, sub_number = self.init_concepts( Concept("one", body="1"), Concept("two", body="2"), Concept("twenty", body="20"), Concept("twenties", definition="twenty (one|two)=unit", body="twenty + unit"), Concept("number"), Concept("sub_number", body="number", where="number >= 20") ) service = sheerka.services[SheerkaIsAManager.NAME] service.add_concepts_to_set(context, [one, two, twenty, twenties], number) assert sheerka.isaset(context, sub_number) assert sheerka.get_set_elements(context, sub_number) == [twenty] # what is expected ? def test_bnf_elements_can_be_part_of_a_set(self): """ The purpose of this test is def concept twenties from bnf ... twenties isa number assert twenty two isa number We want that all elements of the twenties are number :return: """ sheerka, context, one, two, twenty, twenties, number = self.init_test().with_concepts( Concept("one", body="1"), Concept("two", body="2"), Concept("twenty", body="20"), Concept("twenties", definition="twenty (one|two)=unit", body="twenty + unit").def_var("unit"), Concept("number"), create_new=True).unpack() service = sheerka.services[SheerkaIsAManager.NAME] service.add_concepts_to_set(context, [one, two, twenty, twenties], number) assert sheerka.isinset(twenties, number) res = sheerka.evaluate_user_input("twenty one", "") assert len(res) == 1 assert res[0].status assert sheerka.isinset(res[0].body, number) def test_a_concept_can_be_in_multiple_sets(self): sheerka, context, foo, all_foo, all_bar = self.init_test().with_concepts( Concept("foo"), Concept("all_foo"), Concept("all_bar"), create_new=True).unpack() foo = sheerka.new(foo.key) # new instance sheerka.set_isa(context, foo, all_foo) foo = sheerka.new(foo.key) # new instance sheerka.set_isa(context, foo, all_bar) assert foo.get_prop(BuiltinConcepts.ISA) == {all_foo, all_bar} assert sheerka.isa(foo, all_foo) assert sheerka.isa(foo, all_bar) assert sheerka.isinset(foo, all_foo) assert sheerka.isinset(foo, all_bar) assert sheerka.isaset(context, all_foo) assert sheerka.isaset(context, all_bar) def test_i_can_manage_isa_transitivity(self): """ if foo isa bar and bar isa baz, then foo isa baz :return: """ sheerka, context, foo, bar, baz = self.init_concepts( Concept("foo"), Concept("bar"), Concept("baz"), ) sheerka.set_isa(context, sheerka.new("foo"), bar) sheerka.set_isa(context, sheerka.new("bar"), baz) assert sheerka.isa(sheerka.new("foo"), bar) assert sheerka.isa(sheerka.new("bar"), baz) assert sheerka.isa(sheerka.new("foo"), baz) def test_i_cannot_manage_isa_transitivity_when_using_body(self): sheerka, context, one, another_one, number = self.init_concepts( "one", Concept("another one", body="one"), "number" ) sheerka.set_isa(context, sheerka.new("one"), number) assert sheerka.isa(sheerka.new("one"), number) # sanity assert not sheerka.isa(another_one, number) # Correct this misbehaviour when BuiltinConcepts.IS is implemented def test_concepts_in_group_cache_is_updated(self): sheerka, context, one, two, number = self.init_concepts("one", "two", "number") sheerka.set_isa(context, sheerka.new("one"), number) elements = sheerka.get_set_elements(context, number) assert [c.id for c in elements] == [one.id] concepts_in_cache = sheerka.om.get(SheerkaIsAManager.CONCEPTS_IN_GROUPS_ENTRY, number.id) assert [c.id for c in concepts_in_cache] == [one.id] # pretend that number has been updated in sheerka.concepts_grammar sheerka.concepts_grammars.put(number.id, "some parsing expression with 'one' only") # add another element to number sheerka.set_isa(context, sheerka.new("two"), number) elements = sheerka.get_set_elements(context, number) assert {c.id for c in elements} == {one.id, two.id} concepts_in_cache = sheerka.om.get(SheerkaIsAManager.CONCEPTS_IN_GROUPS_ENTRY, number.id) assert {c.id for c in concepts_in_cache} == {one.id, two.id} # make sure the bnf definition is also updated assert number.id not in sheerka.concepts_grammars def test_i_can_get_and_set_isa_when_multiple_ontology_layers(self): sheerka, context, foo, group1, group2 = self.init_concepts( Concept("foo"), Concept("group1"), Concept("group2"), cache_only=False ) sheerka.set_isa(context, foo, group1) assert sheerka.isaset(context, group1) assert sheerka.isinset(foo, group1) assert sheerka.isa(foo, group1) sheerka.push_ontology(context, "new ontology") assert sheerka.isaset(context, group1) assert sheerka.isinset(foo, group1) assert sheerka.isa(foo, group1) assert not sheerka.isaset(context, group2) assert not sheerka.isinset(foo, group2) assert not sheerka.isa(foo, group2) sheerka.set_isa(context, foo, group2) assert sheerka.isaset(context, group1) assert sheerka.isinset(foo, group1) assert sheerka.isa(foo, group1) assert sheerka.isaset(context, group2) assert sheerka.isinset(foo, group2) assert sheerka.isa(foo, group2) # I can revert back sheerka.pop_ontology(context) assert sheerka.isaset(context, group1) assert sheerka.isinset(foo, group1) assert sheerka.isa(foo, group1) assert not sheerka.isaset(context, group2) assert not sheerka.isinset(foo, group2) foo = sheerka.get_by_id(foo.id) assert not sheerka.isa(foo, group2) class TestSheerkaSetsManagerUsingFileBasedSheerka(TestUsingFileBasedSheerka): def test_i_can_add_concept_to_set_and_retrieve_it_in_another_session(self): sheerka, context, foo, bar, group = self.init_test().with_concepts(Concept("foo"), Concept("bar"), Concept("group"), create_new=True).unpack() assert sheerka.add_concept_to_set(context, foo, group).status sheerka.om.commit(context) sheerka = self.get_sheerka(reset_attrs=False) # another session context = self.get_context(sheerka) assert sheerka.add_concept_to_set(context, bar, group).status # I can get the elements assert set(sheerka.get_set_elements(context, group)) == {foo, bar} sheerka.om.commit(context) # save in db all_entries = sheerka.om.current_sdp().get(SheerkaIsAManager.CONCEPTS_GROUPS_ENTRY) # check the db assert all_entries == { group.id: {foo.id, bar.id} } # I can also add a group another elements sheerka = self.get_sheerka(reset_attrs=False) context = self.get_context(sheerka) foo3 = Concept("foo3") foo4 = Concept("foo4") for c in [foo3, foo4]: sheerka.create_new_concept(context, c) sets_handler = sheerka.services[SheerkaIsAManager.NAME] res = sets_handler.add_concepts_to_set(context, (foo3, foo4), group) assert res.status # I can get the elements assert set(sheerka.get_set_elements(context, group)) == {foo, bar, foo3, foo4} sheerka.om.commit(context) # save in db all_entries = sheerka.om.current_sdp().get(SheerkaIsAManager.CONCEPTS_GROUPS_ENTRY) # check the db assert all_entries == { group.id: {foo.id, bar.id, foo3.id, foo4.id} } def test_i_can_set_isa(self): sheerka, context, foo, bar, group = self.init_test().with_concepts("foo", "bar", "group", ).unpack() # nothing was previously in ISA foo = sheerka.new(foo.key) assert BuiltinConcepts.ISA not in foo.get_metadata().props res = sheerka.set_isa(context, foo, group) assert res.status sheerka.om.commit(context) sheerka = self.get_sheerka(reset_attrs=False) assert foo.get_prop(BuiltinConcepts.ISA) == {group} assert sheerka.isa(foo, group) assert sheerka.isinset(foo, group) assert sheerka.isaset(context, group) # I can do the same for bar sheerka = self.get_sheerka(reset_attrs=False) res = sheerka.set_isa(context, bar, group) assert res.status assert bar.get_prop(BuiltinConcepts.ISA) == {group} assert sheerka.isa(bar, group) assert sheerka.isinset(bar, group) assert sheerka.isaset(context, group) sheerka.om.commit(context) # they are both in the same group sheerka = self.get_sheerka(reset_attrs=False) all_entries = sheerka.om.current_sdp().get(SheerkaIsAManager.CONCEPTS_GROUPS_ENTRY) assert all_entries == { group.id: {foo.id, bar.id} } elements = sheerka.get_set_elements(context, group) assert set(elements) == {foo, bar}