Implemented a first and basic version of a Rete rule engine
This commit is contained in:
@@ -65,9 +65,9 @@ class TestSheerkaGreaterThanManager(TestUsingMemoryBasedSheerka):
|
||||
assert in_db == [ComparisonObj(context.event.get_digest(), "prop_name", two.str_id, one.str_id, ">", "#")]
|
||||
|
||||
def test_i_can_add_is_greater_than_for_rules(self):
|
||||
sheerka, context, r1, r2 = self.init_test(cache_only=False).with_rules(("True", "true"),
|
||||
("False", "false"),
|
||||
compile_rule=False).unpack()
|
||||
sheerka, context, r1, r2 = self.init_test(cache_only=False).with_format_rules(("True", "true"),
|
||||
("False", "false"),
|
||||
compile_rule=False).unpack()
|
||||
|
||||
service = sheerka.services[SheerkaComparisonManager.NAME]
|
||||
|
||||
@@ -106,10 +106,10 @@ class TestSheerkaGreaterThanManager(TestUsingMemoryBasedSheerka):
|
||||
assert in_db == [ComparisonObj(context.event.get_digest(), "prop_name", one.str_id, two.str_id, "<", "#")]
|
||||
|
||||
def test_i_can_add_is_less_than_for_rules(self):
|
||||
sheerka, context, r1, r2 = self.init_test(cache_only=False).with_rules(("True", "true"),
|
||||
("False", "false"),
|
||||
compile_rule=False,
|
||||
create_new=True).unpack()
|
||||
sheerka, context, r1, r2 = self.init_test(cache_only=False).with_format_rules(("True", "true"),
|
||||
("False", "false"),
|
||||
compile_rule=False,
|
||||
create_new=True).unpack()
|
||||
|
||||
service = sheerka.services[SheerkaComparisonManager.NAME]
|
||||
|
||||
@@ -213,7 +213,7 @@ class TestSheerkaGreaterThanManager(TestUsingMemoryBasedSheerka):
|
||||
assert sheerka.om.get(SheerkaComparisonManager.RESOLVED_COMPARISON_ENTRY, "prop_name|#") == expected_weights2
|
||||
|
||||
# I can retrieve the previous values
|
||||
sheerka.pop_ontology()
|
||||
sheerka.pop_ontology(context)
|
||||
assert sheerka.om.get(SheerkaComparisonManager.COMPARISON_ENTRY, "prop_name|#") == expected_in_cache
|
||||
assert sheerka.om.get(SheerkaComparisonManager.RESOLVED_COMPARISON_ENTRY, "prop_name|#") == expected_weights
|
||||
|
||||
@@ -544,9 +544,9 @@ class TestSheerkaGreaterThanManager(TestUsingMemoryBasedSheerka):
|
||||
assert event_received
|
||||
|
||||
def test_an_event_is_fired_when_modifying_rule_precedence(self):
|
||||
sheerka, context, r1, r2 = self.init_test(cache_only=False).with_rules(("True", "true"),
|
||||
("False", "false"),
|
||||
compile_rule=False).unpack()
|
||||
sheerka, context, r1, r2 = self.init_test(cache_only=False).with_format_rules(("True", "true"),
|
||||
("False", "false"),
|
||||
compile_rule=False).unpack()
|
||||
foo = Concept("foo")
|
||||
event_received = False
|
||||
sheerka.om.clear(SheerkaComparisonManager.COMPARISON_ENTRY)
|
||||
|
||||
@@ -563,7 +563,7 @@ class TestSheerkaConceptManager(TestUsingMemoryBasedSheerka):
|
||||
assert updated.get_metadata().variables == [("a", None), ("c", "value")]
|
||||
assert updated.get_metadata().props == {BuiltinConcepts.ISA: {"bar"}}
|
||||
|
||||
sheerka.pop_ontology()
|
||||
sheerka.pop_ontology(context)
|
||||
|
||||
def test_i_cannot_modify_without_any_modification(self):
|
||||
sheerka, context, foo = self.init_concepts("foo")
|
||||
@@ -726,7 +726,7 @@ class TestSheerkaConceptManager(TestUsingMemoryBasedSheerka):
|
||||
assert not res.status
|
||||
assert sheerka.isinstance(res.body, BuiltinConcepts.CONCEPT_ALREADY_DEFINED)
|
||||
|
||||
sheerka.pop_ontology()
|
||||
sheerka.pop_ontology(context)
|
||||
# But I can if I remove the layer
|
||||
res = sheerka.create_new_concept(context, Concept("bar"))
|
||||
assert res.status
|
||||
|
||||
@@ -1,12 +1,11 @@
|
||||
import pytest
|
||||
|
||||
from core.builtin_concepts import BuiltinConcepts
|
||||
from core.concept import Concept
|
||||
from core.global_symbols import NotInit, NotFound
|
||||
from core.sheerka.ExecutionContext import ExecutionContext
|
||||
from core.sheerka.services.SheerkaDebugManager import SheerkaDebugManager, DebugItem, ConceptDebugObj
|
||||
from parsers.PythonParser import PythonNode
|
||||
from sdp.sheerkaDataProvider import Event
|
||||
|
||||
from tests.TestUsingMemoryBasedSheerka import TestUsingMemoryBasedSheerka
|
||||
|
||||
|
||||
@@ -21,220 +20,12 @@ class DummyObj:
|
||||
|
||||
class TestSheerkaDebugManager(TestUsingMemoryBasedSheerka):
|
||||
|
||||
def test_i_can_activate_debug(self):
|
||||
sheerka, context = self.init_concepts()
|
||||
return_value_id = 0
|
||||
|
||||
sheerka.set_debug(context, True)
|
||||
assert sheerka.debug_activated()
|
||||
|
||||
sheerka.set_debug(context, False)
|
||||
assert not sheerka.debug_activated()
|
||||
|
||||
def test_when_debug_mode_is_activated_context_are_in_debug_mode(self):
|
||||
sheerka = self.get_sheerka()
|
||||
ExecutionContext.ids.clear()
|
||||
root_context = self.get_context(sheerka)
|
||||
|
||||
sheerka.set_debug(root_context, True)
|
||||
|
||||
context = root_context.push(BuiltinConcepts.NOP, None) # sub_context.id = 1
|
||||
sub_context = context.push(BuiltinConcepts.NOP, None) # sub_sub_context.parent = 1
|
||||
sub_context2 = context.push(BuiltinConcepts.NOP, None) # sub_sub_context2.parent = 1
|
||||
sub_sub_context = sub_context.push(BuiltinConcepts.NOP, None) # is a child
|
||||
|
||||
assert context.id == 1
|
||||
assert context.debug_enabled
|
||||
assert sub_context.debug_enabled
|
||||
assert sub_context2.debug_enabled
|
||||
assert sub_sub_context.debug_enabled
|
||||
assert not root_context.debug_enabled
|
||||
|
||||
def test_i_can_activate_debug_for_new_context(self):
|
||||
sheerka = self.get_sheerka()
|
||||
ExecutionContext.ids.clear()
|
||||
root_context = self.get_context(sheerka)
|
||||
|
||||
sheerka.set_debug(root_context, True)
|
||||
sheerka.set_explicit(root_context, True)
|
||||
sheerka.activate_debug_for(root_context, 1)
|
||||
|
||||
context = ExecutionContext("test", Event(), sheerka, BuiltinConcepts.TESTING, None) # context.id = 1
|
||||
assert context.debug_enabled
|
||||
|
||||
def test_i_can_activate_debug_for_new_context_2(self):
|
||||
"""
|
||||
This time children is also requested
|
||||
:return:
|
||||
"""
|
||||
sheerka = self.get_sheerka()
|
||||
ExecutionContext.ids.clear()
|
||||
root_context = self.get_context(sheerka)
|
||||
|
||||
sheerka.set_debug(root_context, True)
|
||||
sheerka.set_explicit(root_context, True)
|
||||
sheerka.activate_debug_for(root_context, 1, children=True)
|
||||
|
||||
context = ExecutionContext("test", Event(), sheerka, BuiltinConcepts.TESTING, None) # context.id = 1
|
||||
assert context.debug_enabled
|
||||
|
||||
def test_i_can_activate_debug_for_a_context_using_push(self):
|
||||
sheerka = self.get_sheerka()
|
||||
ExecutionContext.ids.clear()
|
||||
root_context = self.get_context(sheerka)
|
||||
service = sheerka.services[SheerkaDebugManager.NAME]
|
||||
|
||||
sheerka.set_debug(root_context, True)
|
||||
sheerka.set_explicit(root_context, True)
|
||||
sheerka.activate_debug_for(root_context, 1)
|
||||
|
||||
context = root_context.push(BuiltinConcepts.NOP, None) # sub_context.id = 1
|
||||
sub_context = context.push(BuiltinConcepts.NOP, None) # sub_sub_context.parent = 1
|
||||
|
||||
assert context.id == 1
|
||||
assert 1 in service.context_cache
|
||||
assert context.debug_enabled
|
||||
assert not sub_context.debug_enabled
|
||||
assert not root_context.debug_enabled
|
||||
|
||||
def test_global_debug_must_be_activated_to_activate_context_debug(self):
|
||||
sheerka = self.get_sheerka()
|
||||
ExecutionContext.ids.clear()
|
||||
root_context = self.get_context(sheerka)
|
||||
service = sheerka.services[SheerkaDebugManager.NAME]
|
||||
|
||||
sheerka.set_debug(root_context, False)
|
||||
sheerka.activate_debug_for(root_context, 1)
|
||||
|
||||
context = root_context.push(BuiltinConcepts.NOP, None) # sub_context.id = 1
|
||||
|
||||
assert context.id == 1
|
||||
assert 1 in service.context_cache
|
||||
assert not context.debug_enabled
|
||||
|
||||
def test_i_can_activate_debug_for_sub_children(self):
|
||||
sheerka = self.get_sheerka()
|
||||
ExecutionContext.ids.clear()
|
||||
root_context = self.get_context(sheerka)
|
||||
service = sheerka.services[SheerkaDebugManager.NAME]
|
||||
|
||||
sheerka.set_debug(root_context, True)
|
||||
sheerka.set_explicit(root_context, True)
|
||||
sheerka.activate_debug_for(root_context, 1, children=True)
|
||||
|
||||
context = root_context.push(BuiltinConcepts.NOP, None) # sub_context.id = 1
|
||||
sub_context = context.push(BuiltinConcepts.NOP, None) # sub_sub_context.parent = 1
|
||||
sub_context2 = context.push(BuiltinConcepts.NOP, None) # sub_sub_context2.parent = 1
|
||||
sub_sub_context = sub_context.push(BuiltinConcepts.NOP, None) # is a child
|
||||
|
||||
assert context.id == 1
|
||||
assert 1 in service.context_cache
|
||||
assert "1+" in service.context_cache
|
||||
assert context.debug_enabled
|
||||
assert sub_context.debug_enabled
|
||||
assert sub_context2.debug_enabled
|
||||
assert sub_sub_context.debug_enabled
|
||||
assert not root_context.debug_enabled
|
||||
|
||||
def test_i_can_deactivate_debug_for_a_context(self):
|
||||
sheerka = self.get_sheerka()
|
||||
ExecutionContext.ids.clear()
|
||||
root_context = self.get_context(sheerka)
|
||||
service = sheerka.services[SheerkaDebugManager.NAME]
|
||||
|
||||
sheerka.set_debug(root_context, True)
|
||||
sheerka.set_explicit(root_context, True)
|
||||
sheerka.activate_debug_for(root_context, 1)
|
||||
sheerka.deactivate_debug_for(root_context, 1)
|
||||
|
||||
context = root_context.push(BuiltinConcepts.NOP, None)
|
||||
|
||||
assert context.id == 1
|
||||
assert 1 not in service.context_cache
|
||||
assert not context.debug_enabled
|
||||
|
||||
def test_i_can_deactivate_context_but_not_children(self):
|
||||
sheerka = self.get_sheerka()
|
||||
ExecutionContext.ids.clear()
|
||||
root_context = self.get_context(sheerka)
|
||||
service = sheerka.services[SheerkaDebugManager.NAME]
|
||||
|
||||
sheerka.set_debug(root_context, True)
|
||||
sheerka.set_explicit(root_context, True)
|
||||
sheerka.activate_debug_for(root_context, 1, True)
|
||||
sheerka.deactivate_debug_for(root_context, 1)
|
||||
|
||||
context = root_context.push(BuiltinConcepts.NOP, None) # sub_context.id = 1
|
||||
sub_context = context.push(BuiltinConcepts.NOP, None) # sub_sub_context.parent = 1
|
||||
sub_context2 = context.push(BuiltinConcepts.NOP, None) # sub_sub_context2.parent = 1
|
||||
sub_sub_context = sub_context.push(BuiltinConcepts.NOP, None) # is a child
|
||||
|
||||
assert context.id == 1
|
||||
assert 1 not in service.context_cache
|
||||
assert "1+" in service.context_cache
|
||||
assert not context.debug_enabled
|
||||
assert sub_context.debug_enabled
|
||||
assert sub_context2.debug_enabled
|
||||
assert sub_sub_context.debug_enabled
|
||||
|
||||
def test_i_can_deactivate_context_and_children(self):
|
||||
sheerka = self.get_sheerka()
|
||||
ExecutionContext.ids.clear()
|
||||
root_context = self.get_context(sheerka)
|
||||
service = sheerka.services[SheerkaDebugManager.NAME]
|
||||
|
||||
sheerka.set_debug(root_context, True)
|
||||
sheerka.set_explicit(root_context, True)
|
||||
sheerka.activate_debug_for(root_context, 1)
|
||||
sheerka.deactivate_debug_for(root_context, 1, children=True)
|
||||
|
||||
context = root_context.push(BuiltinConcepts.NOP, None) # sub_context.id = 1
|
||||
sub_context = context.push(BuiltinConcepts.NOP, None) # sub_sub_context.parent = 1
|
||||
sub_context2 = context.push(BuiltinConcepts.NOP, None) # sub_sub_context2.parent = 1
|
||||
sub_sub_context = sub_context.push(BuiltinConcepts.NOP, None) # is a child
|
||||
|
||||
assert 1 not in service.context_cache
|
||||
assert "1+" not in service.context_cache
|
||||
assert not context.debug_enabled
|
||||
assert not sub_context.debug_enabled
|
||||
assert not sub_context2.debug_enabled
|
||||
assert not sub_sub_context.debug_enabled
|
||||
|
||||
def test_i_can_activate_debug_for_a_variable(self):
|
||||
sheerka, context = self.init_concepts()
|
||||
service = sheerka.services[SheerkaDebugManager.NAME]
|
||||
sheerka.set_debug(context)
|
||||
|
||||
sheerka.activate_debug_for(context, "Out")
|
||||
assert "Out" in service.variable_cache
|
||||
assert sheerka.debug_activated_for("Out")
|
||||
|
||||
sheerka.deactivate_debug_for(context, "Out")
|
||||
assert "Out" not in service.variable_cache
|
||||
assert not sheerka.debug_activated_for("Out")
|
||||
|
||||
def test_i_can_activate_debug_for_sub_children_using_the_simplified_form(self):
|
||||
sheerka = self.get_sheerka()
|
||||
ExecutionContext.ids.clear()
|
||||
root_context = self.get_context(sheerka)
|
||||
service = sheerka.services[SheerkaDebugManager.NAME]
|
||||
|
||||
sheerka.set_debug(root_context, True)
|
||||
sheerka.set_explicit(root_context, True)
|
||||
sheerka.activate_debug_for(root_context, "1+")
|
||||
|
||||
context = root_context.push(BuiltinConcepts.NOP, None) # sub_context.id = 1
|
||||
sub_context = context.push(BuiltinConcepts.NOP, None) # sub_sub_context.parent = 1
|
||||
sub_context2 = context.push(BuiltinConcepts.NOP, None) # sub_sub_context2.parent = 1
|
||||
sub_sub_context = sub_context.push(BuiltinConcepts.NOP, None) # is a child
|
||||
|
||||
assert context.id == 1
|
||||
assert 1 in service.context_cache
|
||||
assert "1+" in service.context_cache
|
||||
assert context.debug_enabled
|
||||
assert sub_context.debug_enabled
|
||||
assert sub_context2.debug_enabled
|
||||
assert sub_sub_context.debug_enabled
|
||||
assert not root_context.debug_enabled
|
||||
@classmethod
|
||||
def setup(cls):
|
||||
sheerka = cls().get_sheerka()
|
||||
cls.return_value_id = sheerka.get_by_key("__RETURN_VALUE").id
|
||||
|
||||
@pytest.mark.parametrize("item_type", [
|
||||
"vars", "rules", "concepts"
|
||||
@@ -631,9 +422,6 @@ class TestSheerkaDebugManager(TestUsingMemoryBasedSheerka):
|
||||
root_context = self.get_context(sheerka)
|
||||
|
||||
sheerka.set_debug(root_context, True)
|
||||
sheerka.set_explicit(root_context, False)
|
||||
sheerka.activate_debug_for(root_context, 1, children=True)
|
||||
sheerka.activate_debug_for(root_context, "SomeVar")
|
||||
sheerka.debug_var(root_context, "service_name.*.var")
|
||||
sheerka.debug_rule(root_context, 1)
|
||||
sheerka.debug_concept(root_context, 1001)
|
||||
@@ -642,9 +430,6 @@ class TestSheerkaDebugManager(TestUsingMemoryBasedSheerka):
|
||||
another_service.initialize_deferred(root_context, True)
|
||||
|
||||
assert another_service.activated
|
||||
assert not another_service.explicit
|
||||
assert another_service.context_cache == {1, "1+"}
|
||||
assert another_service.variable_cache == {"SomeVar"}
|
||||
assert another_service.debug_vars_settings == [
|
||||
DebugItem('var', 'service_name', None, None, False, None, False, True)]
|
||||
assert another_service.debug_rules_settings == [
|
||||
@@ -688,7 +473,7 @@ class TestSheerkaDebugManager(TestUsingMemoryBasedSheerka):
|
||||
python_node = PythonNode("one + 1").init_ast()
|
||||
|
||||
res = sheerka.inspect(context, python_node)
|
||||
assert set(res.body.keys()) == {"#type#", 'ast_', 'ast_str', 'compiled', 'objects', 'source'}
|
||||
assert set(res.body.keys()) == {"#type#", 'ast_', 'ast_str', 'compiled', 'objects', 'source', 'original_source'}
|
||||
|
||||
def test_i_can_inspect_object_specified_attributes(self):
|
||||
sheerka, context = self.init_concepts()
|
||||
@@ -872,7 +657,7 @@ class TestSheerkaDebugManager(TestUsingMemoryBasedSheerka):
|
||||
assert res.body == {
|
||||
'body': concept_debug_obj,
|
||||
'#type#': 'ReturnValueConcept',
|
||||
'id': '43',
|
||||
'id': f'{self.return_value_id}',
|
||||
'key': '__RETURN_VALUE',
|
||||
'name': '__RETURN_VALUE',
|
||||
'parents': [concept_debug_obj],
|
||||
@@ -920,21 +705,18 @@ class TestSheerkaDebugManager(TestUsingMemoryBasedSheerka):
|
||||
sheerka.push_ontology(context, "new ontology")
|
||||
|
||||
service.set_debug(context)
|
||||
service.set_explicit(context)
|
||||
service.debug_var(context, "var_service.var_method.var_name", "1+", 1)
|
||||
service.debug_rule(context, "rule_service.rule_method.rule_name", "2+", 2)
|
||||
service.debug_concept(context, "concept_service.concept_method.concept_name", "3+", 3)
|
||||
|
||||
# sanity check
|
||||
assert service.activated
|
||||
assert service.explicit
|
||||
assert service.debug_vars_settings != []
|
||||
assert service.debug_rules_settings != []
|
||||
assert service.debug_concepts_settings != []
|
||||
|
||||
sheerka.pop_ontology()
|
||||
sheerka.pop_ontology(context)
|
||||
assert not service.activated
|
||||
assert not service.explicit
|
||||
assert service.context_cache == set()
|
||||
assert service.variable_cache == set()
|
||||
assert service.debug_vars_settings == []
|
||||
@@ -946,7 +728,6 @@ class TestSheerkaDebugManager(TestUsingMemoryBasedSheerka):
|
||||
service = sheerka.services[SheerkaDebugManager.NAME]
|
||||
|
||||
service.set_debug(context)
|
||||
service.set_explicit(context)
|
||||
service.debug_var(context, "v_service.v_method.v_name", "1+", 1)
|
||||
service.debug_rule(context, "r_service.r_method.r_name", "2+", 2)
|
||||
service.debug_concept(context, "c_serv.c_method.c_name", "3+", 3)
|
||||
@@ -955,7 +736,6 @@ class TestSheerkaDebugManager(TestUsingMemoryBasedSheerka):
|
||||
|
||||
# modify the state
|
||||
service.set_debug(context, False)
|
||||
service.set_explicit(context, False)
|
||||
service.debug_var(context, "var_service2.var_method2.var_name2", "11+", 11)
|
||||
service.debug_rule(context, "rule_service2.rule_method2.rule_name2", "22+", 22)
|
||||
service.debug_concept(context, "concept_service2.concept_method2.concept_name2", "33+", 33)
|
||||
@@ -967,10 +747,8 @@ class TestSheerkaDebugManager(TestUsingMemoryBasedSheerka):
|
||||
assert len(service.debug_rules_settings) == 2
|
||||
assert len(service.debug_concepts_settings) == 2
|
||||
|
||||
sheerka.pop_ontology()
|
||||
sheerka.pop_ontology(context)
|
||||
assert service.activated
|
||||
assert service.explicit
|
||||
assert service.debug_vars_settings == [DebugItem("v_name", "v_service", "v_method", 1, True, 1, False, True)]
|
||||
assert service.debug_rules_settings == [DebugItem("r_name", "r_service", "r_method", 2, True, 2, False, True)]
|
||||
assert service.debug_concepts_settings == [DebugItem("c_name", "c_serv", "c_method", 3, True, 3, False, True)]
|
||||
|
||||
|
||||
@@ -1,15 +1,22 @@
|
||||
import operator
|
||||
|
||||
from core.concept import Concept
|
||||
from core.rule import Rule
|
||||
from core.sheerka.services.SheerkaEvaluateRules import SheerkaEvaluateRules, LOW_PRIORITY_RULES, DISABLED_RULES
|
||||
import pytest
|
||||
|
||||
from core.builtin_concepts_ids import BuiltinConcepts
|
||||
from core.concept import Concept, DEFINITION_TYPE_DEF
|
||||
from core.rule import Rule, ACTION_TYPE_EXEC
|
||||
from core.sheerka.Sheerka import RECOGNIZED_BY_ID, RECOGNIZED_BY_NAME
|
||||
from core.sheerka.services.SheerkaEvaluateRules import SheerkaEvaluateRules, LOW_PRIORITY_RULES, DISABLED_RULES
|
||||
from core.sheerka.services.SheerkaExecute import ParserInput
|
||||
from core.sheerka.services.SheerkaRuleManager import RuleCompiledPredicate, SheerkaRuleManager
|
||||
from evaluators.PythonEvaluator import PythonEvaluator, Expando
|
||||
from parsers.PythonParser import PythonParser
|
||||
from tests.TestUsingMemoryBasedSheerka import TestUsingMemoryBasedSheerka
|
||||
|
||||
|
||||
class TestSheerkaEvaluateRules(TestUsingMemoryBasedSheerka):
|
||||
def test_i_can_evaluate_python_rules(self):
|
||||
sheerka, context, r1, r2, r3, r4, r5, r6, r7, r8, r9 = self.init_test().with_rules(
|
||||
sheerka, context, r1, r2, r3, r4, r5, r6, r7, r8, r9 = self.init_test().with_format_rules(
|
||||
Rule(predicate="a == 1", action="", priority=1), # r1
|
||||
Rule(predicate="a == 2", action="", priority=1), # r2
|
||||
Rule(predicate="a == 3", action="", priority=0), # r3
|
||||
@@ -32,9 +39,10 @@ class TestSheerkaEvaluateRules(TestUsingMemoryBasedSheerka):
|
||||
DISABLED_RULES: [r7]
|
||||
}
|
||||
|
||||
def test_i_can_evaluate_concept_rules(self):
|
||||
def test_i_can_evaluate_question_concept_rules(self):
|
||||
sheerka, context, concept, r1, r2, r3, r4, r5, r6, r7, r8, r9 = self.init_test().with_concepts(
|
||||
Concept("x equals y", body="x == y").def_var("x").def_var("y"), create_new=True).with_rules(
|
||||
Concept("x equals y", body="x == y", pre="is_question()").def_var("x").def_var("y"),
|
||||
create_new=True).with_format_rules(
|
||||
Rule(predicate="a equals 1", action="", priority=1), # r1
|
||||
Rule(predicate="a equals 2", action="", priority=1), # r2
|
||||
Rule(predicate="a equals 3", action="", priority=0), # r3
|
||||
@@ -58,6 +66,159 @@ class TestSheerkaEvaluateRules(TestUsingMemoryBasedSheerka):
|
||||
DISABLED_RULES: [r7]
|
||||
}
|
||||
|
||||
@pytest.mark.parametrize("predicates", [
|
||||
("True", "False"),
|
||||
("False", "True"),
|
||||
])
|
||||
def test_i_can_eval_when_multiple_python_predicates(self, predicates):
|
||||
"""
|
||||
In this test, the rule has multiple predicates to evaluate
|
||||
The test make sure that is one predicate is successful, the rule must be evaluated
|
||||
"""
|
||||
sheerka, context, my_rule = self.init_test().with_format_rules(Rule("my rule"),
|
||||
compile_rule=False,
|
||||
create_new=False).unpack()
|
||||
service = sheerka.services[SheerkaEvaluateRules.NAME]
|
||||
|
||||
# create fake compiled predicates
|
||||
parser = PythonParser()
|
||||
my_rule.compiled_predicates = [
|
||||
RuleCompiledPredicate("my rule", None, PythonEvaluator.NAME, parser.parse(context, ParserInput(exp)), None)
|
||||
for exp in predicates]
|
||||
my_rule.metadata.is_compiled = True
|
||||
my_rule.metadata.is_enabled = True
|
||||
|
||||
res = service.evaluate_rules(context, [my_rule], {}, set())
|
||||
|
||||
assert res == {
|
||||
True: [my_rule],
|
||||
}
|
||||
|
||||
def test_i_can_evaluate_rules_when_concepts_are_questions(self):
|
||||
sheerka, context, isa, cat, crocodile, pet, r1, r2, r3 = self.init_test().with_concepts(
|
||||
Concept("x is a y", body="isa(x,y)", pre="is_question()").def_var("x").def_var("y"),
|
||||
"cat",
|
||||
"crocodile",
|
||||
"pet",
|
||||
create_new=True).with_format_rules(
|
||||
Rule(predicate="cat is a pet", action=""),
|
||||
Rule(predicate="crocodile is a pet", action=""),
|
||||
Rule(predicate="not crocodile is a pet", action=""),
|
||||
).unpack()
|
||||
sheerka.set_isa(context, cat, pet)
|
||||
service = sheerka.services[SheerkaEvaluateRules.NAME]
|
||||
|
||||
res = service.evaluate_rules(context, [r1, r2, r3], {}, set())
|
||||
assert res == {True: [r1, r3], False: [r2]}
|
||||
|
||||
@pytest.mark.parametrize("predicate", [
|
||||
"greetings",
|
||||
"c:|1001:",
|
||||
"hello 'kodjo'"
|
||||
])
|
||||
def test_i_can_evaluate_rules_when_concepts_are_not_questions(self, predicate):
|
||||
"""
|
||||
In this test, we evaluate rules that involves concepts that are not questions
|
||||
"""
|
||||
sheerka, context, greetings, rule = self.init_test().with_concepts(
|
||||
Concept("greetings", definition="hello a", definition_type=DEFINITION_TYPE_DEF).def_var("a"),
|
||||
create_new=True).with_format_rules(
|
||||
Rule(predicate=predicate, action="")).unpack()
|
||||
|
||||
service = sheerka.services[SheerkaEvaluateRules.NAME]
|
||||
ret = sheerka.ret("evaluator", True, sheerka.new(greetings, a="kodjo"))
|
||||
|
||||
res = service.evaluate_rules(context, [rule], {"__ret": ret}, set())
|
||||
assert res == {True: [rule]}
|
||||
|
||||
@pytest.mark.parametrize("recognized_by", [
|
||||
RECOGNIZED_BY_ID,
|
||||
RECOGNIZED_BY_NAME,
|
||||
None
|
||||
])
|
||||
def test_i_can_evaluate_concept_rules_when_variable_is_a_one_word_concept(self, recognized_by):
|
||||
"""
|
||||
In this test, we evaluate rules that involves concepts that are not questions
|
||||
"""
|
||||
sheerka, context, greetings, there, rule = self.init_test().with_concepts(
|
||||
Concept("greetings", definition="hello a", definition_type=DEFINITION_TYPE_DEF).def_var("a"),
|
||||
Concept("there"),
|
||||
create_new=True).with_format_rules(
|
||||
Rule(predicate="hello there", action="")).unpack()
|
||||
service = sheerka.services[SheerkaEvaluateRules.NAME]
|
||||
|
||||
there_instance = sheerka.new_from_template(there, there.key)
|
||||
if recognized_by:
|
||||
there_instance.set_hint(BuiltinConcepts.RECOGNIZED_BY, recognized_by)
|
||||
ret = sheerka.ret("evaluator", True, sheerka.new(greetings, a=there_instance))
|
||||
res = service.evaluate_rules(context, [rule], {"__ret": ret}, set())
|
||||
assert res == {True: [rule]}
|
||||
|
||||
@pytest.mark.parametrize("recognized_by", [
|
||||
RECOGNIZED_BY_ID,
|
||||
RECOGNIZED_BY_NAME,
|
||||
None
|
||||
])
|
||||
def test_i_can_evaluate_concept_rules_when_variable_is_a_two_words_concept(self, recognized_by):
|
||||
"""
|
||||
In this test, we evaluate rules that involves concepts that are not questions
|
||||
"""
|
||||
sheerka, context, greetings, my_friend, rule = self.init_test().with_concepts(
|
||||
Concept("greetings", definition="hello a", definition_type=DEFINITION_TYPE_DEF).def_var("a"),
|
||||
Concept("my friend"),
|
||||
create_new=True).with_format_rules(
|
||||
Rule(predicate="hello my friend", action="")).unpack()
|
||||
service = sheerka.services[SheerkaEvaluateRules.NAME]
|
||||
|
||||
my_friend_instance = sheerka.new_from_template(my_friend, my_friend.key)
|
||||
if recognized_by:
|
||||
my_friend_instance.set_hint(BuiltinConcepts.RECOGNIZED_BY, recognized_by)
|
||||
ret = sheerka.ret("evaluator", True, sheerka.new(greetings, a=my_friend_instance))
|
||||
res = service.evaluate_rules(context, [rule], {"__ret": ret}, set())
|
||||
assert res == {True: [rule]}
|
||||
|
||||
def test_i_can_evaluate_concept_rules_when_variable_is_an_expando(self):
|
||||
sheerka, context, greetings, rule = self.init_test().with_concepts(
|
||||
Concept("greetings", definition="hello a", definition_type=DEFINITION_TYPE_DEF).def_var("a"),
|
||||
create_new=True).with_format_rules(
|
||||
Rule(predicate="hello sheerka", action="")).unpack()
|
||||
service = sheerka.services[SheerkaEvaluateRules.NAME]
|
||||
|
||||
ret = sheerka.ret("evaluator", True, sheerka.new(greetings, a=Expando("sheerka", {})))
|
||||
res = service.evaluate_rules(context, [rule], {"__ret": ret}, set())
|
||||
assert res == {True: [rule]}
|
||||
|
||||
def test_i_can_evaluate_concept_rules_when_same_name(self):
|
||||
sheerka, context, g1, g2, rule = self.init_test().with_concepts(
|
||||
Concept("greetings", definition="hello a", definition_type=DEFINITION_TYPE_DEF).def_var("a"),
|
||||
Concept("greetings", definition="hi a", definition_type=DEFINITION_TYPE_DEF).def_var("a"),
|
||||
create_new=True).with_format_rules(
|
||||
Rule(predicate="greetings", action="")).unpack()
|
||||
|
||||
service = sheerka.services[SheerkaEvaluateRules.NAME]
|
||||
ret1 = sheerka.ret("evaluator", True, sheerka.new(g1, a="kodjo"))
|
||||
res = service.evaluate_rules(context, [rule], {"__ret": ret1}, set())
|
||||
assert res == {True: [rule]}
|
||||
|
||||
ret2 = sheerka.ret("evaluator", True, sheerka.new(g2, a="kodjo"))
|
||||
res = service.evaluate_rules(context, [rule], {"__ret": ret2}, set())
|
||||
assert res == {True: [rule]}
|
||||
|
||||
def test_i_can_evaluate_concept_rule_with_the_same_name_when_the_second_concept_is_declared_after(self):
|
||||
sheerka, context, g1, rule, g2 = self.init_test().with_concepts(
|
||||
Concept("greetings", definition="hello a", definition_type=DEFINITION_TYPE_DEF).def_var("a"),
|
||||
create_new=True).with_format_rules(Rule(predicate="greetings", action="")).with_concepts(
|
||||
Concept("greetings", definition="hi a", definition_type=DEFINITION_TYPE_DEF).def_var("a")).unpack()
|
||||
|
||||
service = sheerka.services[SheerkaEvaluateRules.NAME]
|
||||
ret1 = sheerka.ret("evaluator", True, sheerka.new(g1, a="kodjo"))
|
||||
res = service.evaluate_rules(context, [rule], {"__ret": ret1}, set())
|
||||
assert res == {True: [rule]}
|
||||
|
||||
ret2 = sheerka.ret("evaluator", True, sheerka.new(g2, a="kodjo"))
|
||||
res = service.evaluate_rules(context, [rule], {"__ret": ret2}, set())
|
||||
assert res == {True: [rule]}
|
||||
|
||||
def test_i_can_disable_rules_at_runtime(self):
|
||||
sheerka, context, r1, r2, = self.init_format_rules(
|
||||
Rule(predicate="a == 1", action="", priority=2), # r1
|
||||
@@ -72,3 +233,15 @@ class TestSheerkaEvaluateRules(TestUsingMemoryBasedSheerka):
|
||||
True: [r2],
|
||||
DISABLED_RULES: [r1]
|
||||
}
|
||||
|
||||
def test_rete_network_is_updated_on_new_rule_creation(self):
|
||||
sheerka, context = self.init_test().unpack()
|
||||
evaluate_rule_service = sheerka.services[SheerkaEvaluateRules.NAME]
|
||||
rule_manager_service = sheerka.services[SheerkaRuleManager.NAME]
|
||||
|
||||
rule = Rule(ACTION_TYPE_EXEC, "test", "ret.status == True", "test()")
|
||||
rule_manager_service.init_rule(context, rule)
|
||||
sheerka.create_new_rule(context, rule)
|
||||
|
||||
assert rule in evaluate_rule_service.network.rules
|
||||
assert rule.rete_net == evaluate_rule_service.network
|
||||
|
||||
@@ -80,6 +80,6 @@ example_of_class_method. event=xxx, data='42'
|
||||
assert "my first topic" in service.subscribers
|
||||
assert "my second topic" in service.subscribers
|
||||
|
||||
sheerka.pop_ontology()
|
||||
sheerka.pop_ontology(context)
|
||||
assert "my first topic" in service.subscribers
|
||||
assert "my second topic" not in service.subscribers
|
||||
|
||||
@@ -122,7 +122,7 @@ class TestSheerkaFunctionsParametersHistory(TestUsingMemoryBasedSheerka):
|
||||
3: [("'string value'", 1)]
|
||||
})}
|
||||
|
||||
sheerka.pop_ontology()
|
||||
sheerka.pop_ontology(context)
|
||||
assert sheerka.om.copy(service.FUNCTIONS_PARAMETERS_ENTRY) == {"function": FunctionParametersObj(
|
||||
context.event.get_digest(),
|
||||
"function",
|
||||
|
||||
@@ -322,7 +322,7 @@ class TestSheerkaIsAManager(TestUsingMemoryBasedSheerka):
|
||||
assert sheerka.isa(foo, group2)
|
||||
|
||||
# I can revert back
|
||||
sheerka.pop_ontology()
|
||||
sheerka.pop_ontology(context)
|
||||
assert sheerka.isaset(context, group1)
|
||||
assert sheerka.isinset(foo, group1)
|
||||
assert sheerka.isa(foo, group1)
|
||||
|
||||
@@ -3,15 +3,21 @@ import ast
|
||||
import pytest
|
||||
|
||||
from core.builtin_concepts import BuiltinConcepts
|
||||
from core.concept import Concept, CMV
|
||||
from core.global_symbols import RULE_COMPARISON_CONTEXT
|
||||
from core.concept import Concept, CMV, DEFINITION_TYPE_DEF, CC, DoNotResolve
|
||||
from core.global_symbols import RULE_COMPARISON_CONTEXT, NotFound, EVENT_RULE_DELETED
|
||||
from core.rule import Rule, ACTION_TYPE_PRINT, ACTION_TYPE_EXEC
|
||||
from core.sheerka.services.SheerkaRuleManager import SheerkaRuleManager, FormatRuleParser, \
|
||||
from core.sheerka.Sheerka import RECOGNIZED_BY_ID, RECOGNIZED_BY_NAME
|
||||
from core.sheerka.services.SheerkaRuleManager import SheerkaRuleManager, FormatRuleActionParser, \
|
||||
FormatAstRawText, FormatAstVariable, FormatAstSequence, FormatAstFunction, \
|
||||
FormatRuleSyntaxError, FormatAstList, UnexpectedEof, FormatAstColor, RulePredicate, FormatAstDict, FormatAstMulti
|
||||
FormatRuleSyntaxError, FormatAstList, UnexpectedEof, FormatAstColor, RuleCompiledPredicate, FormatAstDict, \
|
||||
FormatAstMulti, \
|
||||
PythonCodeEmitter, NoConditionFound, FormatAstNode
|
||||
from core.sheerka.services.sheerka_service import FailedToCompileError
|
||||
from core.tokenizer import Token, TokenKind
|
||||
from parsers.BaseNodeParser import SourceCodeWithConceptNode, SourceCodeNode
|
||||
from parsers.PythonParser import PythonNode
|
||||
from sheerkarete.common import V
|
||||
from sheerkarete.conditions import Condition, AndConditions
|
||||
from tests.TestUsingFileBasedSheerka import TestUsingFileBasedSheerka
|
||||
from tests.TestUsingMemoryBasedSheerka import TestUsingMemoryBasedSheerka
|
||||
|
||||
@@ -32,7 +38,7 @@ class TestSheerkaRuleManager(TestUsingMemoryBasedSheerka):
|
||||
(ACTION_TYPE_EXEC, SheerkaRuleManager.EXEC_RULE_ENTRY),
|
||||
])
|
||||
def test_i_can_create_a_new_rule(self, action_type, cache_entry):
|
||||
sheerka, context = self.init_concepts(cache_only=False)
|
||||
sheerka, context = self.init_test(cache_only=False).unpack()
|
||||
previous_rules_number = sheerka.om.get_all(sheerka.OBJECTS_IDS_ENTRY)[SheerkaRuleManager.RULE_IDS]
|
||||
|
||||
rule = Rule(action_type, "name", "True", "Hello world")
|
||||
@@ -96,6 +102,114 @@ class TestSheerkaRuleManager(TestUsingMemoryBasedSheerka):
|
||||
sheerka.om.current_cache_manager().caches[
|
||||
SheerkaRuleManager.FORMAT_RULE_ENTRY].cache) == 2 + previous_rules_number
|
||||
|
||||
@pytest.mark.parametrize("action_type, cache_entry", [
|
||||
(ACTION_TYPE_PRINT, SheerkaRuleManager.FORMAT_RULE_ENTRY),
|
||||
(ACTION_TYPE_EXEC, SheerkaRuleManager.EXEC_RULE_ENTRY),
|
||||
])
|
||||
def test_i_can_delete_a_rule(self, action_type, cache_entry):
|
||||
sheerka, context, rule = self.init_test(cache_only=False).with_rules(
|
||||
action_type,
|
||||
Rule(action_type, "rule_name", "id.attr == 'value'", 'True')).unpack()
|
||||
rule_to_delete = Rule(rule.compiled_action, rule_id=rule.id)
|
||||
|
||||
event_sink = []
|
||||
self.sheerka.subscribe(EVENT_RULE_DELETED, lambda c, r: event_sink.append(r))
|
||||
|
||||
ret = sheerka.remove_rule(context, rule_to_delete)
|
||||
|
||||
assert ret.status
|
||||
assert sheerka.om.get(cache_entry, rule.id) is NotFound
|
||||
assert sheerka.om.get(SheerkaRuleManager.RULES_BY_NAME_ENTRY, rule.id) is NotFound
|
||||
|
||||
sheerka.om.commit(context)
|
||||
assert sheerka.om.current_sdp().get(cache_entry, rule.id)
|
||||
assert sheerka.om.current_sdp().get(SheerkaRuleManager.RULES_BY_NAME_ENTRY, rule.id)
|
||||
|
||||
assert event_sink == [rule]
|
||||
|
||||
def test_i_can_init_rule_with_a_exec_rule(self):
|
||||
sheerka, context = self.init_test(cache_only=False).unpack()
|
||||
service = sheerka.services[SheerkaRuleManager.NAME]
|
||||
|
||||
rule = Rule(ACTION_TYPE_EXEC, "name", "__input == 'hello world'", "'Hello back at you !'")
|
||||
rule = service.init_rule(context, rule)
|
||||
|
||||
assert rule.metadata.is_compiled
|
||||
assert rule.metadata.is_enabled
|
||||
assert len(rule.compiled_predicates) == 1
|
||||
assert len(rule.rete_disjunctions) == 1
|
||||
assert sheerka.isinstance(rule.compiled_action, BuiltinConcepts.RETURN_VALUE)
|
||||
assert rule.compiled_action.status
|
||||
assert rule.error_sink is None
|
||||
|
||||
def test_i_can_init_rule_with_a_format_rule(self):
|
||||
sheerka, context = self.init_test(cache_only=False).unpack()
|
||||
service = sheerka.services[SheerkaRuleManager.NAME]
|
||||
|
||||
rule = Rule(ACTION_TYPE_PRINT, "name", "__input == 'hello world'", "Hello back at you !")
|
||||
rule = service.init_rule(context, rule)
|
||||
|
||||
assert rule.metadata.is_compiled
|
||||
assert rule.metadata.is_enabled
|
||||
assert len(rule.compiled_predicates) == 1
|
||||
assert len(rule.rete_disjunctions) == 1
|
||||
assert isinstance(rule.compiled_action, FormatAstNode)
|
||||
assert rule.error_sink is None
|
||||
|
||||
def test_i_do_not_init_rule_an_already_compiled_rule(self):
|
||||
sheerka, context = self.init_test(cache_only=False).unpack()
|
||||
service = sheerka.services[SheerkaRuleManager.NAME]
|
||||
|
||||
rule = Rule(ACTION_TYPE_EXEC, "name", "cannot build", "cannot compile either")
|
||||
rule.metadata.is_compiled = True
|
||||
|
||||
rule = service.init_rule(context, rule)
|
||||
|
||||
assert rule.metadata.is_compiled
|
||||
assert rule.error_sink is None # no error detected
|
||||
|
||||
@pytest.mark.parametrize("action_type, action", [
|
||||
(ACTION_TYPE_EXEC, "'Hello back at you !'"),
|
||||
(ACTION_TYPE_PRINT, "Hello back at you !"),
|
||||
])
|
||||
def test_init_rule_returns_errors_when_cannot_build_predicate(self, action_type, action):
|
||||
sheerka, context = self.init_test(cache_only=False).unpack()
|
||||
service = sheerka.services[SheerkaRuleManager.NAME]
|
||||
|
||||
rule = Rule(ACTION_TYPE_EXEC, "name", "cannot build", "'Hello back at you !'")
|
||||
rule.metadata.is_enabled = True # it should be disabled
|
||||
rule = service.init_rule(context, rule)
|
||||
|
||||
assert len(rule.error_sink["when"]) > 0
|
||||
assert sheerka.is_error(rule.error_sink["when"][0])
|
||||
assert "print" not in rule.error_sink
|
||||
assert "then" not in rule.error_sink
|
||||
assert rule.metadata.is_compiled
|
||||
assert not rule.metadata.is_enabled
|
||||
assert rule.compiled_predicates is None
|
||||
assert rule.rete_disjunctions is None
|
||||
|
||||
@pytest.mark.parametrize("action_type, action", [
|
||||
(ACTION_TYPE_EXEC, "cannot build action"),
|
||||
(ACTION_TYPE_PRINT, "list("),
|
||||
])
|
||||
def test_init_rule_returns_error_when_cannot_build_action(self, action_type, action):
|
||||
sheerka, context = self.init_test(cache_only=False).unpack()
|
||||
service = sheerka.services[SheerkaRuleManager.NAME]
|
||||
|
||||
rule = Rule(action_type, "name", "__input == 'hello world'", action)
|
||||
rule.metadata.is_enabled = True # it should be disabled
|
||||
rule = service.init_rule(context, rule)
|
||||
|
||||
other_action_type = ACTION_TYPE_PRINT if action_type == ACTION_TYPE_EXEC else ACTION_TYPE_EXEC
|
||||
|
||||
assert sheerka.is_error(rule.error_sink[action_type])
|
||||
assert other_action_type not in rule.error_sink
|
||||
assert "when" not in rule.error_sink
|
||||
assert rule.metadata.is_compiled
|
||||
assert not rule.metadata.is_enabled
|
||||
assert rule.compiled_action is None
|
||||
|
||||
@pytest.mark.parametrize("text, expected", [
|
||||
("", FormatAstRawText("")),
|
||||
(" ", FormatAstRawText(" ")),
|
||||
@@ -134,7 +248,7 @@ class TestSheerkaRuleManager(TestUsingMemoryBasedSheerka):
|
||||
("multi(var_name)", FormatAstMulti("var_name")),
|
||||
])
|
||||
def test_i_can_parse_format_rule(self, text, expected):
|
||||
assert FormatRuleParser(text).parse() == expected
|
||||
assert FormatRuleActionParser(text).parse() == expected
|
||||
|
||||
@pytest.mark.parametrize("text, expected_error", [
|
||||
("{", UnexpectedEof("while parsing variable", Token(TokenKind.LBRACE, "{", 0, 1, 1))),
|
||||
@@ -156,15 +270,52 @@ class TestSheerkaRuleManager(TestUsingMemoryBasedSheerka):
|
||||
("dict()", FormatRuleSyntaxError("variable name not found", None)),
|
||||
])
|
||||
def test_i_cannot_parse_invalid_format(self, text, expected_error):
|
||||
parser = FormatRuleParser(text)
|
||||
parser = FormatRuleActionParser(text)
|
||||
parser.parse()
|
||||
|
||||
assert parser.error_sink == expected_error
|
||||
|
||||
@pytest.mark.parametrize("text", [
|
||||
"__action == 'some_action' and True",
|
||||
"__action == 'some_action' and not a question",
|
||||
"__action == 'some_action' and is a question",
|
||||
])
|
||||
def test_i_can_compile_predicate_when_action_is_provided(self, text):
|
||||
sheerka, context, *concepts = self.init_test().with_concepts(
|
||||
"a question",
|
||||
Concept("is a question", pre='is_question()'),
|
||||
create_new=True).unpack()
|
||||
service = sheerka.services[SheerkaRuleManager.NAME]
|
||||
|
||||
compiled_result = service.compile_when(context, "test", text)
|
||||
res = compiled_result.compiled_predicates
|
||||
assert len(res) == 1
|
||||
assert isinstance(res[0], RuleCompiledPredicate)
|
||||
assert res[0].action == 'some_action'
|
||||
|
||||
def test_i_can_compile___action_is_not_part_of_the_predicates(self):
|
||||
sheerka, context, *concepts = self.init_concepts("foo")
|
||||
service = sheerka.services[SheerkaRuleManager.NAME]
|
||||
ast_ = ast.parse("a == 5", "<source>", 'eval')
|
||||
expected_python_node = PythonNode('a == 5', ast_)
|
||||
|
||||
compiled_result = service.compile_when(context, "test", "__action == 'some action' and a == 5")
|
||||
res = compiled_result.compiled_predicates
|
||||
|
||||
assert len(res) == 1
|
||||
assert isinstance(res[0], RuleCompiledPredicate)
|
||||
assert res[0].evaluator == PYTHON_EVALUATOR_NAME
|
||||
assert sheerka.isinstance(res[0].predicate, BuiltinConcepts.RETURN_VALUE)
|
||||
assert sheerka.objvalue(res[0].predicate) == expected_python_node
|
||||
assert res[0].concept is None
|
||||
|
||||
@pytest.mark.parametrize("text", [
|
||||
"a == 5",
|
||||
"foo == 5",
|
||||
"foo > 5",
|
||||
"func() == 5",
|
||||
"not a == 5",
|
||||
"not foo > 5",
|
||||
"not func() == 5",
|
||||
])
|
||||
def test_i_can_compile_predicate_when_pure_python(self, text):
|
||||
sheerka, context, *concepts = self.init_concepts("foo")
|
||||
@@ -172,10 +323,11 @@ class TestSheerkaRuleManager(TestUsingMemoryBasedSheerka):
|
||||
ast_ = ast.parse(text, "<source>", 'eval')
|
||||
expected_python_node = PythonNode(text, ast_)
|
||||
|
||||
res = service.compile_when(context, "test", text)
|
||||
compiled_result = service.compile_when(context, "test", text)
|
||||
res = compiled_result.compiled_predicates
|
||||
|
||||
assert len(res) == 1
|
||||
assert isinstance(res[0], RulePredicate)
|
||||
assert isinstance(res[0], RuleCompiledPredicate)
|
||||
assert res[0].evaluator == PYTHON_EVALUATOR_NAME
|
||||
assert sheerka.isinstance(res[0].predicate, BuiltinConcepts.RETURN_VALUE)
|
||||
assert sheerka.objvalue(res[0].predicate) == expected_python_node
|
||||
@@ -184,6 +336,8 @@ class TestSheerkaRuleManager(TestUsingMemoryBasedSheerka):
|
||||
@pytest.mark.parametrize("text, expected_type", [
|
||||
("isinstance(a, int)", SourceCodeWithConceptNode),
|
||||
("func()", SourceCodeNode),
|
||||
("not isinstance(a, int)", PythonNode),
|
||||
("not func()", PythonNode),
|
||||
])
|
||||
def test_i_can_compile_predicates_that_resolve_to_python(self, text, expected_type):
|
||||
sheerka, context, *concepts = self.init_concepts()
|
||||
@@ -191,30 +345,15 @@ class TestSheerkaRuleManager(TestUsingMemoryBasedSheerka):
|
||||
ast_ = ast.parse(text, "<source>", 'eval')
|
||||
expected_python_node = PythonNode(text, ast_)
|
||||
|
||||
res = service.compile_when(context, "test", text)
|
||||
compiled_result = service.compile_when(context, "test", text)
|
||||
res = compiled_result.compiled_predicates
|
||||
|
||||
assert len(res) == 1
|
||||
assert isinstance(res[0], RulePredicate)
|
||||
assert isinstance(res[0], RuleCompiledPredicate)
|
||||
assert res[0].evaluator == PYTHON_EVALUATOR_NAME
|
||||
assert sheerka.isinstance(res[0].predicate, BuiltinConcepts.RETURN_VALUE)
|
||||
assert isinstance(sheerka.objvalue(res[0].predicate), expected_type)
|
||||
assert sheerka.objvalue(res[0].predicate).python_node == expected_python_node
|
||||
assert res[0].concept is None
|
||||
|
||||
def test_i_can_compile_predicate_when_python_and_concept(self):
|
||||
sheerka, context, *concepts = self.init_test().with_concepts(Concept("foo bar"), create_new=True).unpack()
|
||||
service = sheerka.services[SheerkaRuleManager.NAME]
|
||||
text = "foo bar == 5"
|
||||
ast_ = ast.parse("__C__foo0bar__1001__C__ == 5", "<source>", 'eval')
|
||||
resolved_expected = PythonNode(text, ast_)
|
||||
|
||||
res = service.compile_when(context, "test", text)
|
||||
|
||||
assert len(res) == 1
|
||||
assert isinstance(res[0], RulePredicate)
|
||||
assert res[0].evaluator == PYTHON_EVALUATOR_NAME
|
||||
assert sheerka.isinstance(res[0].predicate, BuiltinConcepts.RETURN_VALUE)
|
||||
assert sheerka.objvalue(res[0].predicate) == resolved_expected
|
||||
assert sheerka.objvalue(res[0].predicate).get_python_node() == expected_python_node
|
||||
assert res[0].concept is None
|
||||
|
||||
@pytest.mark.parametrize("text, expected_variables", [
|
||||
@@ -234,15 +373,106 @@ class TestSheerkaRuleManager(TestUsingMemoryBasedSheerka):
|
||||
expected = concepts[0]
|
||||
expected.get_metadata().variables = [('x', expected_variables[0]), ('y', expected_variables[1])]
|
||||
|
||||
res = service.compile_when(context, "test", text)
|
||||
compiled_result = service.compile_when(context, "test", text)
|
||||
res = compiled_result.compiled_predicates
|
||||
|
||||
assert len(res) == 1
|
||||
assert isinstance(res[0], RulePredicate)
|
||||
assert isinstance(res[0], RuleCompiledPredicate)
|
||||
assert res[0].evaluator == CONCEPT_EVALUATOR_NAME
|
||||
assert sheerka.isinstance(res[0].predicate, BuiltinConcepts.RETURN_VALUE)
|
||||
assert sheerka.objvalue(res[0].predicate) == expected
|
||||
assert res[0].concept == expected
|
||||
|
||||
@pytest.mark.parametrize("text, text_to_compile, expected_variables", [
|
||||
("not cat is an animal", "not __C__00var0000is0an000var001__1001__C__", ["cat", "animal"]),
|
||||
("not a is an animal", "not __C__00var0000is0an000var001__1001__C__", ["a", "animal"]),
|
||||
("not cat is an b", "not __C__00var0000is0an000var001__1001__C__", ["cat", "b"]),
|
||||
])
|
||||
def test_i_can_compile_negative_predicate_when_exact_concept(self, text, text_to_compile, expected_variables):
|
||||
sheerka, context, *concepts = self.init_test().with_concepts(
|
||||
Concept("x is an y", pre="is_question()", body="isinstance(x, y)").def_var("x").def_var("y"),
|
||||
Concept("cat"),
|
||||
Concept("animal"),
|
||||
create_new=True
|
||||
).unpack()
|
||||
service = sheerka.services[SheerkaRuleManager.NAME]
|
||||
|
||||
expected_concept = concepts[0]
|
||||
expected_concept.get_metadata().variables = [('x', expected_variables[0]), ('y', expected_variables[1])]
|
||||
ast_ = ast.parse(text_to_compile, "<source>", 'eval')
|
||||
expected_python_node = PythonNode(text_to_compile, ast_)
|
||||
expected_python_node.original_source = text
|
||||
expected_python_node.objects = {"__C__00var0000is0an000var001__1001__C__": expected_concept}
|
||||
res = service.compile_when(context, "test", text)
|
||||
|
||||
assert len(res) == 1
|
||||
assert isinstance(res[0], RuleCompiledPredicate)
|
||||
assert res[0].evaluator == PYTHON_EVALUATOR_NAME
|
||||
assert sheerka.isinstance(res[0].predicate, BuiltinConcepts.RETURN_VALUE)
|
||||
assert isinstance(sheerka.objvalue(res[0].predicate), PythonNode)
|
||||
|
||||
python_node = sheerka.objvalue(res[0].predicate).get_python_node()
|
||||
assert python_node == expected_python_node
|
||||
assert len(python_node.objects) == 1
|
||||
assert python_node.objects["__C__00var0000is0an000var001__1001__C__"] == expected_concept
|
||||
assert res[0].concept is None
|
||||
|
||||
@pytest.mark.skip("Not managed yet")
|
||||
@pytest.mark.parametrize("text, text_to_compile, expected_variables", [
|
||||
("not cat is an animal", "__C__00var0000is0an000var001__1001__C__", ["not cat", "animal"])
|
||||
])
|
||||
def test_i_can_compile_negative_predicate_when_exact_concept(self, text, text_to_compile, expected_variables):
|
||||
sheerka, context, *concepts = self.init_test().with_concepts(
|
||||
Concept("x is an y", pre="is_question()", body="isinstance(x, y)").def_var("x").def_var("y"),
|
||||
Concept("cat"),
|
||||
Concept("animal"),
|
||||
create_new=True
|
||||
).unpack()
|
||||
service = sheerka.services[SheerkaRuleManager.NAME]
|
||||
|
||||
expected_concept = concepts[0]
|
||||
expected_concept.get_metadata().variables = [('x', expected_variables[0]), ('y', expected_variables[1])]
|
||||
ast_ = ast.parse(text_to_compile, "<source>", 'eval')
|
||||
expected_python_node = PythonNode(text_to_compile, ast_)
|
||||
expected_python_node.original_source = text
|
||||
expected_python_node.objects = {"__C__00var0000is0an000var001__1001__C__": expected_concept}
|
||||
res = service.compile_when(context, "test", text)
|
||||
|
||||
assert len(res) == 1
|
||||
assert isinstance(res[0], RuleCompiledPredicate)
|
||||
assert res[0].evaluator == PYTHON_EVALUATOR_NAME
|
||||
assert sheerka.isinstance(res[0].predicate, BuiltinConcepts.RETURN_VALUE)
|
||||
assert isinstance(sheerka.objvalue(res[0].predicate), PythonNode)
|
||||
|
||||
python_node = sheerka.objvalue(res[0].predicate).get_python_node()
|
||||
assert python_node == expected_python_node
|
||||
assert len(python_node.objects) == 1
|
||||
assert python_node.objects["__C__00var0000is0an000var001__1001__C__"] == expected_concept
|
||||
assert res[0].concept is None
|
||||
|
||||
@pytest.mark.parametrize("text, text_to_compile", [
|
||||
("foo bar == 5", "__C__foo0bar__1001__C__ == 5"),
|
||||
("not foo bar == 5", "not __C__foo0bar__1001__C__ == 5"),
|
||||
])
|
||||
def test_i_can_compile_predicate_when_python_and_concept(self, text, text_to_compile):
|
||||
sheerka, context, *concepts = self.init_test().with_concepts(Concept("foo bar"), create_new=True).unpack()
|
||||
service = sheerka.services[SheerkaRuleManager.NAME]
|
||||
ast_ = ast.parse(text_to_compile, "<source>", 'eval')
|
||||
resolved_expected = PythonNode(text_to_compile, ast_, text)
|
||||
|
||||
compiled_result = service.compile_when(context, "test", text)
|
||||
res = compiled_result.compiled_predicates
|
||||
|
||||
assert len(res) == 1
|
||||
assert isinstance(res[0], RuleCompiledPredicate)
|
||||
assert res[0].evaluator == PYTHON_EVALUATOR_NAME
|
||||
assert sheerka.isinstance(res[0].predicate, BuiltinConcepts.RETURN_VALUE)
|
||||
|
||||
python_node = sheerka.objvalue(res[0].predicate).get_python_node()
|
||||
assert python_node == resolved_expected
|
||||
assert python_node.objects == {'__C__foo0bar__1001__C__': concepts[0]}
|
||||
assert res[0].concept is None
|
||||
|
||||
@pytest.mark.parametrize("text, expected_variables", [
|
||||
("a cat is an animal", ["a cat", "animal"]),
|
||||
("a cat is an b", ["a cat", "b"]),
|
||||
@@ -257,10 +487,11 @@ class TestSheerkaRuleManager(TestUsingMemoryBasedSheerka):
|
||||
service = sheerka.services[SheerkaRuleManager.NAME]
|
||||
expected = CMV(concepts[0], x=expected_variables[0], y=expected_variables[1])
|
||||
|
||||
res = service.compile_when(context, "test", text)
|
||||
compiled_result = service.compile_when(context, "test", text)
|
||||
res = compiled_result.compiled_predicates
|
||||
|
||||
assert len(res) == 1
|
||||
assert isinstance(res[0], RulePredicate)
|
||||
assert isinstance(res[0], RuleCompiledPredicate)
|
||||
assert res[0].evaluator == CONCEPT_EVALUATOR_NAME
|
||||
assert sheerka.isinstance(res[0].predicate, BuiltinConcepts.RETURN_VALUE)
|
||||
assert sheerka.objvalue(res[0].predicate)[0].concept == expected
|
||||
@@ -275,15 +506,101 @@ class TestSheerkaRuleManager(TestUsingMemoryBasedSheerka):
|
||||
service = sheerka.services[SheerkaRuleManager.NAME]
|
||||
expected = concepts[1]
|
||||
|
||||
res = service.compile_when(context, "test", "cat is an animal")
|
||||
compiled_result = service.compile_when(context, "test", "cat is an animal")
|
||||
res = compiled_result.compiled_predicates
|
||||
|
||||
assert len(res) == 1
|
||||
assert isinstance(res[0], RulePredicate)
|
||||
assert isinstance(res[0], RuleCompiledPredicate)
|
||||
assert res[0].evaluator == CONCEPT_EVALUATOR_NAME
|
||||
assert sheerka.isinstance(res[0].predicate, BuiltinConcepts.RETURN_VALUE)
|
||||
assert sheerka.objvalue(res[0].predicate)[0].concept == expected
|
||||
assert res[0].concept == expected
|
||||
|
||||
def test_i_can_compile_predicate_when_mix_of_concepts_and_python(self):
|
||||
sheerka, context, animal, cat, dog, pet, is_a, is_an = self.init_test().with_concepts(
|
||||
Concept("animal"),
|
||||
Concept("a cat"),
|
||||
Concept("dog"),
|
||||
Concept("pet"),
|
||||
Concept("x is a y", pre="is_question()", body="isinstance(x, y)").def_var("x").def_var("y"),
|
||||
Concept("x is an y", pre="is_question()", definition="('cat'|'bird')=x 'is an' animal").def_var("x"),
|
||||
create_new=True
|
||||
).unpack()
|
||||
service = sheerka.services[SheerkaRuleManager.NAME]
|
||||
|
||||
text = "a cat is a pet and bird is an animal and x > 5 and dog is a pet"
|
||||
compiled_result = service.compile_when(context, "test", text)
|
||||
res = compiled_result.compiled_predicates
|
||||
|
||||
to_compile = '__C__00var0000is0a000var001__1005__C__ and __C__00var0000is0an0y__1006__C__ and x > 5 and __C__00var0000is0a000var001__1005_1__C__'
|
||||
ast_ = ast.parse(to_compile, "<source>", 'eval')
|
||||
expected_python_node = PythonNode(to_compile, ast_, text)
|
||||
|
||||
assert len(res) == 1
|
||||
assert isinstance(res[0], RuleCompiledPredicate)
|
||||
python_node = res[0].predicate.body.body
|
||||
assert python_node == expected_python_node
|
||||
assert python_node.objects == {
|
||||
"__C__00var0000is0a000var001__1005__C__": CC(is_a, x=cat, y=pet),
|
||||
"__C__00var0000is0an0y__1006__C__": CC(is_an, exclude_body=True, x=DoNotResolve("bird"), animal=animal),
|
||||
"__C__00var0000is0a000var001__1005_1__C__": CMV(is_a, x="dog", y="pet"),
|
||||
}
|
||||
|
||||
@pytest.mark.parametrize("text", [
|
||||
"a and not b",
|
||||
"not b and a",
|
||||
"__ret and not __ret.status",
|
||||
])
|
||||
def test_i_can_compile_negative_conjunctions_when_pure_python(self, text):
|
||||
sheerka, context, *concepts = self.init_concepts("foo")
|
||||
service = sheerka.services[SheerkaRuleManager.NAME]
|
||||
|
||||
ast_ = ast.parse(text, "<source>", 'eval')
|
||||
expected_python_node = PythonNode(text, ast_)
|
||||
|
||||
compiled_result = service.compile_when(context, "test", text)
|
||||
res = compiled_result.compiled_predicates
|
||||
|
||||
assert len(res) == 1
|
||||
assert isinstance(res[0], RuleCompiledPredicate)
|
||||
assert res[0].evaluator == PYTHON_EVALUATOR_NAME
|
||||
assert sheerka.isinstance(res[0].predicate, BuiltinConcepts.RETURN_VALUE)
|
||||
assert sheerka.objvalue(res[0].predicate) == expected_python_node
|
||||
assert res[0].concept is None
|
||||
|
||||
def test_i_can_compile_negative_conjunction_of_mix_of_concepts_and_python(self):
|
||||
sheerka, context, animal, cat, dog, pet, is_a, is_an = self.init_test().with_concepts(
|
||||
Concept("animal"),
|
||||
Concept("a cat"),
|
||||
Concept("dog"),
|
||||
Concept("pet"),
|
||||
Concept("x is a y", pre="is_question()", body="isinstance(x, y)").def_var("x").def_var("y"),
|
||||
Concept("x is an y", pre="is_question()", definition="('cat'|'bird')=x 'is an' animal").def_var("x"),
|
||||
create_new=True
|
||||
).unpack()
|
||||
service = sheerka.services[SheerkaRuleManager.NAME]
|
||||
|
||||
text = "not a cat is a pet and not bird is an animal and not x > 5 and not dog is a pet"
|
||||
compiled_result = service.compile_when(context, "test", text)
|
||||
res = compiled_result.compiled_predicates
|
||||
|
||||
to_compile = 'not __C__00var0000is0a000var001__1005__C__'
|
||||
to_compile += ' and not __C__00var0000is0an0y__1006__C__'
|
||||
to_compile += ' and not x > 5'
|
||||
to_compile += ' and not __C__00var0000is0a000var001__1005_1__C__'
|
||||
ast_ = ast.parse(to_compile, "<source>", 'eval')
|
||||
expected_python_node = PythonNode(to_compile, ast_, text)
|
||||
|
||||
assert len(res) == 1
|
||||
assert isinstance(res[0], RuleCompiledPredicate)
|
||||
python_node = res[0].predicate.body.body
|
||||
assert python_node == expected_python_node
|
||||
assert python_node.objects == {
|
||||
"__C__00var0000is0a000var001__1005__C__": CC(is_a, x=cat, y=pet),
|
||||
"__C__00var0000is0an0y__1006__C__": CC(is_an, exclude_body=True, x=DoNotResolve("bird"), animal=animal),
|
||||
"__C__00var0000is0a000var001__1005_1__C__": CMV(is_a, x="dog", y="pet"),
|
||||
}
|
||||
|
||||
def test_i_can_compile_predicate_when_multiple_choices(self):
|
||||
sheerka, context, *concepts = self.init_test().with_concepts(
|
||||
Concept("x is a y", pre="is_question()", body="isinstance(x, y)").def_var("x").def_var("y"),
|
||||
@@ -292,24 +609,185 @@ class TestSheerkaRuleManager(TestUsingMemoryBasedSheerka):
|
||||
).unpack()
|
||||
service = sheerka.services[SheerkaRuleManager.NAME]
|
||||
|
||||
res = service.compile_when(context, "test", "a is a b")
|
||||
compiled_result = service.compile_when(context, "test", "a is a b")
|
||||
res = compiled_result.compiled_predicates
|
||||
|
||||
assert len(res) == 2
|
||||
assert isinstance(res[0], RulePredicate)
|
||||
assert isinstance(res[0], RuleCompiledPredicate)
|
||||
assert res[0].evaluator == CONCEPT_EVALUATOR_NAME
|
||||
assert sheerka.isinstance(res[0].predicate, BuiltinConcepts.RETURN_VALUE)
|
||||
assert sheerka.objvalue(res[0].predicate)[0].concept == CMV(concepts[0], x="a", y="b")
|
||||
assert res[0].concept == CMV(concepts[0], x="a", y="b")
|
||||
|
||||
assert isinstance(res[1], RulePredicate)
|
||||
assert isinstance(res[1], RuleCompiledPredicate)
|
||||
assert res[1].evaluator == CONCEPT_EVALUATOR_NAME
|
||||
assert sheerka.isinstance(res[1].predicate, BuiltinConcepts.RETURN_VALUE)
|
||||
assert sheerka.objvalue(res[1].predicate)[0].concept == CMV(concepts[1], x="a", y="b")
|
||||
assert res[1].concept == CMV(concepts[1], x="a", y="b")
|
||||
|
||||
def test_i_can_compile_predicate_when_mix_and_multiple_choices(self):
|
||||
sheerka, context, *concepts = self.init_test().with_concepts(
|
||||
Concept("animal"),
|
||||
Concept("a cat"),
|
||||
Concept("dog"),
|
||||
Concept("pet"),
|
||||
Concept("x is a y", pre="is_question()", body="isinstance(x, y)").def_var("x").def_var("y"),
|
||||
Concept("x is a y", pre="is_question()", body="isa(x, y)").def_var("x").def_var("y"),
|
||||
Concept("x is an y", pre="is_question()", definition="('cat'|'bird')=x 'is an' animal").def_var("x"),
|
||||
create_new=True
|
||||
).unpack()
|
||||
service = sheerka.services[SheerkaRuleManager.NAME]
|
||||
|
||||
text = "__action == 'value' and a cat is a pet and bird is an animal and x > 5 and dog is a pet"
|
||||
compiled_result = service.compile_when(context, "test", text)
|
||||
res = compiled_result.compiled_predicates
|
||||
|
||||
assert len(res) == 4
|
||||
trimmed_source = "a cat is a pet and bird is an animal and x > 5 and dog is a pet"
|
||||
|
||||
current_res = res[0]
|
||||
assert isinstance(current_res, RuleCompiledPredicate)
|
||||
assert current_res.evaluator == PYTHON_EVALUATOR_NAME
|
||||
assert sheerka.isinstance(current_res.predicate, BuiltinConcepts.RETURN_VALUE)
|
||||
python_source = "__C__00var0000is0a000var001__1005__C__ and __C__00var0000is0an0y__1007__C__ and x > 5 and __C__00var0000is0a000var001__1005_1__C__"
|
||||
ast_ = ast.parse(python_source, "<source>", 'eval')
|
||||
resolved_expected = PythonNode(python_source, ast_, trimmed_source)
|
||||
assert sheerka.objvalue(current_res.predicate) == resolved_expected
|
||||
assert current_res.concept is None
|
||||
|
||||
current_res = res[1]
|
||||
assert isinstance(current_res, RuleCompiledPredicate)
|
||||
assert current_res.evaluator == PYTHON_EVALUATOR_NAME
|
||||
assert sheerka.isinstance(current_res.predicate, BuiltinConcepts.RETURN_VALUE)
|
||||
python_source = "__C__00var0000is0a000var001__1005__C__ and __C__00var0000is0an0y__1007__C__ and x > 5 and __C__00var0000is0a000var001__1006__C__"
|
||||
ast_ = ast.parse(python_source, "<source>", 'eval')
|
||||
resolved_expected = PythonNode(python_source, ast_, trimmed_source)
|
||||
assert sheerka.objvalue(current_res.predicate) == resolved_expected
|
||||
assert current_res.concept is None
|
||||
|
||||
current_res = res[2]
|
||||
assert isinstance(current_res, RuleCompiledPredicate)
|
||||
assert current_res.evaluator == PYTHON_EVALUATOR_NAME
|
||||
assert sheerka.isinstance(current_res.predicate, BuiltinConcepts.RETURN_VALUE)
|
||||
python_source = "__C__00var0000is0a000var001__1006__C__ and __C__00var0000is0an0y__1007__C__ and x > 5 and __C__00var0000is0a000var001__1005__C__"
|
||||
ast_ = ast.parse(python_source, "<source>", 'eval')
|
||||
resolved_expected = PythonNode(python_source, ast_, trimmed_source)
|
||||
assert sheerka.objvalue(current_res.predicate) == resolved_expected
|
||||
assert current_res.concept is None
|
||||
|
||||
current_res = res[3]
|
||||
assert isinstance(current_res, RuleCompiledPredicate)
|
||||
assert current_res.evaluator == PYTHON_EVALUATOR_NAME
|
||||
assert sheerka.isinstance(current_res.predicate, BuiltinConcepts.RETURN_VALUE)
|
||||
python_source = "__C__00var0000is0a000var001__1006__C__ and __C__00var0000is0an0y__1007__C__ and x > 5 and __C__00var0000is0a000var001__1006_1__C__"
|
||||
ast_ = ast.parse(python_source, "<source>", 'eval')
|
||||
resolved_expected = PythonNode(python_source, ast_, trimmed_source)
|
||||
assert sheerka.objvalue(current_res.predicate) == resolved_expected
|
||||
assert current_res.concept is None
|
||||
|
||||
@pytest.mark.parametrize("text, mode, compiled_text", [
|
||||
("greetings", "eval", f"__ret.status and isinstance(__ret.body, Concept) and __ret.body.name == 'greetings'"),
|
||||
("c:|1001:", "eval", f"__ret.status and isinstance(__ret.body, Concept) and __ret.body.id == '1001'"),
|
||||
("hello 'there'", "eval",
|
||||
f"__ret.status and isinstance(__ret.body, Concept) and __ret.body.key == 'hello __var__0' and __ret.body.get_value('a') == 'there'"),
|
||||
("hello there", "exec",
|
||||
f"__x_00__ = __ret.body.get_value('a')\n__ret.status and isinstance(__ret.body, Concept) and __ret.body.key == 'hello __var__0' and isinstance(__x_00__, Concept) and __x_00__.key == 'there'"),
|
||||
("hello my friend", "exec",
|
||||
f"__x_00__ = __ret.body.get_value('a')\n__ret.status and isinstance(__ret.body, Concept) and __ret.body.key == 'hello __var__0' and isinstance(__x_00__, Concept) and __x_00__.key == 'my friend'"),
|
||||
])
|
||||
def test_i_can_compile_predicate_when_concept_is_not_a_question(self, text, mode, compiled_text):
|
||||
sheerka, context, greetings, there, my_friend = self.init_test().with_concepts(
|
||||
Concept("greetings", definition="hello a", definition_type=DEFINITION_TYPE_DEF).def_var("a"),
|
||||
Concept("there"),
|
||||
Concept("my friend"),
|
||||
create_new=True
|
||||
).unpack()
|
||||
service = sheerka.services[SheerkaRuleManager.NAME]
|
||||
|
||||
ast_ = ast.parse(compiled_text, "<source>", mode)
|
||||
expected_python_node = PythonNode(compiled_text, ast_)
|
||||
|
||||
compiled_result = service.compile_when(context, "test", text)
|
||||
res = compiled_result.compiled_predicates
|
||||
|
||||
assert len(res) == 1
|
||||
assert isinstance(res[0], RuleCompiledPredicate)
|
||||
assert res[0].evaluator == PYTHON_EVALUATOR_NAME
|
||||
assert sheerka.isinstance(res[0].predicate, BuiltinConcepts.RETURN_VALUE)
|
||||
assert sheerka.objvalue(res[0].predicate) == expected_python_node
|
||||
assert res[0].concept is None
|
||||
|
||||
def test_i_can_compile_predicate_when_concept_is_not_a_question_and_involves_sheerka(self):
|
||||
sheerka, context, greetings = self.init_test().with_concepts(
|
||||
Concept("greetings", definition="hello a", definition_type=DEFINITION_TYPE_DEF).def_var("a"),
|
||||
create_new=True
|
||||
).unpack()
|
||||
service = sheerka.services[SheerkaRuleManager.NAME]
|
||||
|
||||
compiled_text = "__x_00__ = __ret.body.get_value('a')\n"
|
||||
compiled_text += "__ret.status"
|
||||
compiled_text += " and isinstance(__ret.body, Concept) and __ret.body.key == 'hello __var__0'"
|
||||
compiled_text += " and isinstance(__x_00__, Expando) and __x_00__.get_name() == 'sheerka'"
|
||||
ast_ = ast.parse(compiled_text, "<source>", "exec")
|
||||
expected_python_node = PythonNode(compiled_text, ast_)
|
||||
|
||||
compiled_result = service.compile_when(context, "test", "hello sheerka")
|
||||
res = compiled_result.compiled_predicates
|
||||
|
||||
assert len(res) == 1
|
||||
assert isinstance(res[0], RuleCompiledPredicate)
|
||||
assert res[0].evaluator == PYTHON_EVALUATOR_NAME
|
||||
assert sheerka.isinstance(res[0].predicate, BuiltinConcepts.RETURN_VALUE)
|
||||
assert sheerka.objvalue(res[0].predicate) == expected_python_node
|
||||
assert res[0].concept is None
|
||||
|
||||
@pytest.mark.skip("Not managed yet")
|
||||
def test_i_can_compile_when_concept_starts_with_not(self):
|
||||
sheerka, context, *concepts = self.init_test().with_concepts(
|
||||
Concept("not a cheesecake", pre="is_question()"),
|
||||
create_new=True).unpack()
|
||||
service = sheerka.services[SheerkaRuleManager.NAME]
|
||||
|
||||
text = "not a cheesecake"
|
||||
expected = concepts[0]
|
||||
|
||||
compiled_result = service.compile_when(context, "test", text)
|
||||
res = compiled_result.compiled_predicates
|
||||
|
||||
assert len(res) == 1
|
||||
assert isinstance(res[0], RuleCompiledPredicate)
|
||||
assert res[0].evaluator == CONCEPT_EVALUATOR_NAME
|
||||
assert sheerka.isinstance(res[0].predicate, BuiltinConcepts.RETURN_VALUE)
|
||||
assert sheerka.objvalue(res[0].predicate) == expected
|
||||
assert res[0].concept == expected
|
||||
|
||||
def test_i_cannot_compile_when_concept_is_not_a_question_and_has_unknown_variable(self):
|
||||
sheerka, context, greetings = self.init_test().with_concepts(
|
||||
Concept("greetings", definition="hello a", definition_type=DEFINITION_TYPE_DEF).def_var("a"),
|
||||
create_new=True
|
||||
).unpack()
|
||||
service = sheerka.services[SheerkaRuleManager.NAME]
|
||||
|
||||
with pytest.raises(FailedToCompileError) as ex:
|
||||
service.compile_when(context, "test", "hello there")
|
||||
|
||||
assert sheerka.isinstance(ex.value.cause[0], BuiltinConcepts.CONCEPT_EVAL_ERROR)
|
||||
|
||||
@pytest.mark.parametrize("text, expected_error", [
|
||||
("__action == 'some_action'", NoConditionFound())
|
||||
])
|
||||
def test_i_cannot_compile_when_error(self, text, expected_error):
|
||||
sheerka, context = self.init_test().unpack()
|
||||
service = sheerka.services[SheerkaRuleManager.NAME]
|
||||
|
||||
with pytest.raises(FailedToCompileError) as ex:
|
||||
service.compile_when(context, "test", text)
|
||||
|
||||
assert ex.value.cause == [expected_error]
|
||||
|
||||
def test_i_can_get_rule_priorities(self):
|
||||
sheerka, context, rule_true, rule_false = self.init_test().with_rules(("True", "True"),
|
||||
("False", "False")).unpack()
|
||||
sheerka, context, rule_true, rule_false = self.init_test().with_format_rules(("True", "True"),
|
||||
("False", "False")).unpack()
|
||||
|
||||
sheerka.set_is_greater_than(context, BuiltinConcepts.PRECEDENCE,
|
||||
rule_true,
|
||||
@@ -322,7 +800,7 @@ class TestSheerkaRuleManager(TestUsingMemoryBasedSheerka):
|
||||
assert rules_from_cache[rule_false.id].priority == 1
|
||||
|
||||
def test_i_can_get_and_retrieve_rules_when_multiple_ontology_layers(self):
|
||||
sheerka, context, rule_true = self.init_test().with_rules(("true", "True", "True")).unpack()
|
||||
sheerka, context, rule_true = self.init_test().with_format_rules(("true", "True", "True")).unpack()
|
||||
|
||||
sheerka.push_ontology(context, "new ontology")
|
||||
rule_false = sheerka.create_new_rule(context, Rule(ACTION_TYPE_EXEC, "false", "False", "False")).body.body
|
||||
@@ -331,12 +809,12 @@ class TestSheerkaRuleManager(TestUsingMemoryBasedSheerka):
|
||||
assert sheerka.get_rule_by_id(rule_true.id) == rule_true
|
||||
assert sheerka.get_rule_by_id(rule_false.id) == rule_false
|
||||
|
||||
sheerka.pop_ontology()
|
||||
sheerka.pop_ontology(context)
|
||||
assert sheerka.get_rule_by_id(rule_true.id) == rule_true
|
||||
assert not sheerka.is_known(sheerka.get_rule_by_id(rule_false.id))
|
||||
|
||||
def test_i_can_resolve_rule(self):
|
||||
sheerka, context, rule = self.init_test().with_rules(("my rule", "True", "True")).unpack()
|
||||
sheerka, context, rule = self.init_test().with_format_rules(("my rule", "True", "True")).unpack()
|
||||
context.add_to_short_term_memory("x", rule.id)
|
||||
|
||||
# direct access by id
|
||||
@@ -370,57 +848,175 @@ class TestSheerkaRuleManager(TestUsingMemoryBasedSheerka):
|
||||
unresolved.metadata.id_is_unresolved = True
|
||||
assert sheerka.resolve_rule(context, unresolved) == rule
|
||||
|
||||
# @pytest.mark.skip
|
||||
# @pytest.mark.parametrize("text, expected", [
|
||||
# ("cat is an animal", set()),
|
||||
# ("a is an animal", {"a"}),
|
||||
# ("a is an b", {"a", "b"}),
|
||||
# ("cat is an b", {"b"}),
|
||||
# ("a cat is an b", {"b"}),
|
||||
#
|
||||
# ("cat is a animal", set()),
|
||||
# ("a is a animal", {"a"}),
|
||||
# ("a is a b", {"a", "b"}),
|
||||
# ("cat is a b", {"b"}),
|
||||
# ("a cat is an b", {"b"}),
|
||||
#
|
||||
# ("a == 5", {"a"}),
|
||||
# ("isinstance(a, int)", {"a"}),
|
||||
# ("a cat == b", {"b"})
|
||||
# ])
|
||||
# def test_i_can_get_rules_variables(self, text, expected):
|
||||
# sheerka, context, *concepts = self.init_concepts(
|
||||
# Concept("x is a y", pre="is_question()", body="isinstance(x, y)").def_var("x").def_var("y"),
|
||||
# Concept("x is a y", pre="is_question()", body="isa(x, y)").def_var("x").def_var("y"),
|
||||
# Concept("x is an y", pre="is_question()", body="isinstance(x, y)").def_var("x").def_var("y"),
|
||||
# Concept("cat"),
|
||||
# Concept("animal"),
|
||||
# Concept("a cat"),
|
||||
# create_new=True
|
||||
# )
|
||||
# service = sheerka.services[SheerkaRuleManager.NAME]
|
||||
#
|
||||
# compiled = service.compile_when(context, "test", "a is a b")
|
||||
#
|
||||
# assert service.get_unknown_variables(compiled) == expected
|
||||
@pytest.mark.parametrize("obj, expected", [
|
||||
("text value", "var == 'text value'"),
|
||||
("text 'value'", '''var == "text 'value'"'''),
|
||||
('text "value"', """var == 'text "value"'"""),
|
||||
(10, "var == 10"),
|
||||
(10.01, "var == 10.01"),
|
||||
])
|
||||
def test_i_can_test_python_code_emitter_for_basic_types(self, obj, expected):
|
||||
sheerka, context = self.init_test().unpack()
|
||||
|
||||
assert PythonCodeEmitter(context).recognize(obj, "var").get_text() == expected
|
||||
assert PythonCodeEmitter(context, "status").recognize(obj, "var").get_text() == "status and " + expected
|
||||
|
||||
@pytest.mark.parametrize("recognized_by, expected", [
|
||||
(RECOGNIZED_BY_ID, "isinstance(var, Concept) and var.id == '1001'"),
|
||||
(RECOGNIZED_BY_NAME, "isinstance(var, Concept) and var.name == 'greetings'"),
|
||||
(None, "isinstance(var, Concept) and var.key == 'hello'"),
|
||||
])
|
||||
def test_i_can_test_python_code_emitter_for_concepts(self, recognized_by, expected):
|
||||
sheerka, context, foo = self.init_concepts(
|
||||
Concept("greetings", definition="hello", definition_type=DEFINITION_TYPE_DEF))
|
||||
|
||||
instance = sheerka.new_from_template(foo, foo.key)
|
||||
if recognized_by:
|
||||
instance.set_hint(BuiltinConcepts.RECOGNIZED_BY, recognized_by)
|
||||
|
||||
assert PythonCodeEmitter(context).recognize(instance, "var").get_text() == expected
|
||||
assert PythonCodeEmitter(context, "status").recognize(instance, "var").get_text() == "status and " + expected
|
||||
|
||||
def test_i_can_test_python_code_emitter_for_concepts_with_variable(self):
|
||||
sheerka, context, greetings, little, foo, bar, and_concept = self.init_concepts(
|
||||
Concept("greetings", definition="hello a", definition_type=DEFINITION_TYPE_DEF).def_var("a"),
|
||||
Concept("little x").def_var("x"),
|
||||
"foo",
|
||||
"bar",
|
||||
Concept("a and b").def_var("a").def_var("b")
|
||||
)
|
||||
|
||||
# variable is a string
|
||||
greetings_instance = sheerka.new_from_template(greetings, greetings.key, a='sheerka')
|
||||
expected = "isinstance(var, Concept) and var.key == 'hello __var__0' and var.get_value('a') == 'sheerka'"
|
||||
text = PythonCodeEmitter(context).recognize(greetings_instance, "var").get_text()
|
||||
assert text == expected
|
||||
|
||||
# variable is a concept recognized by id
|
||||
foo_instance = sheerka.new_from_template(foo, foo.key)
|
||||
foo_instance.set_hint(BuiltinConcepts.RECOGNIZED_BY, RECOGNIZED_BY_ID)
|
||||
greetings_instance = sheerka.new_from_template(greetings, greetings.key, a=foo_instance)
|
||||
expected = """__x_00__ = var.get_value('a')
|
||||
isinstance(var, Concept) and var.key == 'hello __var__0' and isinstance(__x_00__, Concept) and __x_00__.id == '1003'"""
|
||||
text = PythonCodeEmitter(context).recognize(greetings_instance, "var").get_text()
|
||||
assert text == expected
|
||||
|
||||
# variable is a concept recognized by name
|
||||
foo_instance = sheerka.new_from_template(foo, foo.key)
|
||||
foo_instance.set_hint(BuiltinConcepts.RECOGNIZED_BY, RECOGNIZED_BY_NAME)
|
||||
greetings_instance = sheerka.new_from_template(greetings, greetings.key, a=foo_instance)
|
||||
expected = """__x_00__ = var.get_value('a')
|
||||
isinstance(var, Concept) and var.key == 'hello __var__0' and isinstance(__x_00__, Concept) and __x_00__.name == 'foo'"""
|
||||
text = PythonCodeEmitter(context).recognize(greetings_instance, "var").get_text()
|
||||
assert text == expected
|
||||
|
||||
# variable is a concept recognized by value
|
||||
foo_instance = sheerka.new_from_template(foo, foo.key)
|
||||
greetings_instance = sheerka.new_from_template(greetings, greetings.key, a=foo_instance)
|
||||
expected = """__x_00__ = var.get_value('a')
|
||||
isinstance(var, Concept) and var.key == 'hello __var__0' and isinstance(__x_00__, Concept) and __x_00__.key == 'foo'"""
|
||||
text = PythonCodeEmitter(context).recognize(greetings_instance, "var").get_text()
|
||||
assert text == expected
|
||||
|
||||
# variable is a concept witch has itself some variable
|
||||
foo_instance = sheerka.new_from_template(foo, foo.key)
|
||||
little_instance = sheerka.new_from_template(little, little.key, x=foo_instance)
|
||||
greetings_instance = sheerka.new_from_template(greetings, greetings.key, a=little_instance)
|
||||
expected = """__x_00__ = var.get_value('a')
|
||||
__x_01__ = __x_00__.get_value('x')
|
||||
isinstance(var, Concept) and var.key == 'hello __var__0'""" + \
|
||||
" and isinstance(__x_00__, Concept) and __x_00__.key == 'little __var__0'" + \
|
||||
" and isinstance(__x_01__, Concept) and __x_01__.key == 'foo'"""
|
||||
text = PythonCodeEmitter(context).recognize(greetings_instance, "var").get_text()
|
||||
assert text == expected
|
||||
|
||||
# concept with multiple variables (which are themselves concepts)
|
||||
foo_instance = sheerka.new_from_template(foo, foo.key)
|
||||
bar_instance = sheerka.new_from_template(bar, bar.key)
|
||||
little_instance = sheerka.new_from_template(little, little.key, x=foo_instance)
|
||||
and_instance = sheerka.new_from_template(and_concept, and_concept.key, a=bar_instance, b=little_instance)
|
||||
greetings_instance = sheerka.new_from_template(greetings, greetings.key, a=and_instance)
|
||||
expected = """__x_00__ = var.get_value('a')
|
||||
__x_01__ = __x_00__.get_value('a')
|
||||
__x_02__ = __x_00__.get_value('b')
|
||||
__x_03__ = __x_02__.get_value('x')
|
||||
isinstance(var, Concept) and var.key == 'hello __var__0'""" + \
|
||||
" and isinstance(__x_00__, Concept) and __x_00__.key == '__var__0 and __var__1'" + \
|
||||
" and isinstance(__x_01__, Concept) and __x_01__.key == 'bar'" + \
|
||||
" and isinstance(__x_02__, Concept) and __x_02__.key == 'little __var__0'" + \
|
||||
" and isinstance(__x_03__, Concept) and __x_03__.key == 'foo'"
|
||||
text = PythonCodeEmitter(context).recognize(greetings_instance, "var").get_text()
|
||||
assert text == expected
|
||||
|
||||
def test_i_can_get_format_rules(self):
|
||||
sheerka, context = self.init_test().unpack()
|
||||
service = sheerka.services[SheerkaRuleManager.NAME]
|
||||
|
||||
sheerka.om.current_cache_manager().clear(service.FORMAT_RULE_ENTRY)
|
||||
r1 = Rule(ACTION_TYPE_PRINT, "name 1", "True", "Hello world 1", priority=1)
|
||||
r2 = Rule(ACTION_TYPE_PRINT, "name 2", "False", "Hello world 2", priority=3)
|
||||
r3 = Rule(ACTION_TYPE_PRINT, "name 2", "None", "Hello world 3", priority=2)
|
||||
sheerka.create_new_rule(context, r1)
|
||||
sheerka.create_new_rule(context, r2)
|
||||
sheerka.create_new_rule(context, r3)
|
||||
|
||||
res = sheerka.get_format_rules()
|
||||
assert res == [r2, r3, r1]
|
||||
|
||||
def test_i_can_get_exec_rules(self):
|
||||
sheerka, context = self.init_test().unpack()
|
||||
service = sheerka.services[SheerkaRuleManager.NAME]
|
||||
|
||||
sheerka.om.current_cache_manager().clear(service.EXEC_RULE_ENTRY)
|
||||
r1 = Rule(ACTION_TYPE_EXEC, "name 1", "True", "'Hello world 1'", priority=1)
|
||||
r2 = Rule(ACTION_TYPE_EXEC, "name 2", "False", "'Hello world 2'", priority=3)
|
||||
r3 = Rule(ACTION_TYPE_EXEC, "name 2", "None", "'Hello world 3'", priority=2)
|
||||
sheerka.create_new_rule(context, r1)
|
||||
sheerka.create_new_rule(context, r2)
|
||||
sheerka.create_new_rule(context, r3)
|
||||
|
||||
res = sheerka.get_exec_rules()
|
||||
assert res == [r2, r3, r1]
|
||||
|
||||
def test_i_can_compile_rete_using_name(self):
|
||||
sheerka, context, *concepts = self.init_test().unpack()
|
||||
service = sheerka.services[SheerkaRuleManager.NAME]
|
||||
|
||||
text = "__ret"
|
||||
|
||||
compiled_result = service.compile_when(context, "test", text)
|
||||
res = compiled_result.rete_disjunctions
|
||||
|
||||
assert len(res) == 1
|
||||
assert isinstance(res[0], AndConditions)
|
||||
assert res[0].conditions == [Condition(V("__x_00__"), "__name__", "__ret")]
|
||||
|
||||
|
||||
class TestSheerkaRuleManagerUsingFileBasedSheerka(TestUsingFileBasedSheerka):
|
||||
def test_rules_are_initialized_at_startup(self):
|
||||
sheerka, context, *rules = self.init_format_rules(
|
||||
sheerka, context, *rules = self.init_test().with_rules(
|
||||
None,
|
||||
Rule("print", "name1", "True", "Hello world"),
|
||||
Rule("print", "name2", "value() is __EXPLANATION", "list(value())")
|
||||
)
|
||||
Rule("print", "name2", "value() is __EXPLANATION", "list(value())"),
|
||||
Rule("exec", "name3", "True", "'Hello world'"),
|
||||
Rule("exec", "name4", "value() is __EXPLANATION", "list(value())"),
|
||||
).unpack()
|
||||
sheerka.set_is_greater_than(context, BuiltinConcepts.PRECEDENCE,
|
||||
rules[0],
|
||||
rules[1],
|
||||
RULE_COMPARISON_CONTEXT)
|
||||
sheerka.set_is_less_than(context, BuiltinConcepts.PRECEDENCE,
|
||||
rules[2],
|
||||
rules[3],
|
||||
RULE_COMPARISON_CONTEXT)
|
||||
|
||||
sheerka.om.commit(context)
|
||||
expected_rules_by_id = sheerka.om.get_all(SheerkaRuleManager.FORMAT_RULE_ENTRY)
|
||||
expected_rules_by_id.update(sheerka.om.get_all(SheerkaRuleManager.EXEC_RULE_ENTRY))
|
||||
|
||||
sheerka = self.new_sheerka_instance(False) # new instance
|
||||
rules_by_id = sheerka.om.get_all(SheerkaRuleManager.FORMAT_RULE_ENTRY)
|
||||
rules_by_id.update(sheerka.om.get_all(SheerkaRuleManager.EXEC_RULE_ENTRY))
|
||||
|
||||
assert len(rules_by_id) == len(expected_rules_by_id)
|
||||
|
||||
@@ -432,10 +1028,10 @@ class TestSheerkaRuleManagerUsingFileBasedSheerka(TestUsingFileBasedSheerka):
|
||||
assert rule.metadata.predicate == expected.metadata.predicate
|
||||
assert rule.metadata.action == expected.metadata.action
|
||||
assert rule.metadata.id == expected.metadata.id
|
||||
assert rule.metadata.is_compiled == expected.metadata.is_compiled
|
||||
assert rule.metadata.is_enabled == expected.metadata.is_enabled
|
||||
assert rule.metadata.is_compiled
|
||||
assert rule.metadata.is_enabled
|
||||
assert rule.compiled_action == expected.compiled_action
|
||||
assert rule.compiled_predicate == expected.compiled_predicate
|
||||
assert rule.compiled_predicates == expected.compiled_predicates
|
||||
assert rule.priority is not None
|
||||
assert rule.priority == expected.priority
|
||||
|
||||
@@ -468,6 +1064,6 @@ class TestSheerkaRuleManagerUsingFileBasedSheerka(TestUsingFileBasedSheerka):
|
||||
assert rule.metadata.is_compiled == expected.metadata.is_compiled
|
||||
assert rule.metadata.is_enabled == expected.metadata.is_enabled
|
||||
assert rule.compiled_action == expected.compiled_action
|
||||
assert rule.compiled_predicate == expected.compiled_predicate
|
||||
assert rule.compiled_predicates == expected.compiled_predicates
|
||||
assert rule.priority is not None
|
||||
assert rule.priority == expected.priority
|
||||
|
||||
@@ -110,11 +110,11 @@ class TestSheerkaVariable(TestUsingMemoryBasedSheerka):
|
||||
assert sheerka.load_internal_var("TestSheerkaVariable", "lambda")(10) == 12
|
||||
|
||||
# I can revert back
|
||||
sheerka.pop_ontology()
|
||||
sheerka.pop_ontology(context)
|
||||
assert sheerka.load_var("TestSheerkaVariable", "my_variable") == 1
|
||||
assert sheerka.load_internal_var("TestSheerkaVariable", "lambda")(10) == 11
|
||||
|
||||
sheerka.pop_ontology()
|
||||
sheerka.pop_ontology(context)
|
||||
assert sheerka.load_var("TestSheerkaVariable", "my_variable") == 1
|
||||
assert sheerka.load_internal_var("TestSheerkaVariable", "lambda")(10) == 11
|
||||
|
||||
|
||||
@@ -1,10 +1,9 @@
|
||||
import ast
|
||||
import pytest
|
||||
|
||||
import core.builtin_helpers
|
||||
import pytest
|
||||
from core.builtin_concepts import ReturnValueConcept, BuiltinConcepts
|
||||
from core.concept import Concept
|
||||
|
||||
from core.global_symbols import NotInit
|
||||
from tests.TestUsingMemoryBasedSheerka import TestUsingMemoryBasedSheerka
|
||||
|
||||
|
||||
@@ -157,6 +156,32 @@ class TestBuiltinHelpers(TestUsingMemoryBasedSheerka):
|
||||
res = core.builtin_helpers.resolve_ambiguity(context, concepts)
|
||||
assert [c.name for c in res] == expected
|
||||
|
||||
@pytest.mark.parametrize("pre, expected", [
|
||||
("x and y", False),
|
||||
("is_question()", True),
|
||||
(" is_question ( ) ", True),
|
||||
("context.in_context(BuiltinConcepts.EVAL_QUESTION_REQUESTED)", True),
|
||||
(" context . in_context ( BuiltinConcepts . EVAL_QUESTION_REQUESTED ) ", True),
|
||||
(None, False),
|
||||
("", False),
|
||||
(NotInit, False),
|
||||
("is _ question()", False),
|
||||
("is_ question()", False),
|
||||
("is _question()", False),
|
||||
("context.in _context(BuiltinConcepts.EVAL_QUESTION_REQUESTED)", False),
|
||||
("not is_question()", False),
|
||||
("not context.in_context(BuiltinConcepts.EVAL_QUESTION_REQUESTED)", False),
|
||||
("is_question() and True", True),
|
||||
("is_question() and False", True), # don't care about the second argument if it is not related to question
|
||||
("is_question() and xxx", True), # don't care about the second argument if it is not related to question
|
||||
("is_question() and not is_question()", False), # error ?
|
||||
("is_question() and not context.in_context(BuiltinConcepts.EVAL_QUESTION_REQUESTED)", False), # error ?
|
||||
])
|
||||
def test_is_a_question(self, pre, expected):
|
||||
sheerka, context = self.init_test().unpack()
|
||||
concept = Concept("foo", pre=pre)
|
||||
assert core.builtin_helpers.is_a_question(context, concept) == expected
|
||||
|
||||
# @pytest.mark.parametrize("return_values", [
|
||||
# None,
|
||||
# []
|
||||
|
||||
@@ -340,7 +340,7 @@ class TestSheerkaUsingMemoryBasedSheerka(TestUsingMemoryBasedSheerka):
|
||||
sheerka.modify_concept(context, foo, to_add={"variables": {"c": None}}, to_remove={"variables": ["b"]})
|
||||
assert get_concept_attrs(foo) == ["a", "c"]
|
||||
|
||||
sheerka.pop_ontology()
|
||||
sheerka.pop_ontology(context)
|
||||
assert get_concept_attrs(foo) == ["a", "b"]
|
||||
|
||||
def test_i_can_manage_concepts_ids_on_multiple_ontology_layers(self):
|
||||
@@ -356,7 +356,7 @@ class TestSheerkaUsingMemoryBasedSheerka(TestUsingMemoryBasedSheerka):
|
||||
res = sheerka.create_new_concept(context, Concept("baz"))
|
||||
assert res.body.body.id == "1003"
|
||||
|
||||
sheerka.pop_ontology()
|
||||
sheerka.pop_ontology(context)
|
||||
res = sheerka.create_new_concept(context, Concept("baz"))
|
||||
assert res.body.body.id == "1002"
|
||||
|
||||
@@ -380,7 +380,7 @@ class TestSheerkaUsingMemoryBasedSheerka(TestUsingMemoryBasedSheerka):
|
||||
|
||||
# record the ontology
|
||||
ontology = sheerka.get_ontology(context)
|
||||
sheerka.pop_ontology()
|
||||
sheerka.pop_ontology(context)
|
||||
|
||||
# Create another ontology with some other values
|
||||
sheerka.push_ontology(context, "another ontology")
|
||||
@@ -403,7 +403,7 @@ class TestSheerkaUsingMemoryBasedSheerka(TestUsingMemoryBasedSheerka):
|
||||
assert get_concept_attrs(foo) == ["a", "b"]
|
||||
|
||||
# sanity check
|
||||
sheerka.pop_ontology()
|
||||
sheerka.pop_ontology(context)
|
||||
assert sheerka.get_by_name("foo") == foo2
|
||||
assert sheerka.get_by_name("bar") == bar
|
||||
assert sheerka.locals == {"key2": "value2"}
|
||||
@@ -562,7 +562,7 @@ class TestSheerkaUsingFileBasedSheerka(TestUsingFileBasedSheerka):
|
||||
sheerka, context = self.init_test().unpack()
|
||||
|
||||
sheerka.push_ontology(context, "to remove")
|
||||
sheerka.pop_ontology()
|
||||
sheerka.pop_ontology(context)
|
||||
sheerka.push_ontology(context, "new ontology")
|
||||
sheerka.push_ontology(context, "another ontology")
|
||||
|
||||
|
||||
@@ -21,7 +21,7 @@ class TestSheerkaResultManager(TestUsingMemoryBasedSheerka):
|
||||
|
||||
@classmethod
|
||||
def teardown_class(cls):
|
||||
cls.sheerka.pop_ontology()
|
||||
cls.sheerka.pop_ontology(TestSheerkaResultManager.context)
|
||||
cls.root_ontology_name = SheerkaOntologyManager.ROOT_ONTOLOGY_NAME
|
||||
|
||||
def init_service(self):
|
||||
@@ -410,7 +410,7 @@ class TestSheerkaResultManagerFileBased(TestUsingFileBasedSheerka):
|
||||
|
||||
@classmethod
|
||||
def teardown_class(cls):
|
||||
cls.sheerka.pop_ontology()
|
||||
cls.sheerka.pop_ontology(TestSheerkaResultManagerFileBased.context)
|
||||
cls.root_ontology_name = SheerkaOntologyManager.ROOT_ONTOLOGY_NAME
|
||||
|
||||
def test_i_can_retrieve_the_last_error_after_startup(self):
|
||||
|
||||
@@ -8,7 +8,9 @@ from cache.IncCache import IncCache
|
||||
from cache.ListCache import ListCache
|
||||
from cache.ListIfNeededCache import ListIfNeededCache
|
||||
from core.concept import Concept
|
||||
from core.global_symbols import NotFound, Removed
|
||||
from core.global_symbols import NotFound, Removed, EVENT_CONCEPT_ID_DELETED, \
|
||||
EVENT_RULE_ID_DELETED
|
||||
from core.rule import Rule, ACTION_TYPE_EXEC
|
||||
from core.sheerka.SheerkaOntologyManager import SheerkaOntologyManager, OntologyManagerFrozen, OntologyManagerNotFrozen, \
|
||||
OntologyManagerCannotPopLatest, OntologyAlreadyExists
|
||||
from tests.TestUsingFileBasedSheerka import TestUsingFileBasedSheerka
|
||||
@@ -168,22 +170,22 @@ class TestSheerkaOntology(TestUsingMemoryBasedSheerka):
|
||||
assert manager.current_cache_manager().has("cache_name", "key")
|
||||
|
||||
def test_i_cannot_pop_ontology_when_not_frozen(self):
|
||||
sheerka = self.get_sheerka()
|
||||
sheerka, context = self.init_test().unpack()
|
||||
manager = SheerkaOntologyManager(sheerka, sheerka.root_folder, sheerka.cache_only)
|
||||
|
||||
with pytest.raises(OntologyManagerNotFrozen):
|
||||
manager.pop_ontology()
|
||||
manager.pop_ontology(context)
|
||||
|
||||
def test_i_cannot_pop_the_latest_cache_manager(self):
|
||||
sheerka = self.get_sheerka()
|
||||
sheerka, context = self.init_test().unpack()
|
||||
manager = SheerkaOntologyManager(sheerka, sheerka.root_folder, sheerka.cache_only)
|
||||
manager.freeze()
|
||||
|
||||
with pytest.raises(OntologyManagerCannotPopLatest):
|
||||
manager.pop_ontology()
|
||||
manager.pop_ontology(context)
|
||||
|
||||
def test_i_can_pop_ontology(self):
|
||||
sheerka = self.get_sheerka()
|
||||
sheerka, context = self.init_test().unpack()
|
||||
manager = SheerkaOntologyManager(sheerka, sheerka.root_folder, sheerka.cache_only)
|
||||
manager.freeze()
|
||||
|
||||
@@ -191,13 +193,13 @@ class TestSheerkaOntology(TestUsingMemoryBasedSheerka):
|
||||
manager.push_ontology("ontology2")
|
||||
manager.push_ontology("ontology3")
|
||||
|
||||
manager.pop_ontology()
|
||||
manager.pop_ontology(context)
|
||||
assert len(manager.ontologies) == 3
|
||||
|
||||
manager.pop_ontology()
|
||||
manager.pop_ontology()
|
||||
manager.pop_ontology(context)
|
||||
manager.pop_ontology(context)
|
||||
with pytest.raises(OntologyManagerCannotPopLatest):
|
||||
manager.pop_ontology()
|
||||
manager.pop_ontology(context)
|
||||
|
||||
def test_i_can_add_ontology(self):
|
||||
sheerka, context = self.init_test().unpack()
|
||||
@@ -217,7 +219,7 @@ class TestSheerkaOntology(TestUsingMemoryBasedSheerka):
|
||||
assert manager.get("cache_name", "key3") is NotFound
|
||||
|
||||
new_ontology = manager.get_ontology()
|
||||
manager.pop_ontology()
|
||||
manager.pop_ontology(context)
|
||||
|
||||
# add another ontology, with its own values
|
||||
manager.push_ontology("another ontology")
|
||||
@@ -250,7 +252,7 @@ class TestSheerkaOntology(TestUsingMemoryBasedSheerka):
|
||||
assert manager.get_ontology("name4")
|
||||
|
||||
def test_i_can_access_values_after_push_and_pop_cache_only_true(self):
|
||||
sheerka = self.get_sheerka(cache_only=True)
|
||||
sheerka, context = self.init_test(cache_only=True).unpack()
|
||||
|
||||
manager = SheerkaOntologyManager(sheerka, sheerka.root_folder, sheerka.cache_only)
|
||||
manager.register_cache("cache_name", Cache())
|
||||
@@ -263,7 +265,7 @@ class TestSheerkaOntology(TestUsingMemoryBasedSheerka):
|
||||
manager.put("cache_name", "key", "value2")
|
||||
assert manager.get("cache_name", "key") == "value2"
|
||||
|
||||
manager.pop_ontology()
|
||||
manager.pop_ontology(context)
|
||||
assert manager.get("cache_name", "key") == "value1"
|
||||
|
||||
def test_i_can_access_values_after_push_and_pop_cache_only_false(self):
|
||||
@@ -296,7 +298,7 @@ class TestSheerkaOntology(TestUsingMemoryBasedSheerka):
|
||||
assert manager.ontologies[1].cache_manager.sdp.state.data == {'cache_name': {'key': 'value1'}}
|
||||
|
||||
# remove a layer
|
||||
manager.pop_ontology()
|
||||
manager.pop_ontology(context)
|
||||
assert not manager.current_cache_manager().has("cache_name", "key") # value is no longer in cache
|
||||
assert manager.get("cache_name", "key") == "value1"
|
||||
|
||||
@@ -333,13 +335,13 @@ class TestSheerkaOntology(TestUsingMemoryBasedSheerka):
|
||||
|
||||
assert manager.get("cache_name", "key") == "value4"
|
||||
|
||||
manager.pop_ontology()
|
||||
manager.pop_ontology(context)
|
||||
assert manager.get("cache_name", "key") == "value3"
|
||||
|
||||
manager.pop_ontology()
|
||||
manager.pop_ontology(context)
|
||||
assert manager.get("cache_name", "key") == "value2"
|
||||
|
||||
manager.pop_ontology()
|
||||
manager.pop_ontology(context)
|
||||
assert manager.get("cache_name", "key") == "value1"
|
||||
|
||||
def test_i_have_access_to_sub_layers_values_cache_only_false(self):
|
||||
@@ -368,6 +370,7 @@ class TestSheerkaOntology(TestUsingMemoryBasedSheerka):
|
||||
|
||||
def test_i_can_get_value_from_all_layers(self):
|
||||
sheerka = self.get_sheerka(cache_only=False)
|
||||
context = self.get_context(sheerka)
|
||||
|
||||
manager = SheerkaOntologyManager(sheerka, sheerka.root_folder, sheerka.cache_only)
|
||||
manager.register_cache("cache_name", Cache().auto_configure("cache_name"))
|
||||
@@ -381,14 +384,15 @@ class TestSheerkaOntology(TestUsingMemoryBasedSheerka):
|
||||
|
||||
assert manager.get("cache_name", "key") == "value"
|
||||
|
||||
manager.pop_ontology()
|
||||
manager.pop_ontology(context)
|
||||
assert manager.get("cache_name", "key") == "value"
|
||||
|
||||
manager.pop_ontology()
|
||||
manager.pop_ontology(context)
|
||||
assert manager.get("cache_name", "key") == "value"
|
||||
|
||||
def test_i_can_only_get_top_layer_values_when_dictionary_cache(self):
|
||||
sheerka = self.get_sheerka()
|
||||
context = self.get_context(sheerka)
|
||||
|
||||
manager = SheerkaOntologyManager(sheerka, sheerka.root_folder, sheerka.cache_only)
|
||||
manager.register_cache("cache_name", DictionaryCache().auto_configure("cache_name"))
|
||||
@@ -407,7 +411,7 @@ class TestSheerkaOntology(TestUsingMemoryBasedSheerka):
|
||||
assert manager.get_all("cache_name") == {"key": "value", "key1": "value1"}
|
||||
|
||||
# I can get back my values after pop
|
||||
manager.pop_ontology()
|
||||
manager.pop_ontology(context)
|
||||
assert manager.copy("cache_name") == {"key": "value"}
|
||||
|
||||
def test_dictionary_caches_values_are_copied_when_a_new_ontology_is_pushed(self):
|
||||
@@ -728,7 +732,7 @@ class TestSheerkaOntology(TestUsingMemoryBasedSheerka):
|
||||
assert manager.ontologies[1].cache_manager.sdp.state.data == {'cache_name': {"key": "value"}}
|
||||
|
||||
# The entry still exists in lower ontology
|
||||
manager.pop_ontology()
|
||||
manager.pop_ontology(context)
|
||||
assert manager.get("cache_name", "key") == "value"
|
||||
|
||||
def test_i_can_remove_when_value_is_in_both_low_and_current_level(self):
|
||||
@@ -764,7 +768,7 @@ class TestSheerkaOntology(TestUsingMemoryBasedSheerka):
|
||||
assert manager.ontologies[1].cache_manager.sdp.state.data == {'cache_name': {"key": "value"}}
|
||||
|
||||
# The entry still exists in lower ontology
|
||||
manager.pop_ontology()
|
||||
manager.pop_ontology(context)
|
||||
assert manager.get("cache_name", "key") == "value"
|
||||
|
||||
def test_i_can_remove_when_value_is_not_low_level(self):
|
||||
@@ -830,8 +834,8 @@ class TestSheerkaOntology(TestUsingMemoryBasedSheerka):
|
||||
assert manager.ontologies[2].cache_manager.sdp.state.data == {'cache_name': {"key": ["value", "value2"]}}
|
||||
|
||||
# The entry still exists in lower ontology
|
||||
manager.pop_ontology()
|
||||
manager.pop_ontology()
|
||||
manager.pop_ontology(context)
|
||||
manager.pop_ontology(context)
|
||||
assert manager.get("cache_name", "key") == ["value", "value2"]
|
||||
|
||||
def test_i_can_add_concept_default_layer(self):
|
||||
@@ -941,7 +945,7 @@ class TestSheerkaOntology(TestUsingMemoryBasedSheerka):
|
||||
assert manager.ontologies[1].cache_manager.sdp.get('by_id', foo.id) == foo
|
||||
|
||||
# so I can get the old values when I pop ontology
|
||||
manager.pop_ontology()
|
||||
manager.pop_ontology(context)
|
||||
assert manager.get("by_key", foo.key) == foo
|
||||
assert manager.get("by_id", foo.id) == foo
|
||||
|
||||
@@ -990,7 +994,7 @@ class TestSheerkaOntology(TestUsingMemoryBasedSheerka):
|
||||
assert manager.ontologies[1].cache_manager.sdp.get('by_id', foo.id) == foo
|
||||
|
||||
# so I can get the old values when I pop ontology
|
||||
manager.pop_ontology()
|
||||
manager.pop_ontology(context)
|
||||
assert manager.get("by_key", foo.key) == foo
|
||||
assert manager.get("by_id", foo.id) == foo
|
||||
|
||||
@@ -1119,12 +1123,12 @@ class TestSheerkaOntology(TestUsingMemoryBasedSheerka):
|
||||
assert manager.ontologies[2].cache_manager.sdp.get("by_key") == {foo.key: foo}
|
||||
|
||||
# So I can pop
|
||||
manager.pop_ontology()
|
||||
manager.pop_ontology(context)
|
||||
assert manager.get("by_id", foo.id) == foo
|
||||
assert manager.get("by_key", foo.key) == foo
|
||||
|
||||
# and pop again
|
||||
manager.pop_ontology()
|
||||
manager.pop_ontology(context)
|
||||
assert manager.get("by_id", foo.id) == foo
|
||||
assert manager.get("by_key", foo.key) == foo
|
||||
|
||||
@@ -1167,6 +1171,145 @@ class TestSheerkaOntology(TestUsingMemoryBasedSheerka):
|
||||
"key5": "value5"
|
||||
}
|
||||
|
||||
def test_i_can_keep_track_of_created_concepts_by_ontologies(self):
|
||||
sheerka, context, foo = self.init_concepts("foo", create_new=True)
|
||||
|
||||
def from_cache(entry):
|
||||
return sheerka.om.self_cache_manager.copy(entry)
|
||||
|
||||
def from_db(entry):
|
||||
return sheerka.om.self_cache_manager.sdp.get(entry)
|
||||
|
||||
# check that the new concept is tracked
|
||||
assert from_cache(SheerkaOntologyManager.CONCEPTS_BY_ONTOLOGY_ENTRY) == {'#unit_test#': {'1001'}}
|
||||
assert from_cache(SheerkaOntologyManager.ONTOLOGY_BY_CONCEPT_ENTRY) == {'1001': '#unit_test#'}
|
||||
|
||||
# add a new ontology and make sure the new concepts are tracked
|
||||
sheerka.push_ontology(context, "new ontology")
|
||||
sheerka.create_new_concept(context, Concept("bar"))
|
||||
assert from_cache(SheerkaOntologyManager.CONCEPTS_BY_ONTOLOGY_ENTRY) == {'#unit_test#': {'1001'},
|
||||
'new ontology': {'1002'}}
|
||||
assert from_cache(SheerkaOntologyManager.ONTOLOGY_BY_CONCEPT_ENTRY) == {'1001': '#unit_test#',
|
||||
'1002': 'new ontology'}
|
||||
|
||||
# commit the info and check the DB
|
||||
sheerka.om.commit(context)
|
||||
assert from_db(SheerkaOntologyManager.CONCEPTS_BY_ONTOLOGY_ENTRY) == {'#unit_test#': {'1001'},
|
||||
'new ontology': {'1002'}, }
|
||||
assert from_db(SheerkaOntologyManager.ONTOLOGY_BY_CONCEPT_ENTRY) == {'1001': '#unit_test#',
|
||||
'1002': 'new ontology', }
|
||||
|
||||
# remove a concept a check
|
||||
sheerka.remove_concept(context, sheerka.get_by_name("foo"))
|
||||
assert from_cache(SheerkaOntologyManager.CONCEPTS_BY_ONTOLOGY_ENTRY) == {'new ontology': {'1002'}, }
|
||||
assert from_cache(SheerkaOntologyManager.ONTOLOGY_BY_CONCEPT_ENTRY) == {'1002': 'new ontology', }
|
||||
|
||||
sheerka.remove_concept(context, sheerka.get_by_name("bar"))
|
||||
assert from_cache(SheerkaOntologyManager.CONCEPTS_BY_ONTOLOGY_ENTRY) == {}
|
||||
assert from_cache(SheerkaOntologyManager.ONTOLOGY_BY_CONCEPT_ENTRY) == {}
|
||||
|
||||
# commit again and check
|
||||
sheerka.om.commit(context)
|
||||
assert from_db(SheerkaOntologyManager.CONCEPTS_BY_ONTOLOGY_ENTRY) == {}
|
||||
assert from_db(SheerkaOntologyManager.ONTOLOGY_BY_CONCEPT_ENTRY) == {}
|
||||
|
||||
def test_i_can_keep_track_of_created_rules_by_ontologies(self):
|
||||
sheerka, context, rule1 = self.init_format_rules(("rule1", "id.attr == 'value'", "True"))
|
||||
|
||||
def rules_by_ontology_from_cache():
|
||||
res = sheerka.om.self_cache_manager.copy(SheerkaOntologyManager.RULES_BY_ONTOLOGY_ENTRY)
|
||||
del res[SheerkaOntologyManager.ROOT_ONTOLOGY_NAME] # discard builtin rules
|
||||
return res
|
||||
|
||||
def ontologies_from_cache():
|
||||
res = sheerka.om.self_cache_manager.copy(SheerkaOntologyManager.ONTOLOGY_BY_RULE_ENTRY)
|
||||
return {k: v for k, v in res.items() if v != SheerkaOntologyManager.ROOT_ONTOLOGY_NAME}
|
||||
|
||||
def rules_by_ontology_from_db():
|
||||
res = sheerka.om.self_cache_manager.sdp.get(SheerkaOntologyManager.RULES_BY_ONTOLOGY_ENTRY)
|
||||
del res[SheerkaOntologyManager.ROOT_ONTOLOGY_NAME] # discard builtin rules
|
||||
return res
|
||||
|
||||
def ontologies_from_db():
|
||||
res = sheerka.om.self_cache_manager.sdp.get(SheerkaOntologyManager.ONTOLOGY_BY_RULE_ENTRY)
|
||||
return {k: v for k, v in res.items() if v != SheerkaOntologyManager.ROOT_ONTOLOGY_NAME}
|
||||
|
||||
assert rules_by_ontology_from_cache() == {"#unit_test#": {rule1.id}}
|
||||
assert ontologies_from_cache() == {rule1.id: "#unit_test#"}
|
||||
|
||||
# add a new rule from a new ontology and check
|
||||
sheerka.push_ontology(context, "new ontology")
|
||||
rule2 = Rule(ACTION_TYPE_EXEC, "rule2", "id2.attr2 == 'value'", "True")
|
||||
sheerka.create_new_rule(context, rule2)
|
||||
|
||||
assert rules_by_ontology_from_cache() == {"#unit_test#": {rule1.id}, "new ontology": {rule2.id}}
|
||||
assert ontologies_from_cache() == {rule1.id: "#unit_test#", rule2.id: "new ontology"}
|
||||
|
||||
# commit and check the result
|
||||
sheerka.om.commit(context)
|
||||
assert rules_by_ontology_from_db() == {"#unit_test#": {rule1.id}, "new ontology": {rule2.id}}
|
||||
assert ontologies_from_db() == {rule1.id: "#unit_test#", rule2.id: "new ontology"}
|
||||
|
||||
sheerka.remove_rule(context, rule1)
|
||||
assert rules_by_ontology_from_cache() == {"new ontology": {rule2.id}}
|
||||
assert ontologies_from_cache() == {rule2.id: "new ontology"}
|
||||
|
||||
# remove the last rule
|
||||
sheerka.remove_rule(context, rule2)
|
||||
assert rules_by_ontology_from_cache() == {}
|
||||
assert ontologies_from_cache() == {}
|
||||
|
||||
# commit and check the db
|
||||
sheerka.om.commit(context)
|
||||
assert rules_by_ontology_from_db() == {}
|
||||
assert ontologies_from_db() == {}
|
||||
|
||||
def test_i_can_keep_track_of_created_concept_on_ontology_pop(self):
|
||||
sheerka, context, foo = self.init_concepts("foo", create_new=True)
|
||||
|
||||
events_raised = set()
|
||||
sheerka.subscribe(EVENT_CONCEPT_ID_DELETED, lambda ctx, c: events_raised.add(c))
|
||||
|
||||
def from_cache(entry):
|
||||
return sheerka.om.self_cache_manager.copy(entry)
|
||||
|
||||
sheerka.push_ontology(context, "new ontology")
|
||||
sheerka.create_new_concept(context, Concept("bar"))
|
||||
sheerka.create_new_concept(context, Concept("baz"))
|
||||
|
||||
sheerka.pop_ontology(context)
|
||||
assert from_cache(SheerkaOntologyManager.CONCEPTS_BY_ONTOLOGY_ENTRY) == {'#unit_test#': {'1001'}}
|
||||
assert from_cache(SheerkaOntologyManager.ONTOLOGY_BY_CONCEPT_ENTRY) == {'1001': '#unit_test#'}
|
||||
|
||||
# check that the 'concept is deleted' events are raised
|
||||
assert events_raised == {'1002', '1003'}
|
||||
|
||||
def test_i_can_keep_track_of_created_rules_on_ontology_pop(self):
|
||||
sheerka, context, rule1 = self.init_format_rules(("rule1", "id.attr == 'value'", "True"))
|
||||
|
||||
events_raised = set()
|
||||
sheerka.subscribe(EVENT_RULE_ID_DELETED, lambda ctx, r: events_raised.add(r))
|
||||
|
||||
def rules_by_ontology_from_cache():
|
||||
res = sheerka.om.self_cache_manager.copy(SheerkaOntologyManager.RULES_BY_ONTOLOGY_ENTRY)
|
||||
del res[SheerkaOntologyManager.ROOT_ONTOLOGY_NAME] # discard builtin rules
|
||||
return res
|
||||
|
||||
def ontologies_from_cache():
|
||||
res = sheerka.om.self_cache_manager.copy(SheerkaOntologyManager.ONTOLOGY_BY_RULE_ENTRY)
|
||||
return {k: v for k, v in res.items() if v != SheerkaOntologyManager.ROOT_ONTOLOGY_NAME}
|
||||
|
||||
sheerka.push_ontology(context, "new ontology")
|
||||
sheerka.create_new_rule(context, Rule(ACTION_TYPE_EXEC, "rule2", "id2.attr2 == 'value'", "True"))
|
||||
sheerka.create_new_rule(context, Rule(ACTION_TYPE_EXEC, "rule3", "id3.attr3 == 'value'", "True"))
|
||||
|
||||
sheerka.pop_ontology(context)
|
||||
assert rules_by_ontology_from_cache() == {'#unit_test#': {'10'}}
|
||||
assert ontologies_from_cache() == {'10': '#unit_test#'}
|
||||
|
||||
# check that the 'rule is deleted' events are raised
|
||||
assert events_raised == {'11', '12'}
|
||||
|
||||
# def test_i_can_list_by_key_when_dictionaries(self):
|
||||
# sheerka = self.get_sheerka(cache_only=False)
|
||||
# context = self.get_context(sheerka)
|
||||
@@ -1268,7 +1411,6 @@ class TestSheerkaOntology(TestUsingMemoryBasedSheerka):
|
||||
# assert manager.list_by_key("cache_name", "key2") == ["e", "f", "g"]
|
||||
# assert manager.list_by_key("cache_name", "key3") == ["a", "b", "c", "e", "f", "g"]
|
||||
|
||||
|
||||
def test_i_can_get_call_when_a_cache_is_cleared(self):
|
||||
sheerka = self.get_sheerka(cache_only=False)
|
||||
context = self.get_context(sheerka)
|
||||
@@ -1401,11 +1543,11 @@ class TestSheerkaOntology(TestUsingMemoryBasedSheerka):
|
||||
assert manager.ontologies[2].cache_manager.get_cache("cache_name").copy() == {'key1': 'value1',
|
||||
'key2': 'value2'}
|
||||
|
||||
manager.pop_ontology()
|
||||
manager.pop_ontology(context)
|
||||
assert manager.get("cache_name", "key1") == "new value1"
|
||||
assert manager.get("cache_name", "key2") is NotFound
|
||||
|
||||
manager.pop_ontology()
|
||||
manager.pop_ontology(context)
|
||||
assert manager.get("cache_name", "key1") == "value1"
|
||||
assert manager.get("cache_name", "key2") == "value2"
|
||||
|
||||
@@ -1453,9 +1595,63 @@ class TestSheerkaOntologyWithFileBasedSheerka(TestUsingFileBasedSheerka):
|
||||
|
||||
assert manager.get("cache_name", "key") == "value2"
|
||||
|
||||
manager.pop_ontology()
|
||||
manager.pop_ontology(context)
|
||||
assert manager.get("cache_name", "key") == "value1"
|
||||
|
||||
# put back the previous ontology
|
||||
manager.push_ontology("new ontology")
|
||||
assert manager.get("cache_name", "key") == "value2"
|
||||
|
||||
def test_i_can_remember_concept_and_rules_by_ontology(self):
|
||||
sheerka, context, foo, r1 = self.init_test().with_concepts(
|
||||
"foo",
|
||||
create_new=True
|
||||
).with_format_rules(
|
||||
("rule1", "__ret", "True"),
|
||||
).unpack()
|
||||
sheerka.om.commit(context)
|
||||
|
||||
sheerka = self.new_sheerka_instance(False)
|
||||
context = self.get_context(sheerka)
|
||||
|
||||
sheerka.create_new_concept(context, Concept("bar"))
|
||||
r2 = sheerka.create_new_rule(context, Rule(ACTION_TYPE_EXEC, "rule2", "__ret.status", "True")).body.body
|
||||
sheerka.om.commit(context)
|
||||
|
||||
sheerka.push_ontology(context, "new ontology")
|
||||
sheerka.create_new_concept(context, Concept("baz"))
|
||||
sheerka.create_new_rule(context, Rule(ACTION_TYPE_EXEC, "rule3", "id3.attr3 == 'value'", "True"))
|
||||
sheerka.om.commit(context)
|
||||
|
||||
sheerka = self.new_sheerka_instance(False)
|
||||
context = self.get_context(sheerka)
|
||||
|
||||
sheerka.push_ontology(context, "another ontology")
|
||||
sheerka.create_new_concept(context, Concept("qux"))
|
||||
r4 = sheerka.create_new_rule(context, Rule(ACTION_TYPE_EXEC, "rule4", "id4.attr4", "True")).body.body
|
||||
sheerka.remove_concept(context, foo)
|
||||
sheerka.remove_rule(context, r2)
|
||||
sheerka.om.commit(context)
|
||||
|
||||
assert sheerka.om.self_cache_manager.copy(SheerkaOntologyManager.CONCEPTS_BY_ONTOLOGY_ENTRY) == {
|
||||
'#unit_test#': {'1002'},
|
||||
'another ontology': {'1004'},
|
||||
}
|
||||
|
||||
assert sheerka.om.self_cache_manager.copy(SheerkaOntologyManager.RULES_BY_ONTOLOGY_ENTRY) == {
|
||||
'#unit_test#': {r1.id},
|
||||
'another ontology': {r4.id},
|
||||
}
|
||||
|
||||
# in db
|
||||
assert sheerka.om.self_cache_manager.sdp.get(SheerkaOntologyManager.CONCEPTS_BY_ONTOLOGY_ENTRY) == {
|
||||
'#unit_test#': {'1002'},
|
||||
'another ontology': {'1004'},
|
||||
'new ontology': {'1003'}}
|
||||
|
||||
rules_from_db = sheerka.om.self_cache_manager.sdp.get(SheerkaOntologyManager.RULES_BY_ONTOLOGY_ENTRY)
|
||||
del rules_from_db["__default__"]
|
||||
assert rules_from_db == {
|
||||
'#unit_test#': {'10'},
|
||||
'another ontology': {'13'},
|
||||
'new ontology': {'12'}}
|
||||
|
||||
@@ -368,19 +368,19 @@ second : 'value d'
|
||||
sheerka.print(lst)
|
||||
captured = capsys.readouterr()
|
||||
assert captured.out == """(1001)foo a b
|
||||
a : 'value a'
|
||||
b : 'value b'
|
||||
id : '1001'
|
||||
name: 'foo a b'
|
||||
key : 'foo __var__0 __var__1'
|
||||
a : 'value a'
|
||||
b : 'value b'
|
||||
body: **NotInit**
|
||||
self: (1001)foo a b
|
||||
(1001)foo a b
|
||||
a : 'value c'
|
||||
b : 'value d'
|
||||
id : '1001'
|
||||
name: 'foo a b'
|
||||
key : 'foo __var__0 __var__1'
|
||||
a : 'value c'
|
||||
b : 'value d'
|
||||
body: **NotInit**
|
||||
self: (1001)foo a b
|
||||
"""
|
||||
@@ -404,6 +404,9 @@ self: (1001)foo a b
|
||||
sheerka.print(lst)
|
||||
captured = capsys.readouterr()
|
||||
assert captured.out == """(1001)foo a b
|
||||
id : '1001'
|
||||
name: 'foo a b'
|
||||
key : 'foo __var__0 __var__1'
|
||||
a : 'value a'
|
||||
b : {'a' : 'value a'
|
||||
'beta' : {'b1': 10
|
||||
@@ -425,9 +428,6 @@ b : {'a' : 'value a'
|
||||
'empty': ()}
|
||||
'h' : {'set' : {'set-a'}
|
||||
'empty': {}}}
|
||||
id : '1001'
|
||||
name: 'foo a b'
|
||||
key : 'foo __var__0 __var__1'
|
||||
body: **NotInit**
|
||||
self: (1001)foo a b
|
||||
"""
|
||||
|
||||
@@ -1,7 +1,8 @@
|
||||
from dataclasses import dataclass
|
||||
|
||||
import core.utils
|
||||
import pytest
|
||||
|
||||
import core.utils
|
||||
from core.builtin_concepts import BuiltinConcepts
|
||||
from core.builtin_helpers import evaluate_expression
|
||||
from core.concept import Concept
|
||||
@@ -111,7 +112,7 @@ def test_i_can_get_sub_classes():
|
||||
([['a'], ['b']], ['c', 'd', 'e'], [['a', 'c'], ['b', 'c'], ['a', 'd'], ['b', 'd'], ['a', 'e'], ['b', 'e']]),
|
||||
])
|
||||
def test_i_can_product(a, b, expected):
|
||||
res = core.utils.product(a, b)
|
||||
res = core.utils.sheerka_product(a, b)
|
||||
assert res == expected
|
||||
|
||||
|
||||
@@ -425,3 +426,31 @@ def test_i_can_deep_copy_a_custom_type():
|
||||
assert core.utils.sheerka_deepcopy(NotInit) is NotInit
|
||||
assert core.utils.sheerka_deepcopy(NotFound) is NotFound
|
||||
assert core.utils.sheerka_deepcopy(Removed) is Removed
|
||||
|
||||
|
||||
@pytest.mark.parametrize("expression1, expression2, expected", [
|
||||
("foo bar baz", "foo bar baz", True),
|
||||
("foo()", " foo ( ) ", True),
|
||||
("is_instance()", "is _ instance()", False),
|
||||
("foo bar baz", "foo bar", False)
|
||||
])
|
||||
def test_tokens_are_matching(expression1, expression2, expected):
|
||||
assert core.utils.tokens_are_matching(Tokenizer(expression1), Tokenizer(expression2)) == expected
|
||||
|
||||
|
||||
def test_tokens_are_matching_when_no_eof():
|
||||
expression1 = "foo bar baz"
|
||||
expression2 = "foo bar"
|
||||
tokens1 = Tokenizer(expression1, yield_eof=False)
|
||||
tokens2 = Tokenizer(expression2, yield_eof=False)
|
||||
|
||||
assert not core.utils.tokens_are_matching(tokens1, tokens2)
|
||||
|
||||
|
||||
def test_tokens_are_matching_when_eof_differs():
|
||||
expression1 = "foo bar baz"
|
||||
expression2 = "foo bar baz"
|
||||
tokens1 = Tokenizer(expression1, yield_eof=True)
|
||||
tokens2 = Tokenizer(expression2, yield_eof=False)
|
||||
|
||||
assert core.utils.tokens_are_matching(tokens1, tokens2)
|
||||
|
||||
Reference in New Issue
Block a user