Added first version of DebugManager. Implemented draft of the rule engine
This commit is contained in:
+162
-106
@@ -1,140 +1,196 @@
|
||||
import pytest
|
||||
|
||||
from core.builtin_concepts import BuiltinConcepts
|
||||
from core.concept import Concept
|
||||
from core.sheerka.ExecutionContext import ExecutionContext
|
||||
from core.sheerka.services.SheerkaMemory import SheerkaMemory
|
||||
from sdp.sheerkaDataProvider import Event
|
||||
|
||||
|
||||
def test_id_is_incremented_by_event_digest():
|
||||
a = ExecutionContext("foo", Event("event_1"), None, BuiltinConcepts.NOP, None)
|
||||
b = ExecutionContext("foo", Event("event_1"), None, BuiltinConcepts.NOP, None)
|
||||
c = ExecutionContext("foo", Event("event_2"), None, BuiltinConcepts.NOP, None)
|
||||
d = b.push(BuiltinConcepts.NOP, None)
|
||||
e = c.push(BuiltinConcepts.NOP, None)
|
||||
|
||||
assert a.id == 0
|
||||
assert b.id == 1
|
||||
assert c.id == 0
|
||||
assert d.id == 2
|
||||
assert e.id == 1
|
||||
from tests.TestUsingMemoryBasedSheerka import TestUsingMemoryBasedSheerka
|
||||
|
||||
|
||||
def test_i_can_use_with_statement():
|
||||
with ExecutionContext("who_", Event("event"), "fake_sheerka", BuiltinConcepts.NOP, None) as e:
|
||||
pass
|
||||
assert e.elapsed > 0
|
||||
class TestExecutionContext(TestUsingMemoryBasedSheerka):
|
||||
|
||||
def test_id_is_incremented_by_event_digest(self):
|
||||
sheerka = self.get_sheerka()
|
||||
|
||||
def test_i_can_push():
|
||||
a = ExecutionContext("foo", Event("event_1"), "fake_sheerka", BuiltinConcepts.NOP, None,
|
||||
desc="some description",
|
||||
obj=Concept("foo"),
|
||||
step=BuiltinConcepts.EVALUATION,
|
||||
iteration=15,
|
||||
concepts={"bar": Concept("bar")})
|
||||
a.preprocess = set()
|
||||
a.preprocess.add("preprocess")
|
||||
a.protected_hints.add(BuiltinConcepts.EVAL_BODY_REQUESTED)
|
||||
a.global_hints.add(BuiltinConcepts.EVAL_BODY_REQUESTED)
|
||||
a = ExecutionContext("foo", Event("event_1"), sheerka, BuiltinConcepts.NOP, None)
|
||||
b = ExecutionContext("foo", Event("event_1"), sheerka, BuiltinConcepts.NOP, None)
|
||||
c = ExecutionContext("foo", Event("event_2"), sheerka, BuiltinConcepts.NOP, None)
|
||||
d = b.push(BuiltinConcepts.NOP, None)
|
||||
e = c.push(BuiltinConcepts.NOP, None)
|
||||
|
||||
b = a.push(BuiltinConcepts.EVALUATION, "sub action context", desc="sub description")
|
||||
assert a.id == 0
|
||||
assert b.id == 1
|
||||
assert c.id == 0
|
||||
assert d.id == 2
|
||||
assert e.id == 1
|
||||
|
||||
assert b._parent == a
|
||||
assert b.who == a.who
|
||||
assert b.event == a.event
|
||||
assert b.sheerka == a.sheerka
|
||||
assert b.action == BuiltinConcepts.EVALUATION
|
||||
assert b.action_context == "sub action context"
|
||||
assert b.desc == "sub description"
|
||||
assert b.obj == a.obj
|
||||
assert b.step == a.step
|
||||
assert b.iteration == a.iteration
|
||||
assert b.concepts == a.concepts
|
||||
assert b.id == a.id + 1
|
||||
assert b._tab == a._tab + " "
|
||||
assert b.preprocess == a.preprocess
|
||||
assert b.protected_hints == {BuiltinConcepts.EVAL_BODY_REQUESTED}
|
||||
assert b.global_hints == a.global_hints
|
||||
def test_i_can_use_with_statement(self):
|
||||
sheerka = self.get_sheerka()
|
||||
|
||||
with ExecutionContext("who_", Event("event"), sheerka, BuiltinConcepts.NOP, None) as e:
|
||||
pass
|
||||
assert e.elapsed > 0
|
||||
|
||||
def test_children_i_created_when_i_push():
|
||||
e = ExecutionContext("who_", Event("event"), "fake_sheerka", BuiltinConcepts.NOP, None)
|
||||
e.push(BuiltinConcepts.NOP, None, who="a", desc="I do something")
|
||||
e.push(BuiltinConcepts.NOP, None, who="b", desc="oups! I did a again")
|
||||
e.push(BuiltinConcepts.NOP, None, who="c", desc="I do something else")
|
||||
def test_i_can_push(self):
|
||||
sheerka = self.get_sheerka()
|
||||
|
||||
assert len(e._children) == 3
|
||||
assert e._children[0].who, e._children[0].who == ("a", "I do something")
|
||||
assert e._children[1].who, e._children[1].who == ("b", "oups! I did a again")
|
||||
assert e._children[2].who, e._children[2].who == ("c", "I do something else")
|
||||
a = ExecutionContext("foo", Event("event_1"), sheerka, BuiltinConcepts.NOP, None,
|
||||
desc="some description",
|
||||
obj=Concept("foo"),
|
||||
concepts={"bar": Concept("bar")})
|
||||
a.preprocess = set()
|
||||
a.preprocess.add("preprocess")
|
||||
a.preprocess_parsers = ["list of parsers"]
|
||||
a.preprocess_evaluators = ["list of evaluators"]
|
||||
a.protected_hints.add(BuiltinConcepts.EVAL_BODY_REQUESTED)
|
||||
a.global_hints.add(BuiltinConcepts.EVAL_BODY_REQUESTED)
|
||||
|
||||
b = a.push(BuiltinConcepts.EVALUATION, "sub action context", desc="sub description")
|
||||
|
||||
def test_i_can_add_variable_when_i_push():
|
||||
e = ExecutionContext("who_", Event("event"), "fake_sheerka", BuiltinConcepts.NOP, None)
|
||||
sub_e = e.push(BuiltinConcepts.NOP, None, who="a", my_new_var="new var value")
|
||||
assert b._parent == a
|
||||
assert b.who == a.who
|
||||
assert b.event == a.event
|
||||
assert b.sheerka == a.sheerka
|
||||
assert b.action == BuiltinConcepts.EVALUATION
|
||||
assert b.action_context == "sub action context"
|
||||
assert b.desc == "sub description"
|
||||
assert b.obj == a.obj
|
||||
assert b.concepts == a.concepts
|
||||
assert b.id == a.id + 1
|
||||
assert b.preprocess == a.preprocess
|
||||
assert b.preprocess_parsers == a.preprocess_parsers
|
||||
assert b.preprocess_evaluators == a.preprocess_evaluators
|
||||
assert b.protected_hints == {BuiltinConcepts.EVAL_BODY_REQUESTED}
|
||||
assert b.global_hints == a.global_hints
|
||||
|
||||
assert sub_e.my_new_var == "new var value"
|
||||
with pytest.raises(AttributeError):
|
||||
assert e.my_new_var == "" # my_new_var does not exist in parent
|
||||
def test_children_i_created_when_i_push(self):
|
||||
sheerka = self.get_sheerka()
|
||||
|
||||
e = ExecutionContext("who_", Event("event"), sheerka, BuiltinConcepts.NOP, None)
|
||||
e.push(BuiltinConcepts.NOP, None, who="a", desc="I do something")
|
||||
e.push(BuiltinConcepts.NOP, None, who="b", desc="oups! I did a again")
|
||||
e.push(BuiltinConcepts.NOP, None, who="c", desc="I do something else")
|
||||
|
||||
def test_local_hints_are_local_and_global_hints_are_global():
|
||||
a = ExecutionContext("foo", Event("event_1"), "fake_sheerka", BuiltinConcepts.NOP, None)
|
||||
a.protected_hints.add("local hint 1")
|
||||
a.global_hints.add("global hint 1")
|
||||
assert len(e._children) == 3
|
||||
assert e._children[0].who, e._children[0].who == ("a", "I do something")
|
||||
assert e._children[1].who, e._children[1].who == ("b", "oups! I did a again")
|
||||
assert e._children[2].who, e._children[2].who == ("c", "I do something else")
|
||||
|
||||
b = a.push(BuiltinConcepts.NOP, None)
|
||||
b.protected_hints.add("local hint 2")
|
||||
b.global_hints.add("global hint 2")
|
||||
# def test_i_can_add_variable_when_i_push(self):
|
||||
# sheerka = self.get_sheerka()
|
||||
#
|
||||
# e = ExecutionContext("who_", Event("event"), sheerka, BuiltinConcepts.NOP, None)
|
||||
# sub_e = e.push(BuiltinConcepts.NOP, None, who="a", my_new_var="new var value")
|
||||
#
|
||||
# assert sub_e.my_new_var == "new var value"
|
||||
# with pytest.raises(AttributeError):
|
||||
# assert e.my_new_var == "" # my_new_var does not exist in parent
|
||||
|
||||
assert a.protected_hints == {"local hint 1"}
|
||||
assert a.global_hints == {"global hint 1", "global hint 2"}
|
||||
def test_local_hints_are_local_and_global_hints_are_global(self):
|
||||
sheerka = self.get_sheerka()
|
||||
|
||||
assert b.protected_hints == {"local hint 1", "local hint 2"}
|
||||
assert b.global_hints == {"global hint 1", "global hint 2"}
|
||||
a = ExecutionContext("foo", Event("event_1"), sheerka, BuiltinConcepts.NOP, None)
|
||||
a.protected_hints.add("local hint 1")
|
||||
a.global_hints.add("global hint 1")
|
||||
|
||||
b = a.push(BuiltinConcepts.NOP, None)
|
||||
b.protected_hints.add("local hint 2")
|
||||
b.global_hints.add("global hint 2")
|
||||
|
||||
def test_global_hits_are_global_even_when_empty():
|
||||
a = ExecutionContext("foo", Event("event_1"), "fake_sheerka", BuiltinConcepts.NOP, None)
|
||||
assert a.protected_hints == {"local hint 1"}
|
||||
assert a.global_hints == {"global hint 1", "global hint 2"}
|
||||
|
||||
b = a.push(BuiltinConcepts.NOP, None)
|
||||
b.global_hints.add("global hint 2")
|
||||
assert b.protected_hints == {"local hint 1", "local hint 2"}
|
||||
assert b.global_hints == {"global hint 1", "global hint 2"}
|
||||
|
||||
assert a.global_hints == {"global hint 2"}
|
||||
assert b.global_hints == {"global hint 2"}
|
||||
def test_global_hits_are_global_even_when_empty(self):
|
||||
sheerka = self.get_sheerka()
|
||||
|
||||
a = ExecutionContext("foo", Event("event_1"), sheerka, BuiltinConcepts.NOP, None)
|
||||
|
||||
def test_i_can_search():
|
||||
a = ExecutionContext("foo", Event("event_1"), "fake_sheerka", BuiltinConcepts.TESTING, "a")
|
||||
ab = a.push(BuiltinConcepts.TESTING, "ab", obj="obj_ab")
|
||||
ac = a.push(BuiltinConcepts.TESTING, "ac", obj="obj_ac")
|
||||
abb = ab.push(BuiltinConcepts.TESTING, "abb", obj="skip")
|
||||
abbb = abb.push(BuiltinConcepts.TESTING, "abbb", obj="obj_abbb")
|
||||
b = a.push(BuiltinConcepts.NOP, None)
|
||||
b.global_hints.add("global hint 2")
|
||||
|
||||
assert list(abbb.search()) == [abb, ab, a]
|
||||
assert list(abbb.search(start_with_self=True)) == [abbb, abb, ab, a]
|
||||
assert list(abbb.search(lambda ec: ec.obj != "skip")) == [ab, a]
|
||||
assert list(abbb.search(lambda ec: ec.obj != "skip", lambda ec: ec.action_context)) == ["ab", "a"]
|
||||
assert list(abbb.search(stop=lambda ec: ec.obj == "skip")) == [abb]
|
||||
assert list(abbb.search(
|
||||
stop=lambda ec: ec.obj == "skip",
|
||||
start_with_self=True,
|
||||
get_obj=lambda ec: ec.obj)) == ["obj_abbb", "skip"]
|
||||
assert a.global_hints == {"global hint 2"}
|
||||
assert b.global_hints == {"global hint 2"}
|
||||
|
||||
def test_i_can_search(self):
|
||||
sheerka = self.get_sheerka()
|
||||
|
||||
def test_variables_are_passed_to_children_but_not_to_parents():
|
||||
a = ExecutionContext("foo", Event("event_1"), "fake_sheerka", BuiltinConcepts.NOP, None)
|
||||
assert not hasattr(a, "var")
|
||||
a = ExecutionContext("foo", Event("event_1"), sheerka, BuiltinConcepts.TESTING, "a")
|
||||
ab = a.push(BuiltinConcepts.TESTING, "ab", obj="obj_ab")
|
||||
ac = a.push(BuiltinConcepts.TESTING, "ac", obj="obj_ac")
|
||||
abb = ab.push(BuiltinConcepts.TESTING, "abb", obj="skip")
|
||||
abbb = abb.push(BuiltinConcepts.TESTING, "abbb", obj="obj_abbb")
|
||||
|
||||
b = a.push(BuiltinConcepts.NOP, None, var="foo")
|
||||
assert b.var == "foo"
|
||||
assert not hasattr(a, "var")
|
||||
assert list(abbb.search()) == [abb, ab, a]
|
||||
assert list(abbb.search(start_with_self=True)) == [abbb, abb, ab, a]
|
||||
assert list(abbb.search(lambda ec: ec.obj != "skip")) == [ab, a]
|
||||
assert list(abbb.search(lambda ec: ec.obj != "skip", lambda ec: ec.action_context)) == ["ab", "a"]
|
||||
assert list(abbb.search(stop=lambda ec: ec.obj == "skip")) == [abb]
|
||||
assert list(abbb.search(
|
||||
stop=lambda ec: ec.obj == "skip",
|
||||
start_with_self=True,
|
||||
get_obj=lambda ec: ec.obj)) == ["obj_abbb", "skip"]
|
||||
|
||||
c = b.push(BuiltinConcepts.NOP, None)
|
||||
assert c.var == "foo"
|
||||
def test_i_can_deactivate_push(self):
|
||||
sheerka = self.get_sheerka()
|
||||
|
||||
c.var = "bar"
|
||||
assert c.var == "bar"
|
||||
assert b.var != "bar"
|
||||
assert not hasattr(a, "var")
|
||||
context = ExecutionContext("foo", Event("event_1"), sheerka, BuiltinConcepts.NOP, None)
|
||||
context.deactivate_push()
|
||||
sub_context1 = context.push(BuiltinConcepts.NOP, None)
|
||||
sub_context2 = context.push(BuiltinConcepts.NOP, None)
|
||||
sub_context3 = sub_context1.push(BuiltinConcepts.NOP, None)
|
||||
|
||||
assert id(sub_context1) == id(sub_context2)
|
||||
assert id(sub_context1) == id(sub_context3)
|
||||
|
||||
def test_stm_are_copied_when_deactivate_push(self):
|
||||
sheerka = self.get_sheerka()
|
||||
|
||||
context = ExecutionContext("foo", Event("event_1"), sheerka, BuiltinConcepts.NOP, None)
|
||||
context.add_to_short_term_memory("key1", "value1")
|
||||
context.add_to_short_term_memory("key2", "value2")
|
||||
|
||||
context.deactivate_push()
|
||||
|
||||
stm_cache = sheerka.services[SheerkaMemory.NAME].short_term_objects.cache
|
||||
assert stm_cache == {
|
||||
context.id: {'key1': 'value1', 'key2': 'value2'},
|
||||
context.id + 1: {'key1': 'value1', 'key2': 'value2'}
|
||||
}
|
||||
|
||||
def test_has_parent(self):
|
||||
sheerka = self.get_sheerka()
|
||||
root = ExecutionContext("foo", Event("event_1"), sheerka, BuiltinConcepts.NOP, None)
|
||||
|
||||
sub1 = root.push(BuiltinConcepts.TESTING, None)
|
||||
sub2 = root.push(BuiltinConcepts.TESTING, None)
|
||||
|
||||
sub11 = sub1.push(BuiltinConcepts.TESTING, None)
|
||||
sub111 = sub11.push(BuiltinConcepts.TESTING, None)
|
||||
|
||||
assert not root.has_parent(sub1.id)
|
||||
assert sub1.has_parent(root.id)
|
||||
assert sub11.has_parent(root.id)
|
||||
assert sub111.has_parent(root.id)
|
||||
assert sub2.has_parent(root.id)
|
||||
assert not sub1.has_parent(sub2.id)
|
||||
assert not sub2.has_parent(sub1.id)
|
||||
# def test_variables_are_passed_to_children_but_not_to_parents(self):
|
||||
# sheerka = self.get_sheerka()
|
||||
#
|
||||
# a = ExecutionContext("foo", Event("event_1"), sheerka, BuiltinConcepts.NOP, None)
|
||||
# assert not hasattr(a, "var")
|
||||
#
|
||||
# b = a.push(BuiltinConcepts.NOP, None, var="foo")
|
||||
# assert b.var == "foo"
|
||||
# assert not hasattr(a, "var")
|
||||
#
|
||||
# c = b.push(BuiltinConcepts.NOP, None)
|
||||
# assert c.var == "foo"
|
||||
#
|
||||
# c.var = "bar"
|
||||
# assert c.var == "bar"
|
||||
# assert b.var != "bar"
|
||||
# assert not hasattr(a, "var")
|
||||
|
||||
@@ -0,0 +1,65 @@
|
||||
from core.builtin_concepts import BuiltinConcepts
|
||||
|
||||
from tests.TestUsingMemoryBasedSheerka import TestUsingMemoryBasedSheerka
|
||||
|
||||
|
||||
class TestSheerkaAdmin(TestUsingMemoryBasedSheerka):
|
||||
def test_i_can_get_last_ret(self):
|
||||
pass
|
||||
|
||||
def test_i_can_get_last_error_ret(self):
|
||||
sheerka, context = self.init_concepts()
|
||||
|
||||
# nothing in history
|
||||
last_error_ret = sheerka.last_error_ret(context)
|
||||
assert sheerka.isinstance(last_error_ret, BuiltinConcepts.RETURN_VALUE)
|
||||
assert not last_error_ret.status
|
||||
assert sheerka.isinstance(last_error_ret.body, BuiltinConcepts.NOT_FOUND)
|
||||
|
||||
# only success in history
|
||||
r_success = sheerka.ret("Test", True, "success")
|
||||
sheerka.last_return_values.append([r_success])
|
||||
last_error_ret = sheerka.last_error_ret(context)
|
||||
assert sheerka.isinstance(last_error_ret, BuiltinConcepts.RETURN_VALUE)
|
||||
assert not last_error_ret.status
|
||||
assert sheerka.isinstance(last_error_ret.body, BuiltinConcepts.NOT_FOUND)
|
||||
|
||||
# at least on error
|
||||
r_failure = sheerka.ret("Test", False, "failure")
|
||||
sheerka.last_return_values.append([r_failure])
|
||||
assert sheerka.last_error_ret(context) == r_failure
|
||||
|
||||
# add another success and make sure we get the same error
|
||||
sheerka.last_return_values.append([r_success])
|
||||
assert sheerka.last_error_ret(context) == r_failure
|
||||
|
||||
# and I only get the last failure
|
||||
r_failure2 = sheerka.ret("Test", False, "another failure")
|
||||
sheerka.last_return_values.append([r_failure2])
|
||||
assert sheerka.last_error_ret(context) == r_failure2
|
||||
|
||||
# but I still can get the previous error
|
||||
assert sheerka.last_error_ret(context, -2) == r_failure
|
||||
|
||||
def test_i_can_get_last_error_ret_when_only_one_ret_has_failed(self):
|
||||
sheerka, context = self.init_concepts()
|
||||
|
||||
r_success = sheerka.ret("Test", True, "success")
|
||||
r_failure = sheerka.ret("Test", False, "False1")
|
||||
|
||||
sheerka.last_return_values.append([r_success, r_failure])
|
||||
assert sheerka.last_error_ret(context) == r_failure
|
||||
|
||||
def test_i_cannot_get_last_error_ret_when_too_many_errors(self):
|
||||
sheerka, context = self.init_concepts()
|
||||
|
||||
r1 = sheerka.ret("Test", True, "success")
|
||||
r2 = sheerka.ret("Test", False, "False1")
|
||||
r3 = sheerka.ret("Test", False, "False2")
|
||||
|
||||
sheerka.last_return_values.append([r1, r2, r3])
|
||||
last_error_ret = sheerka.last_error_ret(context)
|
||||
assert sheerka.isinstance(last_error_ret, BuiltinConcepts.RETURN_VALUE)
|
||||
assert not last_error_ret.status
|
||||
assert sheerka.isinstance(last_error_ret.body, BuiltinConcepts.TOO_MANY_ERRORS)
|
||||
assert last_error_ret.body.body == [r2, r3]
|
||||
@@ -1,5 +1,8 @@
|
||||
import pytest
|
||||
from core.builtin_concepts import BuiltinConcepts
|
||||
from core.concept import Concept
|
||||
from core.global_symbols import CONCEPT_PRECEDENCE_MODIFIED, CONCEPT_COMPARISON_CONTEXT, RULE_PRECEDENCE_MODIFIED, \
|
||||
RULE_COMPARISON_CONTEXT
|
||||
from core.sheerka.services.SheerkaComparisonManager import SheerkaComparisonManager, ComparisonObj
|
||||
|
||||
from tests.TestUsingMemoryBasedSheerka import TestUsingMemoryBasedSheerka
|
||||
@@ -31,15 +34,36 @@ class TestSheerkaGreaterThanManager(TestUsingMemoryBasedSheerka):
|
||||
assert sheerka.isinstance(res.body, BuiltinConcepts.SUCCESS)
|
||||
|
||||
in_cache = sheerka.cache_manager.get(SheerkaComparisonManager.COMPARISON_ENTRY, "prop_name|#")
|
||||
assert in_cache == [ComparisonObj(context.event.get_digest(), "prop_name", two.id, one.id, ">", "#")]
|
||||
assert in_cache == [ComparisonObj(context.event.get_digest(), "prop_name", two.str_id, one.str_id, ">", "#")]
|
||||
|
||||
weighted = sheerka.cache_manager.get(SheerkaComparisonManager.RESOLVED_COMPARISON_ENTRY, "prop_name|#")
|
||||
assert weighted == {"1001": 1, "1002": 2}
|
||||
assert weighted == {"c:one|1001:": 1, "c:two|1002:": 2}
|
||||
|
||||
# I can commit
|
||||
sheerka.cache_manager.commit(context)
|
||||
in_db = sheerka.sdp.get(SheerkaComparisonManager.COMPARISON_ENTRY, "prop_name|#")
|
||||
assert in_db == [ComparisonObj(context.event.get_digest(), "prop_name", two.id, one.id, ">", "#")]
|
||||
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_format_rules(("True", "true"), ("False", "false"),
|
||||
cache_only=False,
|
||||
compile_rule=False)
|
||||
service = sheerka.services[SheerkaComparisonManager.NAME]
|
||||
|
||||
res = service.set_is_greater_than(context, "prop_name", r2, r1)
|
||||
assert res.status
|
||||
assert sheerka.isinstance(res.body, BuiltinConcepts.SUCCESS)
|
||||
|
||||
in_cache = sheerka.cache_manager.get(SheerkaComparisonManager.COMPARISON_ENTRY, "prop_name|#")
|
||||
assert in_cache == [ComparisonObj(context.event.get_digest(), "prop_name", r2.str_id, r1.str_id, ">", "#")]
|
||||
|
||||
weighted = sheerka.cache_manager.get(SheerkaComparisonManager.RESOLVED_COMPARISON_ENTRY, "prop_name|#")
|
||||
assert weighted == {"r:|1:": 1, "r:|2:": 2}
|
||||
|
||||
# I can commit
|
||||
sheerka.cache_manager.commit(context)
|
||||
in_db = sheerka.sdp.get(SheerkaComparisonManager.COMPARISON_ENTRY, "prop_name|#")
|
||||
assert in_db == [ComparisonObj(context.event.get_digest(), "prop_name", r2.str_id, r1.str_id, ">", "#")]
|
||||
|
||||
def test_i_can_add_a_is_less_than(self):
|
||||
sheerka, context, one, two = self.init_concepts("one", "two", cache_only=False)
|
||||
@@ -50,15 +74,36 @@ class TestSheerkaGreaterThanManager(TestUsingMemoryBasedSheerka):
|
||||
assert sheerka.isinstance(res.body, BuiltinConcepts.SUCCESS)
|
||||
|
||||
in_cache = sheerka.cache_manager.get(SheerkaComparisonManager.COMPARISON_ENTRY, "prop_name|#")
|
||||
assert in_cache == [ComparisonObj(context.event.get_digest(), "prop_name", one.id, two.id, "<", "#")]
|
||||
assert in_cache == [ComparisonObj(context.event.get_digest(), "prop_name", one.str_id, two.str_id, "<", "#")]
|
||||
|
||||
weighted = sheerka.cache_manager.get(SheerkaComparisonManager.RESOLVED_COMPARISON_ENTRY, "prop_name|#")
|
||||
assert weighted == {"1001": 1, "1002": 2}
|
||||
assert weighted == {"c:one|1001:": 1, "c:two|1002:": 2}
|
||||
|
||||
# I can commit
|
||||
sheerka.cache_manager.commit(context)
|
||||
in_db = sheerka.sdp.get(SheerkaComparisonManager.COMPARISON_ENTRY, "prop_name|#")
|
||||
assert in_db == [ComparisonObj(context.event.get_digest(), "prop_name", one.id, two.id, "<", "#")]
|
||||
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_format_rules(("True", "true"), ("False", "false"),
|
||||
cache_only=False,
|
||||
compile_rule=False)
|
||||
service = sheerka.services[SheerkaComparisonManager.NAME]
|
||||
|
||||
res = service.set_is_less_than(context, "prop_name", r1, r2)
|
||||
assert res.status
|
||||
assert sheerka.isinstance(res.body, BuiltinConcepts.SUCCESS)
|
||||
|
||||
in_cache = sheerka.cache_manager.get(SheerkaComparisonManager.COMPARISON_ENTRY, "prop_name|#")
|
||||
assert in_cache == [ComparisonObj(context.event.get_digest(), "prop_name", r1.str_id, r2.str_id, "<", "#")]
|
||||
|
||||
weighted = sheerka.cache_manager.get(SheerkaComparisonManager.RESOLVED_COMPARISON_ENTRY, "prop_name|#")
|
||||
assert weighted == {"r:|1:": 1, "r:|2:": 2}
|
||||
|
||||
# I can commit
|
||||
sheerka.cache_manager.commit(context)
|
||||
in_db = sheerka.sdp.get(SheerkaComparisonManager.COMPARISON_ENTRY, "prop_name|#")
|
||||
assert in_db == [ComparisonObj(context.event.get_digest(), "prop_name", r1.str_id, r2.str_id, "<", "#")]
|
||||
|
||||
def test_i_can_add_multiples_constraints(self):
|
||||
sheerka, context, one, two, three, four = self.init_concepts("one", "two", "three", "four", cache_only=False)
|
||||
@@ -69,16 +114,16 @@ class TestSheerkaGreaterThanManager(TestUsingMemoryBasedSheerka):
|
||||
|
||||
in_cache = sheerka.cache_manager.get(SheerkaComparisonManager.COMPARISON_ENTRY, "prop_name|#")
|
||||
assert in_cache == [
|
||||
ComparisonObj(context.event.get_digest(), "prop_name", two.id, one.id, ">", "#"),
|
||||
ComparisonObj(context.event.get_digest(), "prop_name", three.id, two.id, ">", "#")
|
||||
ComparisonObj(context.event.get_digest(), "prop_name", two.str_id, one.str_id, ">", "#"),
|
||||
ComparisonObj(context.event.get_digest(), "prop_name", three.str_id, two.str_id, ">", "#")
|
||||
]
|
||||
|
||||
# I can commit
|
||||
sheerka.cache_manager.commit(context)
|
||||
in_db = sheerka.sdp.get(SheerkaComparisonManager.COMPARISON_ENTRY, "prop_name|#")
|
||||
assert in_db == [
|
||||
ComparisonObj(context.event.get_digest(), "prop_name", two.id, one.id, ">", "#"),
|
||||
ComparisonObj(context.event.get_digest(), "prop_name", three.id, two.id, ">", "#")
|
||||
ComparisonObj(context.event.get_digest(), "prop_name", two.str_id, one.str_id, ">", "#"),
|
||||
ComparisonObj(context.event.get_digest(), "prop_name", three.str_id, two.str_id, ">", "#")
|
||||
]
|
||||
|
||||
sheerka.cache_manager.clear(SheerkaComparisonManager.COMPARISON_ENTRY) # reset the cache
|
||||
@@ -86,21 +131,45 @@ class TestSheerkaGreaterThanManager(TestUsingMemoryBasedSheerka):
|
||||
service.set_is_greater_than(context, "prop_name", four, three)
|
||||
in_cache = sheerka.cache_manager.get(SheerkaComparisonManager.COMPARISON_ENTRY, "prop_name|#")
|
||||
assert in_cache == [
|
||||
ComparisonObj(context.event.get_digest(), "prop_name", two.id, one.id, ">", "#"),
|
||||
ComparisonObj(context.event.get_digest(), "prop_name", three.id, two.id, ">", "#"),
|
||||
ComparisonObj(context.event.get_digest(), "prop_name", four.id, three.id, ">", "#"),
|
||||
ComparisonObj(context.event.get_digest(), "prop_name", two.str_id, one.str_id, ">", "#"),
|
||||
ComparisonObj(context.event.get_digest(), "prop_name", three.str_id, two.str_id, ">", "#"),
|
||||
ComparisonObj(context.event.get_digest(), "prop_name", four.str_id, three.str_id, ">", "#"),
|
||||
]
|
||||
|
||||
weighted = sheerka.cache_manager.get(SheerkaComparisonManager.RESOLVED_COMPARISON_ENTRY, "prop_name|#")
|
||||
assert weighted == {"1001": 1, "1002": 2, "1003": 3, "1004": 4}
|
||||
assert weighted == {"c:one|1001:": 1, "c:two|1002:": 2, "c:three|1003:": 3, "c:four|1004:": 4}
|
||||
|
||||
def test_i_can_add_multiple_constraints_2(self):
|
||||
sheerka, context, one, two, three = self.init_concepts("one", "two", "three")
|
||||
service = sheerka.services[SheerkaComparisonManager.NAME]
|
||||
|
||||
service.set_is_greater_than(context, "prop_name", two, one)
|
||||
service.set_is_greater_than(context, "prop_name", three, two)
|
||||
|
||||
weighted = sheerka.cache_manager.get(SheerkaComparisonManager.RESOLVED_COMPARISON_ENTRY, "prop_name|#")
|
||||
assert weighted == {"c:one|1001:": 1, "c:two|1002:": 2, "c:three|1003:": 3}
|
||||
|
||||
service.set_is_greater_than(context, "prop_name", three, one) # should not change order
|
||||
weighted = sheerka.cache_manager.get(SheerkaComparisonManager.RESOLVED_COMPARISON_ENTRY, "prop_name|#")
|
||||
assert weighted == {"c:one|1001:": 1, "c:two|1002:": 2, "c:three|1003:": 3}
|
||||
|
||||
def test_i_lesser_than_and_opposite_greater_than(self):
|
||||
sheerka, context, one, two = self.init_concepts("one", "two")
|
||||
service = sheerka.services[SheerkaComparisonManager.NAME]
|
||||
|
||||
service.set_is_greater_than(context, "prop_name", two, one)
|
||||
service.set_is_less_than(context, "prop_name", one, two)
|
||||
|
||||
weighted = sheerka.cache_manager.get(SheerkaComparisonManager.RESOLVED_COMPARISON_ENTRY, "prop_name|#")
|
||||
assert weighted == {"c:one|1001:": 1, "c:two|1002:": 2}
|
||||
|
||||
@pytest.mark.parametrize("entries, expected", [
|
||||
(["two > one"], {'1001': 1, '1002': 2}),
|
||||
(["one < two"], {'1001': 1, '1002': 2}),
|
||||
(["three > two", "one < two"], {'1001': 1, '1002': 2, '1003': 3}),
|
||||
(["three > one", "one < two"], {'1001': 1, '1002': 2, '1003': 2}),
|
||||
(["three >>"], {'1003': 2}),
|
||||
(["one <<"], {'1001': 0}),
|
||||
(["two > one"], {'c:one|1001:': 1, 'c:two|1002:': 2}),
|
||||
(["one < two"], {'c:one|1001:': 1, 'c:two|1002:': 2}),
|
||||
(["three > two", "one < two"], {'c:one|1001:': 1, 'c:two|1002:': 2, 'c:three|1003:': 3}),
|
||||
(["three > one", "one < two"], {'c:one|1001:': 1, 'c:two|1002:': 2, 'c:three|1003:': 2}),
|
||||
(["three >>"], {'c:three|1003:': 2}),
|
||||
(["one <<"], {'c:one|1001:': 0}),
|
||||
])
|
||||
def test_i_can_get_concept_weight(self, entries, expected):
|
||||
sheerka, context, *concepts = self.init_concepts("one", "two", "three")
|
||||
@@ -125,7 +194,7 @@ class TestSheerkaGreaterThanManager(TestUsingMemoryBasedSheerka):
|
||||
service.set_is_lesser(context, "prop_name", one)
|
||||
sheerka.cache_manager.clear(service.RESOLVED_COMPARISON_ENTRY)
|
||||
|
||||
assert service.get_concepts_weights("prop_name") == {"1001": 0}
|
||||
assert service.get_concepts_weights("prop_name") == {"c:one|1001:": 0}
|
||||
|
||||
def test_i_can_get_partition(self):
|
||||
sheerka, context, one, two, three = self.init_concepts("one", "two", "three")
|
||||
@@ -137,9 +206,9 @@ class TestSheerkaGreaterThanManager(TestUsingMemoryBasedSheerka):
|
||||
res = service.get_partition("prop_name")
|
||||
|
||||
assert res == {
|
||||
1: ["1001"],
|
||||
2: ["1002"],
|
||||
3: ["1003"],
|
||||
1: ["c:one|1001:"],
|
||||
2: ["c:two|1002:"],
|
||||
3: ["c:three|1003:"],
|
||||
}
|
||||
|
||||
def test_i_can_detect_chicken_and_egg(self):
|
||||
@@ -176,7 +245,7 @@ class TestSheerkaGreaterThanManager(TestUsingMemoryBasedSheerka):
|
||||
service.set_is_less_than(context, "prop_name", one, two)
|
||||
|
||||
weighted = sheerka.cache_manager.get(SheerkaComparisonManager.RESOLVED_COMPARISON_ENTRY, "prop_name|#")
|
||||
assert weighted == {"1001": 1, "1002": 2}
|
||||
assert weighted == {"c:one|1001:": 1, "c:two|1002:": 2}
|
||||
|
||||
def test_methods_are_correctly_bound(self):
|
||||
sheerka, context, one, two = self.init_concepts("one", "two")
|
||||
@@ -188,17 +257,17 @@ class TestSheerkaGreaterThanManager(TestUsingMemoryBasedSheerka):
|
||||
service = sheerka.services[SheerkaComparisonManager.NAME]
|
||||
|
||||
service.set_is_lesser(context, "prop_name", one)
|
||||
assert service.get_concepts_weights("prop_name") == {"1001": 0} # DEFAULT_COMPARISON_VALUE - 1
|
||||
assert service.get_concepts_weights("prop_name") == {"c:one|1001:": 0} # DEFAULT_COMPARISON_VALUE - 1
|
||||
|
||||
sheerka.set_is_greater_than(context, "prop_name", three, two)
|
||||
assert service.get_concepts_weights("prop_name") == {"1001": 0, "1002": 1, "1003": 2}
|
||||
assert service.get_concepts_weights("prop_name") == {"c:one|1001:": 0, "c:two|1002:": 1, "c:three|1003:": 2}
|
||||
|
||||
# I can commit
|
||||
sheerka.cache_manager.commit(context)
|
||||
in_db = sheerka.sdp.get(SheerkaComparisonManager.COMPARISON_ENTRY, "prop_name|#")
|
||||
assert in_db == [
|
||||
ComparisonObj(context.event.get_digest(), "prop_name", one.id, None, "<<", "#"),
|
||||
ComparisonObj(context.event.get_digest(), "prop_name", three.id, two.id, ">", "#")
|
||||
ComparisonObj(context.event.get_digest(), "prop_name", one.str_id, None, "<<", "#"),
|
||||
ComparisonObj(context.event.get_digest(), "prop_name", three.str_id, two.str_id, ">", "#")
|
||||
]
|
||||
|
||||
def test_i_can_define_an_order_for_lesser_concepts(self):
|
||||
@@ -211,7 +280,9 @@ class TestSheerkaGreaterThanManager(TestUsingMemoryBasedSheerka):
|
||||
|
||||
sheerka.set_is_less_than(context, "prop_name", less_l, lesser)
|
||||
sheerka.set_is_greater_than(context, "prop_name", less_l, even_more_l)
|
||||
assert service.get_concepts_weights("prop_name") == {"1001": 0, "1002": -1, "1003": -2}
|
||||
assert service.get_concepts_weights("prop_name") == {"c:lesser|1001:": 0,
|
||||
"c:less_l|1002:": -1,
|
||||
"c:even_less_l|1003:": -2}
|
||||
|
||||
def test_i_cannot_define_less_than_a_lesser_if_not_a_lesser_itself(self):
|
||||
"""
|
||||
@@ -237,10 +308,10 @@ class TestSheerkaGreaterThanManager(TestUsingMemoryBasedSheerka):
|
||||
service = sheerka.services[SheerkaComparisonManager.NAME]
|
||||
|
||||
service.set_is_greatest(context, "prop_name", three)
|
||||
assert service.get_concepts_weights("prop_name") == {"1003": 2} # DEFAULT_COMPARISON_VALUE + 1
|
||||
assert service.get_concepts_weights("prop_name") == {"c:three|1003:": 2} # DEFAULT_COMPARISON_VALUE + 1
|
||||
|
||||
sheerka.set_is_greater_than(context, "prop_name", two, one)
|
||||
assert service.get_concepts_weights("prop_name") == {"1001": 1, "1002": 2, "1003": 3}
|
||||
assert service.get_concepts_weights("prop_name") == {"c:one|1001:": 1, "c:two|1002:": 2, "c:three|1003:": 3}
|
||||
|
||||
def test_i_cannot_define_greater_than_a_greatest_if_not_a_greater_itself(self):
|
||||
sheerka, context, greatest, foo = self.init_concepts("greatest", "foo")
|
||||
@@ -280,7 +351,9 @@ class TestSheerkaGreaterThanManager(TestUsingMemoryBasedSheerka):
|
||||
|
||||
sheerka.set_is_less_than(context, "prop_name", greatest, more_g)
|
||||
sheerka.set_is_greater_than(context, "prop_name", even_more_g, more_g)
|
||||
assert service.get_concepts_weights("prop_name") == {"1001": 2, "1002": 3, "1003": 4}
|
||||
assert service.get_concepts_weights("prop_name") == {"c:greatest|1001:": 2,
|
||||
"c:more_g|1002:": 3,
|
||||
"c:even_more_g|1003:": 4}
|
||||
|
||||
def test_i_can_mix_all_comparisons(self):
|
||||
sheerka, context, one, two, three, four, five, six, three_and_half = self.init_concepts(
|
||||
@@ -298,25 +371,54 @@ class TestSheerkaGreaterThanManager(TestUsingMemoryBasedSheerka):
|
||||
sheerka.set_is_less_than(context, "prop_name", three, four)
|
||||
|
||||
assert service.get_concepts_weights("prop_name") == {
|
||||
"1001": -1,
|
||||
"1002": 0,
|
||||
"1003": 1,
|
||||
"1004": 2,
|
||||
"1005": 3,
|
||||
"1006": 4
|
||||
"c:one|1001:": -1,
|
||||
"c:two|1002:": 0,
|
||||
"c:three|1003:": 1,
|
||||
"c:four|1004:": 2,
|
||||
"c:five|1005:": 3,
|
||||
"c:six|1006:": 4
|
||||
}
|
||||
|
||||
sheerka.set_is_less_than(context, "prop_name", three_and_half, four)
|
||||
sheerka.set_is_greater_than(context, "prop_name", three_and_half, three)
|
||||
|
||||
assert service.get_concepts_weights("prop_name") == {
|
||||
"1001": -1,
|
||||
"1002": 0,
|
||||
"1003": 1,
|
||||
"1007": 2,
|
||||
"1004": 3,
|
||||
"1005": 4,
|
||||
"1006": 5
|
||||
"c:one|1001:": -1,
|
||||
"c:two|1002:": 0,
|
||||
"c:three|1003:": 1,
|
||||
"c:two_and_half|1007:": 2,
|
||||
"c:four|1004:": 3,
|
||||
"c:five|1005:": 4,
|
||||
"c:six|1006:": 5
|
||||
}
|
||||
|
||||
def test_i_can_mix_all_comparisons_2(self):
|
||||
sheerka, context, zero, one, two, three, four, five, thousand = self.init_concepts(
|
||||
"zero", "one", "two", "three", "four", "five", "thousand")
|
||||
service = sheerka.services[SheerkaComparisonManager.NAME]
|
||||
|
||||
service.set_is_greater_than(context, "prop_name", four, one)
|
||||
service.set_is_less_than(context, "prop_name", one, five)
|
||||
service.set_is_less_than(context, "prop_name", one, three)
|
||||
service.set_is_less_than(context, "prop_name", two, three)
|
||||
service.set_is_greater_than(context, "prop_name", two, one)
|
||||
service.set_is_greater_than(context, "prop_name", five, four)
|
||||
service.set_is_less_than(context, "prop_name", three, four)
|
||||
service.set_is_greatest(context, "prop_name", thousand)
|
||||
service.set_is_lesser(context, "prop_name", zero)
|
||||
service.set_is_less_than(context, "prop_name", two, five)
|
||||
service.set_is_less_than(context, "prop_name", two, four)
|
||||
service.set_is_greater_than(context, "prop_name", five, one)
|
||||
service.set_is_greater_than(context, "prop_name", five, three)
|
||||
|
||||
assert service.get_concepts_weights("prop_name") == {
|
||||
"c:zero|1001:": 0,
|
||||
"c:one|1002:": 1,
|
||||
"c:two|1003:": 2,
|
||||
"c:three|1004:": 3,
|
||||
"c:four|1005:": 4,
|
||||
"c:five|1006:": 5,
|
||||
"c:thousand|1007:": 6
|
||||
}
|
||||
|
||||
@pytest.mark.parametrize("definition", [
|
||||
@@ -335,3 +437,47 @@ class TestSheerkaGreaterThanManager(TestUsingMemoryBasedSheerka):
|
||||
|
||||
assert not res.status
|
||||
assert sheerka.isinstance(res.body, BuiltinConcepts.CONCEPT_ALREADY_DEFINED)
|
||||
|
||||
def test_an_event_is_fired_when_modifying_concepts_precedence(self):
|
||||
sheerka, context, one, two, foo = self.init_concepts("one", "two", "foo")
|
||||
event_received = False
|
||||
|
||||
def receive_event(c):
|
||||
nonlocal event_received
|
||||
event_received = True
|
||||
|
||||
sheerka.subscribe(CONCEPT_PRECEDENCE_MODIFIED, receive_event)
|
||||
|
||||
sheerka.set_is_greater_than(context, foo, one, two)
|
||||
assert not event_received
|
||||
|
||||
sheerka.set_is_greater_than(context, BuiltinConcepts.PRECEDENCE, foo, one, two)
|
||||
assert not event_received
|
||||
|
||||
sheerka.set_is_greater_than(context, BuiltinConcepts.PRECEDENCE, one, two, CONCEPT_COMPARISON_CONTEXT)
|
||||
assert event_received
|
||||
|
||||
def test_an_event_is_fired_when_modifying_rule_precedence(self):
|
||||
sheerka, context, r1, r2 = self.init_format_rules(
|
||||
("True", "True"),
|
||||
("False", "False"),
|
||||
compile_rule=False,
|
||||
)
|
||||
foo = Concept("foo")
|
||||
event_received = False
|
||||
sheerka.cache_manager.clear(SheerkaComparisonManager.COMPARISON_ENTRY)
|
||||
|
||||
def receive_event(c):
|
||||
nonlocal event_received
|
||||
event_received = True
|
||||
|
||||
sheerka.subscribe(RULE_PRECEDENCE_MODIFIED, receive_event)
|
||||
|
||||
sheerka.set_is_greater_than(context, foo, r1, r2)
|
||||
assert not event_received
|
||||
|
||||
sheerka.set_is_greater_than(context, BuiltinConcepts.PRECEDENCE, foo, r1, r2)
|
||||
assert not event_received
|
||||
|
||||
sheerka.set_is_greater_than(context, BuiltinConcepts.PRECEDENCE, r1, r2, RULE_COMPARISON_CONTEXT)
|
||||
assert event_received
|
||||
|
||||
@@ -19,7 +19,7 @@ class TestSheerkaConceptsAlgebra(TestUsingMemoryBasedSheerka):
|
||||
res = sheerka.cadd(context, sheerka.new("man"), sheerka.new("driver"))
|
||||
|
||||
assert isinstance(res, Concept)
|
||||
assert res.metadata.props == {BuiltinConcepts.ISA: {male, human},
|
||||
assert res.get_metadata().props == {BuiltinConcepts.ISA: {male, human},
|
||||
BuiltinConcepts.HASA: {car, licence}, }
|
||||
|
||||
def test_can_add_concepts_when_property_already_exist(self):
|
||||
@@ -32,7 +32,7 @@ class TestSheerkaConceptsAlgebra(TestUsingMemoryBasedSheerka):
|
||||
res = sheerka.cadd(context, sheerka.new("man"), sheerka.new("king"))
|
||||
|
||||
assert isinstance(res, Concept)
|
||||
assert res.metadata.props == {BuiltinConcepts.ISA: {male, human}}
|
||||
assert res.get_metadata().props == {BuiltinConcepts.ISA: {male, human}}
|
||||
|
||||
def test_i_can_subtract_concepts(self):
|
||||
sheerka, context, foo, bar, isa1, isa2, hasa1, hasa2 = self.init_concepts(
|
||||
@@ -53,14 +53,14 @@ class TestSheerkaConceptsAlgebra(TestUsingMemoryBasedSheerka):
|
||||
|
||||
res = sheerka.csub(context, new_foo)
|
||||
assert isinstance(res, Concept)
|
||||
assert res.metadata.props == res.metadata.props
|
||||
assert res.get_metadata().props == res.get_metadata().props
|
||||
|
||||
res = sheerka.csub(context, new_foo, new_bar)
|
||||
assert isinstance(res, Concept)
|
||||
assert res.metadata.props == {BuiltinConcepts.ISA: {isa2},
|
||||
assert res.get_metadata().props == {BuiltinConcepts.ISA: {isa2},
|
||||
BuiltinConcepts.HASA: {hasa2}, }
|
||||
|
||||
def test_i_can_recognize_myself_when_cache_only_is_not_set(self):
|
||||
def test_i_can_recognize_myself_when_using_sdp_repository(self):
|
||||
sheerka, context, foo, isa1, hasa1, = self.init_concepts("foo", "isa1", "has1",
|
||||
cache_only=False,
|
||||
create_new=True)
|
||||
@@ -73,7 +73,7 @@ class TestSheerkaConceptsAlgebra(TestUsingMemoryBasedSheerka):
|
||||
|
||||
assert sheerka.recognize(new_foo, all_scores=True) == [ConceptScore(1, new_foo, new_foo)]
|
||||
|
||||
def test_i_can_recognize_myself_when_cache_only_is_set(self):
|
||||
def test_i_can_recognize_myself_when_not_using_sdp_repository(self):
|
||||
sheerka, context, foo, isa1, hasa1, = self.init_concepts("foo", "isa1", "has1")
|
||||
|
||||
new_foo = sheerka.new("foo")
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
import pytest
|
||||
from core.builtin_concepts import BuiltinConcepts
|
||||
from core.concept import PROPERTIES_TO_SERIALIZE, Concept, DEFINITION_TYPE_DEF
|
||||
from core.concept import PROPERTIES_TO_SERIALIZE, Concept, DEFINITION_TYPE_DEF, get_concept_attrs
|
||||
from core.sheerka.Sheerka import Sheerka
|
||||
|
||||
from tests.TestUsingFileBasedSheerka import TestUsingFileBasedSheerka
|
||||
@@ -22,10 +22,11 @@ class TestSheerkaCreateNewConcept(TestUsingMemoryBasedSheerka):
|
||||
|
||||
concept_found = res.value.body
|
||||
for prop in PROPERTIES_TO_SERIALIZE:
|
||||
assert getattr(concept_found.metadata, prop) == getattr(concept.metadata, prop)
|
||||
assert getattr(concept_found.get_metadata(), prop) == getattr(concept.get_metadata(), prop)
|
||||
|
||||
assert concept_found.key == "__var__0 + __var__1"
|
||||
assert concept_found.id == "1001"
|
||||
assert get_concept_attrs(concept) == ['a', 'b']
|
||||
|
||||
# saved in cache
|
||||
assert sheerka.has_id(concept.id)
|
||||
@@ -63,7 +64,7 @@ class TestSheerkaCreateNewConcept(TestUsingMemoryBasedSheerka):
|
||||
|
||||
concept_found = res.value.body
|
||||
for prop in PROPERTIES_TO_SERIALIZE:
|
||||
assert getattr(concept_found.metadata, prop) == getattr(concept.metadata, prop)
|
||||
assert getattr(concept_found.get_metadata(), prop) == getattr(concept.get_metadata(), prop)
|
||||
|
||||
assert concept_found.key == "hello __var__0"
|
||||
assert concept_found.id == "1001"
|
||||
@@ -120,7 +121,7 @@ class TestSheerkaCreateNewConcept(TestUsingMemoryBasedSheerka):
|
||||
sheerka = self.get_sheerka()
|
||||
concept1 = self.get_default_concept()
|
||||
concept2 = self.get_default_concept()
|
||||
concept2.metadata.body = "a+b"
|
||||
concept2.get_metadata().body = "a+b"
|
||||
|
||||
res1 = sheerka.create_new_concept(self.get_context(sheerka), concept1)
|
||||
res2 = sheerka.create_new_concept(self.get_context(sheerka), concept2)
|
||||
@@ -149,7 +150,7 @@ class TestSheerkaCreateNewConcept(TestUsingMemoryBasedSheerka):
|
||||
|
||||
assert res.status
|
||||
assert sheerka.get_by_name(concept.name) == concept
|
||||
assert sheerka.get_by_name(concept.metadata.definition) == concept
|
||||
assert sheerka.get_by_name(concept.get_metadata().definition) == concept
|
||||
|
||||
concept = Concept(name="foo", definition="foo", definition_type=DEFINITION_TYPE_DEF)
|
||||
res = sheerka.create_new_concept(context, concept)
|
||||
@@ -273,6 +274,7 @@ class TestSheerkaCreateNewConceptFileBased(TestUsingFileBasedSheerka):
|
||||
assert len(sheerka.sdp.get(Sheerka.CONCEPTS_BY_KEY_ENTRY, "foo")) == 2
|
||||
|
||||
sheerka = self.get_sheerka() # new instance
|
||||
context = self.get_context(sheerka)
|
||||
sheerka.create_new_concept(context, Concept("foo", body="3"))
|
||||
sheerka.cache_manager.commit(context)
|
||||
|
||||
|
||||
@@ -0,0 +1,425 @@
|
||||
import pytest
|
||||
from core.builtin_concepts import BuiltinConcepts
|
||||
from core.sheerka.ExecutionContext import ExecutionContext
|
||||
from core.sheerka.services.SheerkaDebugManager import SheerkaDebugManager, DebugVarSetting, DebugRuleSetting
|
||||
from sdp.sheerkaDataProvider import Event
|
||||
|
||||
from tests.TestUsingMemoryBasedSheerka import TestUsingMemoryBasedSheerka
|
||||
|
||||
|
||||
class TestSheerkaDebugManager(TestUsingMemoryBasedSheerka):
|
||||
|
||||
def test_i_can_activate_debug(self):
|
||||
sheerka, context = self.init_concepts()
|
||||
|
||||
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
|
||||
|
||||
@pytest.mark.parametrize("settings, expected", [
|
||||
({"service": "my_service"}, True),
|
||||
({"service": "other_service"}, False),
|
||||
({"method": "my_method"}, True),
|
||||
({"method": "other_method"}, False),
|
||||
])
|
||||
def test_i_can_compute_debug(self, settings, expected):
|
||||
sheerka, context = self.init_concepts()
|
||||
service = sheerka.services[SheerkaDebugManager.NAME]
|
||||
service.set_debug(context, True)
|
||||
|
||||
service.debug_var(context, **settings)
|
||||
assert service.compute_debug("my_service", "my_method", context) == expected
|
||||
|
||||
def test_i_can_compute_debug_for_context(self):
|
||||
sheerka, root_context = self.init_concepts()
|
||||
service = sheerka.services[SheerkaDebugManager.NAME]
|
||||
service.set_debug(root_context, True)
|
||||
|
||||
context1 = root_context.push(BuiltinConcepts.TESTING, None)
|
||||
context2 = root_context.push(BuiltinConcepts.TESTING, None)
|
||||
service.debug_var(root_context, context_id=context1.id)
|
||||
|
||||
assert service.compute_debug("my_service", "my_method", context1)
|
||||
assert not service.compute_debug("my_service", "my_method", context2)
|
||||
|
||||
def test_i_can_disable_debug_setting(self):
|
||||
sheerka, context = self.init_concepts()
|
||||
service = sheerka.services[SheerkaDebugManager.NAME]
|
||||
|
||||
service.debug_var(context, service="my_service", enabled=False)
|
||||
assert not service.compute_debug("my_service", "my_method", context)
|
||||
|
||||
def test_i_can_compute_combination_of_debug_settings(self):
|
||||
sheerka, context = self.init_concepts()
|
||||
service = sheerka.services[SheerkaDebugManager.NAME]
|
||||
service.set_debug(context, True)
|
||||
|
||||
service.debug_var(context, service="my_service", enabled=True)
|
||||
service.debug_var(context, method="my_method", enabled=False)
|
||||
service.debug_var(context, variable="xxx", enabled=False) # is not used
|
||||
service.debug_var(context, debug_id=1, enabled=False) # is not used
|
||||
|
||||
assert not service.compute_debug("my_service", "my_method", context) # False > True
|
||||
assert service.compute_debug("my_service", "another_method", context)
|
||||
assert not service.compute_debug("another_service", "my_method", context)
|
||||
|
||||
def test_variable_debug_is_deactivated_by_default(self):
|
||||
sheerka, context = self.init_concepts()
|
||||
service = sheerka.services[SheerkaDebugManager.NAME]
|
||||
service.set_debug(context, True)
|
||||
|
||||
assert not service.compute_var_debug("my_service", "my_method", 0, "my_variable", 0)
|
||||
|
||||
def test_i_can_activate_variable_debug_for_all_variables(self):
|
||||
sheerka, context = self.init_concepts()
|
||||
service = sheerka.services[SheerkaDebugManager.NAME]
|
||||
service.set_debug(context, True)
|
||||
|
||||
service.debug_var(context, variable="*")
|
||||
|
||||
assert service.compute_var_debug("my_service", "my_method", 0, "my_variable", 0) == True
|
||||
|
||||
def test_i_can_activate_variable_display_for_all_variables(self):
|
||||
sheerka, context = self.init_concepts()
|
||||
service = sheerka.services[SheerkaDebugManager.NAME]
|
||||
service.set_debug(context, True)
|
||||
|
||||
service.debug_var(context, variable="*", enabled='list')
|
||||
|
||||
assert service.compute_var_debug("my_service", "my_method", 0, "my_variable", 0) == 'list'
|
||||
|
||||
def test_i_can_disable_variable_debug(self):
|
||||
sheerka, context = self.init_concepts()
|
||||
service = sheerka.services[SheerkaDebugManager.NAME]
|
||||
service.set_debug(context, True)
|
||||
|
||||
service.debug_var(context, variable="my_variable", enabled=False)
|
||||
assert not service.compute_var_debug("my_service", "my_method", 0, "my_variable", 0)
|
||||
|
||||
@pytest.mark.parametrize("enabled_1, enabled_2, expected", [
|
||||
(False, False, False),
|
||||
(False, True, False),
|
||||
(False, 'list', False),
|
||||
(True, False, False),
|
||||
(True, True, True),
|
||||
(True, 'list', 'list'),
|
||||
('list', False, False),
|
||||
('list', True, 'list'),
|
||||
('list', 'list', 'list'),
|
||||
])
|
||||
def test_i_can_compute_combination_of_debug_var_settings(self, enabled_1, enabled_2, expected):
|
||||
sheerka, context = self.init_concepts()
|
||||
service = sheerka.services[SheerkaDebugManager.NAME]
|
||||
service.set_debug(context, True)
|
||||
|
||||
service.debug_var(context, variable="my_variable", enabled=enabled_1)
|
||||
service.debug_var(context, variable="*", enabled=enabled_2)
|
||||
|
||||
assert service.compute_var_debug("my_service", "my_method", 0, "my_variable", 0) == expected
|
||||
|
||||
@pytest.mark.parametrize("settings, expected", [
|
||||
({"service": "my_service"}, True),
|
||||
({"service": "other_service"}, False),
|
||||
({"method": "my_method"}, True),
|
||||
({"method": "other_method"}, False),
|
||||
({"context_id": 0}, True),
|
||||
({"context_id": 1}, False),
|
||||
])
|
||||
def test_service_and_method_and_context_id_are_tested_before_disabling_a_variable(self, settings, expected):
|
||||
sheerka, context = self.init_concepts()
|
||||
service = sheerka.services[SheerkaDebugManager.NAME]
|
||||
service.set_debug(context, True)
|
||||
|
||||
settings["variable"] = "my_variable"
|
||||
|
||||
service.debug_var(context, **settings, enabled=True)
|
||||
assert service.compute_var_debug("my_service", "my_method", 0, "my_variable", 0) == expected
|
||||
|
||||
@pytest.mark.parametrize("context_children, expected", [
|
||||
(True, True),
|
||||
(False, False),
|
||||
])
|
||||
def test_i_can_compute_debug_var_for_context_children(self, context_children, expected):
|
||||
sheerka, context = self.init_concepts()
|
||||
service = sheerka.services[SheerkaDebugManager.NAME]
|
||||
service.set_debug(context, True)
|
||||
|
||||
sub_context = context.push(BuiltinConcepts.TESTING, None)
|
||||
sub_sub_context = sub_context.push(BuiltinConcepts.TESTING, None)
|
||||
|
||||
service.debug_var(context, context_id=sub_context.id, context_children=context_children)
|
||||
assert service.compute_debug("my_service", "my_method", sub_sub_context) == expected
|
||||
|
||||
def test_i_can_update_debug_setting(self):
|
||||
sheerka, context = self.init_concepts()
|
||||
service = sheerka.services[SheerkaDebugManager.NAME]
|
||||
|
||||
service.debug_var(context, service="my_service", enabled=True)
|
||||
service.debug_var(context, service="my_service", enabled=False)
|
||||
|
||||
assert len(service.debug_vars_settings) == 1
|
||||
assert not service.debug_vars_settings[0].enabled
|
||||
|
||||
service.debug_var(context, service="my_service", enabled=True)
|
||||
assert len(service.debug_vars_settings) == 1
|
||||
assert service.debug_vars_settings[0].enabled
|
||||
|
||||
def test_i_can_reset_debug_settings(self):
|
||||
sheerka, context = self.init_concepts()
|
||||
service = sheerka.services[SheerkaDebugManager.NAME]
|
||||
service.set_debug(context, True)
|
||||
|
||||
service.debug_var(context, service="my_service")
|
||||
assert service.compute_debug("my_service", "my_method", context)
|
||||
|
||||
service.reset_debug(context)
|
||||
assert not service.compute_debug("my_service", "my_method", context)
|
||||
|
||||
@pytest.mark.parametrize("settings, expected", [
|
||||
({"rule": "1"}, True),
|
||||
({"rule": "2"}, False),
|
||||
({"context_id": 0}, True),
|
||||
({"context_id": 1}, False),
|
||||
({"debug_id": 0}, True),
|
||||
({"debug_id": 1}, False),
|
||||
])
|
||||
def test_i_can_compute_rules_debug_settings(self, settings, expected):
|
||||
sheerka, context = self.init_concepts()
|
||||
service = sheerka.services[SheerkaDebugManager.NAME]
|
||||
service.set_debug(context, True)
|
||||
|
||||
service.debug_rule(context, **settings)
|
||||
assert service.compute_debug_rule("1", 0, 0) == expected
|
||||
|
||||
def test_state_is_saved_and_restored(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, False)
|
||||
sheerka.activate_debug_for(root_context, 1, children=True)
|
||||
sheerka.activate_debug_for(root_context, "SomeVar")
|
||||
sheerka.debug_rule(root_context, "1", 10, 15)
|
||||
sheerka.debug_var(root_context, service="service_name")
|
||||
|
||||
another_service = SheerkaDebugManager(sheerka)
|
||||
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_rules_settings == [
|
||||
DebugRuleSetting("1", 10, 15, True)
|
||||
]
|
||||
assert another_service.debug_vars_settings == [
|
||||
DebugVarSetting('service_name', None, None, None, False, None, False, True)]
|
||||
@@ -1,6 +1,7 @@
|
||||
import pytest
|
||||
from core.builtin_concepts import BuiltinConcepts, ReturnValueConcept, ParserResultConcept
|
||||
from core.concept import Concept, DoNotResolve, ConceptParts, Property, InfiniteRecursionResolved, CB, NotInit
|
||||
from core.concept import Concept, DoNotResolve, ConceptParts, InfiniteRecursionResolved, CB, NotInit, \
|
||||
concept_part_value
|
||||
from core.sheerka.services.SheerkaEvaluateConcept import SheerkaEvaluateConcept
|
||||
from core.sheerka.services.SheerkaMemory import SheerkaMemory
|
||||
from parsers.PythonParser import PythonNode
|
||||
@@ -11,7 +12,7 @@ from tests.TestUsingMemoryBasedSheerka import TestUsingMemoryBasedSheerka
|
||||
class TestSheerkaEvaluateConcept(TestUsingMemoryBasedSheerka):
|
||||
|
||||
@pytest.mark.parametrize("body, expected", [
|
||||
(None, BuiltinConcepts.NOT_INITIALIZED),
|
||||
(None, NotInit),
|
||||
("", ""),
|
||||
("1", 1),
|
||||
("1+1", 2),
|
||||
@@ -27,13 +28,13 @@ class TestSheerkaEvaluateConcept(TestUsingMemoryBasedSheerka):
|
||||
|
||||
assert evaluated.key == concept.key
|
||||
assert evaluated.body == expected
|
||||
assert evaluated.metadata.body == body
|
||||
assert evaluated.metadata.pre is None
|
||||
assert evaluated.metadata.post is None
|
||||
assert evaluated.metadata.where is None
|
||||
assert evaluated.get_metadata().body == body
|
||||
assert evaluated.get_metadata().pre is None
|
||||
assert evaluated.get_metadata().post is None
|
||||
assert evaluated.get_metadata().where is None
|
||||
assert evaluated.variables() == {}
|
||||
assert evaluated.metadata.is_evaluated
|
||||
assert len(evaluated.values) == 0 if body is None else 1
|
||||
assert evaluated.get_metadata().is_evaluated
|
||||
assert len(evaluated.values()) == 0 if body is None else 1
|
||||
|
||||
assert "foo" in sheerka.services[SheerkaMemory.NAME].registration
|
||||
|
||||
@@ -59,13 +60,13 @@ class TestSheerkaEvaluateConcept(TestUsingMemoryBasedSheerka):
|
||||
evaluated = sheerka.evaluate_concept(context, concept)
|
||||
|
||||
assert evaluated.key == concept.key
|
||||
assert evaluated.metadata.body is None
|
||||
assert evaluated.metadata.post == expr
|
||||
assert evaluated.metadata.pre is None
|
||||
assert evaluated.metadata.where is None
|
||||
assert evaluated.get_metadata().body is None
|
||||
assert evaluated.get_metadata().post == expr
|
||||
assert evaluated.get_metadata().pre is None
|
||||
assert evaluated.get_metadata().where is None
|
||||
assert evaluated.get_value(ConceptParts.POST) == expected
|
||||
assert evaluated.variables() == {}
|
||||
assert not evaluated.metadata.is_evaluated
|
||||
assert not evaluated.get_metadata().is_evaluated
|
||||
assert len(evaluated.values) == 0 if expr is None else 1
|
||||
|
||||
@pytest.mark.parametrize("expr, expected", [
|
||||
@@ -84,12 +85,12 @@ class TestSheerkaEvaluateConcept(TestUsingMemoryBasedSheerka):
|
||||
evaluated = sheerka.evaluate_concept(context, concept)
|
||||
|
||||
assert evaluated.key == concept.key
|
||||
assert evaluated.metadata.pre is None
|
||||
assert evaluated.metadata.pre is None
|
||||
assert evaluated.metadata.post is None
|
||||
assert evaluated.metadata.where is None
|
||||
assert evaluated.variables() == {"a": Property("a", expected)}
|
||||
assert evaluated.metadata.is_evaluated
|
||||
assert evaluated.get_metadata().pre is None
|
||||
assert evaluated.get_metadata().pre is None
|
||||
assert evaluated.get_metadata().post is None
|
||||
assert evaluated.get_metadata().where is None
|
||||
assert evaluated.variables() == {"a": expected}
|
||||
assert evaluated.get_metadata().is_evaluated
|
||||
|
||||
def test_i_can_evaluate_when_the_body_is_the_name_of_the_concept(self):
|
||||
# to prove that I can distinguish from a string
|
||||
@@ -102,33 +103,33 @@ class TestSheerkaEvaluateConcept(TestUsingMemoryBasedSheerka):
|
||||
|
||||
def test_i_can_evaluate_metadata_using_do_not_resolve(self):
|
||||
sheerka, context, concept = self.init_concepts(Concept("foo"), eval_body=True)
|
||||
concept.compiled[ConceptParts.BODY] = DoNotResolve("do not resolve")
|
||||
concept.get_compiled()[ConceptParts.BODY] = DoNotResolve("do not resolve")
|
||||
|
||||
evaluated = sheerka.evaluate_concept(context, concept)
|
||||
|
||||
assert evaluated.body == "do not resolve"
|
||||
assert evaluated.metadata.is_evaluated
|
||||
assert evaluated.get_metadata().is_evaluated
|
||||
|
||||
def test_i_can_evaluate_variable_using_do_not_resolve(self):
|
||||
sheerka, context, concept = self.init_concepts(Concept("foo").def_var("a"), eval_body=True)
|
||||
concept.compiled["a"] = DoNotResolve("do not resolve")
|
||||
concept.get_compiled()["a"] = DoNotResolve("do not resolve")
|
||||
|
||||
evaluated = sheerka.evaluate_concept(context, concept)
|
||||
|
||||
assert evaluated.get_value("a") == "do not resolve"
|
||||
assert evaluated.metadata.is_evaluated
|
||||
assert evaluated.get_metadata().is_evaluated
|
||||
|
||||
def test_original_value_is_overridden_when_using_do_no_resolve(self):
|
||||
concept = Concept("foo", body="original value").def_var("a", "original value")
|
||||
sheerka, context, concept = self.init_concepts(concept, eval_body=True)
|
||||
concept.compiled["a"] = DoNotResolve("do not resolve")
|
||||
concept.compiled[ConceptParts.BODY] = DoNotResolve("do not resolve")
|
||||
concept.get_compiled()["a"] = DoNotResolve("do not resolve")
|
||||
concept.get_compiled()[ConceptParts.BODY] = DoNotResolve("do not resolve")
|
||||
|
||||
evaluated = sheerka.evaluate_concept(context, concept)
|
||||
|
||||
assert evaluated.body == "do not resolve"
|
||||
assert evaluated.get_value("a") == "do not resolve"
|
||||
assert evaluated.metadata.is_evaluated
|
||||
assert evaluated.get_metadata().is_evaluated
|
||||
|
||||
def test_variables_are_evaluated_before_body(self):
|
||||
sheerka, context, concept = self.init_concepts(Concept("foo", body="a+1").def_var("a", "10"), eval_body=True)
|
||||
@@ -145,9 +146,9 @@ class TestSheerkaEvaluateConcept(TestUsingMemoryBasedSheerka):
|
||||
|
||||
evaluated = sheerka.evaluate_concept(context, concept)
|
||||
|
||||
assert evaluated == CB("foo", CB("a", BuiltinConcepts.NOT_INITIALIZED))
|
||||
assert evaluated.metadata.is_evaluated
|
||||
assert evaluated.body.metadata.is_evaluated
|
||||
assert evaluated == CB("foo", CB("a", NotInit))
|
||||
assert evaluated.get_metadata().is_evaluated
|
||||
assert evaluated.body.get_metadata().is_evaluated
|
||||
|
||||
def test_i_can_evaluate_when_the_referenced_concept_has_a_body(self):
|
||||
sheerka, context, concept_a, concept = self.init_concepts(
|
||||
@@ -159,8 +160,8 @@ class TestSheerkaEvaluateConcept(TestUsingMemoryBasedSheerka):
|
||||
|
||||
assert evaluated.key == concept.key
|
||||
assert evaluated.body == CB("a", 1)
|
||||
assert not concept_a.metadata.is_evaluated
|
||||
assert evaluated.metadata.is_evaluated
|
||||
assert not concept_a.get_metadata().is_evaluated
|
||||
assert evaluated.get_metadata().is_evaluated
|
||||
|
||||
def test_i_can_evaluate_concept_of_concept_when_the_leaf_has_a_body(self):
|
||||
sheerka, context, concept_a, concept_b, concept_c, concept_d = self.init_concepts(
|
||||
@@ -176,7 +177,7 @@ class TestSheerkaEvaluateConcept(TestUsingMemoryBasedSheerka):
|
||||
expected = CB("c", CB("b", CB("a", "a")))
|
||||
assert evaluated.body == expected
|
||||
assert sheerka.objvalue(evaluated) == 'a'
|
||||
assert evaluated.metadata.is_evaluated
|
||||
assert evaluated.get_metadata().is_evaluated
|
||||
|
||||
def test_i_can_evaluate_concept_of_concept_does_not_have_a_body(self):
|
||||
sheerka, context, concept_a, concept_b, concept_c, concept_d = self.init_concepts(
|
||||
@@ -189,10 +190,10 @@ class TestSheerkaEvaluateConcept(TestUsingMemoryBasedSheerka):
|
||||
evaluated = sheerka.evaluate_concept(context, concept_d)
|
||||
|
||||
assert evaluated.key == concept_d.key
|
||||
expected = CB("c", CB("b", CB("a", BuiltinConcepts.NOT_INITIALIZED)))
|
||||
expected = CB("c", CB("b", CB("a", NotInit)))
|
||||
assert evaluated.body == expected
|
||||
assert sheerka.objvalue(evaluated) == CB("a", BuiltinConcepts.NOT_INITIALIZED)
|
||||
assert evaluated.metadata.is_evaluated
|
||||
assert sheerka.objvalue(evaluated) == CB("a", NotInit)
|
||||
assert evaluated.get_metadata().is_evaluated
|
||||
|
||||
def test_i_can_evaluate_concept_when_variables_reference_others_concepts_1(self):
|
||||
"""
|
||||
@@ -273,7 +274,7 @@ class TestSheerkaEvaluateConcept(TestUsingMemoryBasedSheerka):
|
||||
sheerka, context, concept_a = self.init_concepts(Concept(name="a", body="'a'"), eval_body=True)
|
||||
|
||||
concept = Concept("foo").def_var("a")
|
||||
concept.compiled["a"] = concept_a
|
||||
concept.get_compiled()["a"] = concept_a
|
||||
evaluated = sheerka.evaluate_concept(context, concept)
|
||||
|
||||
assert evaluated.key == concept.key
|
||||
@@ -306,7 +307,7 @@ class TestSheerkaEvaluateConcept(TestUsingMemoryBasedSheerka):
|
||||
foo = Concept("foo", body="1")
|
||||
|
||||
concept = Concept("to_eval").def_var("prop")
|
||||
concept.compiled["prop"] = [foo, DoNotResolve("1")]
|
||||
concept.get_compiled()["prop"] = [foo, DoNotResolve("1")]
|
||||
evaluated = sheerka.evaluate_concept(self.get_context(sheerka, True), concept)
|
||||
|
||||
variables = evaluated.get_value("prop")
|
||||
@@ -321,13 +322,13 @@ class TestSheerkaEvaluateConcept(TestUsingMemoryBasedSheerka):
|
||||
parser_result = ParserResultConcept(parser="who", value=python_node)
|
||||
|
||||
concept = Concept("to_eval").def_var("prop")
|
||||
concept.compiled["prop"] = [ReturnValueConcept("who", True, parser_result)]
|
||||
concept.get_compiled()["prop"] = [ReturnValueConcept("who", True, parser_result)]
|
||||
evaluated = sheerka.evaluate_concept(self.get_context(sheerka, True), concept)
|
||||
assert evaluated.get_value("prop") == 2
|
||||
|
||||
# also works when only one return value
|
||||
concept = Concept("to_eval").def_var("prop")
|
||||
concept.compiled["prop"] = ReturnValueConcept("who", True, parser_result)
|
||||
concept.get_compiled()["prop"] = ReturnValueConcept("who", True, parser_result)
|
||||
evaluated = sheerka.evaluate_concept(self.get_context(sheerka, True), concept)
|
||||
assert evaluated.get_value("prop") == 2
|
||||
|
||||
@@ -342,7 +343,7 @@ class TestSheerkaEvaluateConcept(TestUsingMemoryBasedSheerka):
|
||||
evaluated = sheerka.evaluate_concept(context, add_instance)
|
||||
|
||||
assert evaluated.key == add_instance.key
|
||||
assert evaluated.metadata.is_evaluated
|
||||
assert evaluated.get_metadata().is_evaluated
|
||||
assert sheerka.objvalue(evaluated) == 3
|
||||
|
||||
def test_i_can_evaluate_when_body_is_a_concept_with_its_own_variables_and_different_names(self):
|
||||
@@ -356,7 +357,7 @@ class TestSheerkaEvaluateConcept(TestUsingMemoryBasedSheerka):
|
||||
evaluated = sheerka.evaluate_concept(context, add_instance)
|
||||
|
||||
assert evaluated.key == add_instance.key
|
||||
assert evaluated.metadata.is_evaluated
|
||||
assert evaluated.get_metadata().is_evaluated
|
||||
assert sheerka.objvalue(evaluated) == 3
|
||||
|
||||
def test_i_can_evaluate_when_body_is_a_concept_with_its_own_variables_multiple_levels(self):
|
||||
@@ -371,7 +372,7 @@ class TestSheerkaEvaluateConcept(TestUsingMemoryBasedSheerka):
|
||||
evaluated = sheerka.evaluate_concept(context, inc_instance)
|
||||
|
||||
assert evaluated.key == inc_instance.key
|
||||
assert evaluated.metadata.is_evaluated
|
||||
assert evaluated.get_metadata().is_evaluated
|
||||
assert sheerka.objvalue(evaluated) == 2
|
||||
|
||||
def test_i_can_reference_sheerka(self):
|
||||
@@ -445,12 +446,12 @@ class TestSheerkaEvaluateConcept(TestUsingMemoryBasedSheerka):
|
||||
assert evaluated.key == concept.init_key().key
|
||||
|
||||
@pytest.mark.parametrize("where_clause, expected, expected_prop, expected_body", [
|
||||
("True", True, None, BuiltinConcepts.NOT_INITIALIZED),
|
||||
("False", False, ConceptParts.WHERE, BuiltinConcepts.NOT_INITIALIZED),
|
||||
("True", True, None, NotInit),
|
||||
("False", False, ConceptParts.WHERE, NotInit),
|
||||
("self < 10", False, ConceptParts.WHERE, 10),
|
||||
("self < 11", True, None, 10),
|
||||
("a < 20", False, "a", BuiltinConcepts.NOT_INITIALIZED),
|
||||
("a > 19", True, None, BuiltinConcepts.NOT_INITIALIZED),
|
||||
("a < 20", False, "a", NotInit),
|
||||
("a > 19", True, None, NotInit),
|
||||
("a + self > 20", True, None, 10),
|
||||
("a + self < 20", False, ConceptParts.WHERE, 10),
|
||||
])
|
||||
@@ -602,7 +603,7 @@ class TestSheerkaEvaluateConcept(TestUsingMemoryBasedSheerka):
|
||||
)
|
||||
|
||||
evaluated = sheerka.evaluate_concept(context, plus)
|
||||
assert evaluated.key == BuiltinConcepts.CONDITION_FAILED
|
||||
assert evaluated.key == str(BuiltinConcepts.CONDITION_FAILED)
|
||||
assert evaluated.body == "a is an int"
|
||||
|
||||
def test_i_can_enable_disable_where_clause_evaluation(self):
|
||||
@@ -728,18 +729,18 @@ class TestSheerkaEvaluateConcept(TestUsingMemoryBasedSheerka):
|
||||
|
||||
one = sheerka.new("one")
|
||||
number2 = sheerka.new("number")
|
||||
number2.compiled["one"] = one
|
||||
number2.compiled[ConceptParts.BODY] = one
|
||||
number2.get_compiled()["one"] = one
|
||||
number2.get_compiled()[ConceptParts.BODY] = one
|
||||
forties = sheerka.new("forties")
|
||||
forties.compiled["forty"] = sheerka.new("forty")
|
||||
forties.compiled["number"] = number2
|
||||
forties.get_compiled()["forty"] = sheerka.new("forty")
|
||||
forties.get_compiled()["number"] = number2
|
||||
|
||||
number1 = sheerka.new("number")
|
||||
number1.compiled["forties"] = forties
|
||||
number1.compiled[ConceptParts.BODY] = forties
|
||||
number1.get_compiled()["forties"] = forties
|
||||
number1.get_compiled()[ConceptParts.BODY] = forties
|
||||
|
||||
forty_one_thousand = sheerka.new("thousand")
|
||||
forty_one_thousand.compiled["number"] = number1
|
||||
forty_one_thousand.get_compiled()["number"] = number1
|
||||
|
||||
evaluated = sheerka.evaluate_concept(context, forty_one_thousand)
|
||||
|
||||
@@ -758,15 +759,15 @@ class TestSheerkaEvaluateConcept(TestUsingMemoryBasedSheerka):
|
||||
assert "a" in sheerka.locals
|
||||
|
||||
@pytest.mark.parametrize("metadata", [
|
||||
"where",
|
||||
"pre",
|
||||
"post",
|
||||
"ret"
|
||||
ConceptParts.WHERE,
|
||||
ConceptParts.PRE,
|
||||
ConceptParts.POST,
|
||||
ConceptParts.RET
|
||||
])
|
||||
def test_i_cannot_evaluate_python_statement_in_where_pre_post_ret(self, metadata, capsys):
|
||||
sheerka, context, foo = self.init_concepts("foo")
|
||||
setattr(foo.metadata, metadata, "a=10; print('10')")
|
||||
foo.metadata.need_validation = True
|
||||
setattr(foo.get_metadata(), concept_part_value(metadata), "a=10; print('10')")
|
||||
foo.get_metadata().need_validation = True
|
||||
|
||||
evaluated = sheerka.evaluate_concept(context, foo, eval_body=True)
|
||||
captured = capsys.readouterr()
|
||||
@@ -774,7 +775,7 @@ class TestSheerkaEvaluateConcept(TestUsingMemoryBasedSheerka):
|
||||
assert sheerka.isinstance(evaluated, BuiltinConcepts.CONCEPT_EVAL_ERROR)
|
||||
error = evaluated.body
|
||||
assert sheerka.isinstance(error, BuiltinConcepts.PYTHON_SECURITY_ERROR)
|
||||
assert error.prop.value == metadata
|
||||
assert error.prop == metadata
|
||||
assert error.body == "a=10; print('10')"
|
||||
assert captured.out == ""
|
||||
|
||||
@@ -813,13 +814,14 @@ class TestSheerkaEvaluateConcept(TestUsingMemoryBasedSheerka):
|
||||
|
||||
@pytest.mark.parametrize("concept, eval_body, expected", [
|
||||
(Concept("foo"), False, []),
|
||||
(Concept("foo", pre="pre", post="post", ret="ret", where="where"), False, ["pre", "post"]),
|
||||
(Concept("foo", pre="pr", post="p", ret="r", where="w"), True, ["pre", "ret", "post", "variables", "body"]),
|
||||
(Concept("foo", pre="a").def_var("a"), False, ["variables", "pre"]),
|
||||
(Concept("foo", pre="self"), False, ["body", "pre"]),
|
||||
(Concept("foo", pre="self + a").def_var("a"), False, ["variables", "body", "pre"]),
|
||||
(Concept("foo", pre="self + a", ret="ret").def_var("a"), False, ["variables", "body", "pre"]),
|
||||
(Concept("foo", pre="self + a", ret="ret").def_var("a"), True, ["variables", "body", "pre", "ret"]),
|
||||
(Concept("foo", pre="pre", post="post", ret="ret", where="where"), False, ["#pre#", "#post#"]),
|
||||
(Concept("foo", pre="pr", post="p", ret="r", where="w"), True,
|
||||
["#pre#", "#ret#", "#post#", "variables", "#body#"]),
|
||||
(Concept("foo", pre="a").def_var("a"), False, ["variables", "#pre#"]),
|
||||
(Concept("foo", pre="self"), False, ["#body#", "#pre#"]),
|
||||
(Concept("foo", pre="self + a").def_var("a"), False, ["variables", "#body#", "#pre#"]),
|
||||
(Concept("foo", pre="self + a", ret="ret").def_var("a"), False, ["variables", "#body#", "#pre#"]),
|
||||
(Concept("foo", pre="self + a", ret="ret").def_var("a"), True, ["variables", "#body#", "#pre#", "#ret#"]),
|
||||
(Concept("foo", body="body"), False, [])
|
||||
])
|
||||
def test_i_can_compute_metadata_to_eval(self, concept, eval_body, expected):
|
||||
@@ -839,27 +841,27 @@ class TestSheerkaEvaluateConcept(TestUsingMemoryBasedSheerka):
|
||||
context = self.get_context(sheerka, eval_where=True)
|
||||
concept = Concept("foo", where="where")
|
||||
service.initialize_concept_asts(context, concept)
|
||||
assert service.compute_metadata_to_eval(context, concept) == ["where"]
|
||||
assert service.compute_metadata_to_eval(context, concept) == ["#where#"]
|
||||
|
||||
concept = Concept("foo", where="where a").def_var("a")
|
||||
service.initialize_concept_asts(context, concept)
|
||||
assert service.compute_metadata_to_eval(context, concept) == ["variables", "where"]
|
||||
assert service.compute_metadata_to_eval(context, concept) == ["variables", "#where#"]
|
||||
|
||||
concept = Concept("foo", where="where self")
|
||||
service.initialize_concept_asts(context, concept)
|
||||
assert service.compute_metadata_to_eval(context, concept) == ["body", "where"]
|
||||
assert service.compute_metadata_to_eval(context, concept) == ["#body#", "#where#"]
|
||||
|
||||
context = self.get_context(sheerka, eval_body=True)
|
||||
concept = Concept("foo")
|
||||
assert service.compute_metadata_to_eval(context, concept) == ["variables", "body"]
|
||||
assert service.compute_metadata_to_eval(context, concept) == ["variables", "#body#"]
|
||||
|
||||
context = self.get_context(sheerka, eval_body=True)
|
||||
concept = Concept("foo").def_var("a")
|
||||
assert service.compute_metadata_to_eval(context, concept) == ["variables", "body"]
|
||||
assert service.compute_metadata_to_eval(context, concept) == ["variables", "#body#"]
|
||||
|
||||
context = self.get_context(sheerka, eval_body=True)
|
||||
concept = Concept("foo", body="body").def_var("a")
|
||||
assert service.compute_metadata_to_eval(context, concept) == ["variables", "body"]
|
||||
assert service.compute_metadata_to_eval(context, concept) == ["variables", "#body#"]
|
||||
|
||||
@pytest.mark.parametrize("concept, expected", [
|
||||
(Concept("foo"), True),
|
||||
@@ -870,7 +872,7 @@ class TestSheerkaEvaluateConcept(TestUsingMemoryBasedSheerka):
|
||||
evaluated = sheerka.evaluate_concept(context, concept, eval_body=True)
|
||||
|
||||
assert evaluated.key == concept.key
|
||||
assert concept.metadata.is_evaluated == expected
|
||||
assert concept.get_metadata().is_evaluated == expected
|
||||
|
||||
def test_i_only_compute_the_requested_metadata(self):
|
||||
sheerka, context, concept = self.init_concepts(
|
||||
@@ -879,8 +881,8 @@ class TestSheerkaEvaluateConcept(TestUsingMemoryBasedSheerka):
|
||||
context.protected_hints.add(BuiltinConcepts.EVAL_WHERE_REQUESTED) # to prove that we do not care
|
||||
context.protected_hints.add(BuiltinConcepts.EVAL_BODY_REQUESTED) # to prove that we do not care
|
||||
|
||||
evaluated = sheerka.evaluate_concept(context, concept, metadata=['pre'])
|
||||
assert evaluated.values == {"a": Property("a", NotInit), ConceptParts.PRE: Property(ConceptParts.PRE, 'pre')}
|
||||
evaluated = sheerka.evaluate_concept(context, concept, metadata=[ConceptParts.PRE])
|
||||
assert evaluated.values() == {"a": NotInit, ConceptParts.PRE: 'pre'}
|
||||
|
||||
def test_i_can_manage_ret(self):
|
||||
sheerka, context, foo, bar = self.init_concepts("foo", Concept("bar", ret="foo"))
|
||||
@@ -897,14 +899,20 @@ class TestSheerkaEvaluateConcept(TestUsingMemoryBasedSheerka):
|
||||
res = sheerka.evaluate_concept(context, bar, eval_body=False)
|
||||
assert res.id == bar.id
|
||||
|
||||
def test_i_can_eval_concept_with_rules(self):
|
||||
sheerka, context, foo = self.init_concepts(Concept("foo a", body="a.name").def_var("a", "r:|1:"))
|
||||
|
||||
res = sheerka.evaluate_concept(context, foo, eval_body=True)
|
||||
assert res.body == "Print return values"
|
||||
|
||||
# I cannot implement value cache for now
|
||||
# def test_values_when_no_variables_are_computed_only_once(self):
|
||||
# sheerka, context, foo = self.init_concepts(Concept("foo", body="10"))
|
||||
#
|
||||
# evaluated = sheerka.evaluate_concept(context, sheerka.new("foo"), eval_body=True)
|
||||
# assert evaluated.body == 10
|
||||
# assert len(evaluated.compiled) > 0
|
||||
# assert len(evaluated.get_compiled()) > 0
|
||||
#
|
||||
# evaluated_2 = sheerka.evaluate_concept(context, sheerka.new("foo"), eval_body=True)
|
||||
# assert evaluated_2.body == 10
|
||||
# assert len(evaluated_2.compiled) == 0
|
||||
# assert len(evaluated_2.get_compiled()) == 0
|
||||
|
||||
@@ -0,0 +1,74 @@
|
||||
import operator
|
||||
|
||||
from core.concept import Concept
|
||||
from core.rule import Rule
|
||||
from core.sheerka.services.SheerkaEvaluateRules import SheerkaEvaluateRules, LOW_PRIORITY_RULES, DISABLED_RULES
|
||||
|
||||
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_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
|
||||
Rule(predicate="a == 4", action="", priority=0), # r4
|
||||
Rule(predicate="a == 5", action="", priority=0), # r5
|
||||
Rule(predicate="a == 1", action="", priority=1), # r6
|
||||
Rule(predicate="a == 7", action="", priority=1, is_enabled=False), # r7
|
||||
Rule(predicate="a == 8", action="", priority=1), # r8
|
||||
Rule(predicate="a == 9", action="", priority=2), # r9
|
||||
)
|
||||
service = sheerka.services[SheerkaEvaluateRules.NAME]
|
||||
rules = sorted([r1, r2, r3, r4, r5, r6, r7, r8, r9], key=operator.attrgetter('priority'), reverse=True)
|
||||
|
||||
res = service.evaluate_rules(context, rules, {"a": 1}, set())
|
||||
|
||||
assert res == {
|
||||
True: [r1, r6],
|
||||
False: [r9, r2, r8],
|
||||
LOW_PRIORITY_RULES: [r3, r4, r5],
|
||||
DISABLED_RULES: [r7]
|
||||
}
|
||||
|
||||
def test_i_can_evaluate_concept_rules(self):
|
||||
sheerka, context, r1, r2, r3, r4, r5, r6, r7, r8, r9 = self.init_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
|
||||
Rule(predicate="a equals 4", action="", priority=0), # r4
|
||||
Rule(predicate="a equals 5", action="", priority=0), # r5
|
||||
Rule(predicate="a equals 1", action="", priority=1), # r6
|
||||
Rule(predicate="a equals 7", action="", priority=1, is_enabled=False), # r7
|
||||
Rule(predicate="a equals 8", action="", priority=1), # r8
|
||||
Rule(predicate="a equals 9", action="", priority=2), # r9
|
||||
concepts=[Concept("x equals y", body="x == y").def_var("x").def_var("y")],
|
||||
)
|
||||
|
||||
service = sheerka.services[SheerkaEvaluateRules.NAME]
|
||||
rules = sorted([r1, r2, r3, r4, r5, r6, r7, r8, r9], key=operator.attrgetter('priority'), reverse=True)
|
||||
|
||||
res = service.evaluate_rules(context, rules, {"a": 1}, set())
|
||||
|
||||
assert res == {
|
||||
True: [r1, r6],
|
||||
False: [r9, r2, r8],
|
||||
LOW_PRIORITY_RULES: [r3, r4, r5],
|
||||
DISABLED_RULES: [r7]
|
||||
}
|
||||
|
||||
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
|
||||
Rule(predicate="a == 1", action="", priority=1), # r2
|
||||
)
|
||||
service = sheerka.services[SheerkaEvaluateRules.NAME]
|
||||
rules = sorted([r1, r2], key=operator.attrgetter('priority'), reverse=True)
|
||||
|
||||
res = service.evaluate_rules(context, rules, {"a": 1}, {r1.id})
|
||||
|
||||
assert res == {
|
||||
True: [r2],
|
||||
DISABLED_RULES: [r1]
|
||||
}
|
||||
@@ -0,0 +1,66 @@
|
||||
from core.sheerka.services.SheerkaEventManager import SheerkaEventManager
|
||||
|
||||
from tests.TestUsingMemoryBasedSheerka import TestUsingMemoryBasedSheerka
|
||||
|
||||
|
||||
def example_of_function(context):
|
||||
print(f"example_of_class_method. event={context.event.get_digest()}")
|
||||
|
||||
|
||||
def example_of_function_with_data(context, data):
|
||||
print(f"example_of_class_method. event={context.event.get_digest()}, {data=}")
|
||||
|
||||
|
||||
class TestSheerkaEventManager(TestUsingMemoryBasedSheerka):
|
||||
|
||||
def example_of_class_method(self, context):
|
||||
print(f"example_of_class_method. event={context.event.get_digest()}")
|
||||
|
||||
@staticmethod
|
||||
def example_of_static_method(context):
|
||||
print(f"example_of_static_method. event={context.event.get_digest()}")
|
||||
|
||||
def example_of_class_method_with_data(self, context, data):
|
||||
print(f"example_of_class_method. event={context.event.get_digest()}, {data=}")
|
||||
|
||||
@staticmethod
|
||||
def example_of_static_method_with_data(context, data):
|
||||
print(f"example_of_static_method. event={context.event.get_digest()}, {data=}")
|
||||
|
||||
def test_i_can_subscribe_and_publish(self, capsys):
|
||||
sheerka, context = self.init_concepts()
|
||||
topic = "my topic"
|
||||
|
||||
sheerka.subscribe(topic, self.example_of_class_method)
|
||||
sheerka.subscribe(topic, self.example_of_static_method)
|
||||
sheerka.subscribe(topic, example_of_function)
|
||||
|
||||
sheerka.publish(context, topic)
|
||||
|
||||
captured = capsys.readouterr()
|
||||
assert captured.out == """example_of_class_method. event=xxx
|
||||
example_of_static_method. event=xxx
|
||||
example_of_class_method. event=xxx
|
||||
"""
|
||||
|
||||
service = sheerka.services[SheerkaEventManager.NAME]
|
||||
service.reset_topic(topic)
|
||||
|
||||
def test_i_can_subscribe_and_publish_with_data(self, capsys):
|
||||
sheerka, context = self.init_concepts()
|
||||
topic = "my topic"
|
||||
|
||||
sheerka.subscribe(topic, self.example_of_class_method_with_data)
|
||||
sheerka.subscribe(topic, self.example_of_static_method_with_data)
|
||||
sheerka.subscribe(topic, example_of_function_with_data)
|
||||
|
||||
sheerka.publish(context, topic, "42")
|
||||
|
||||
captured = capsys.readouterr()
|
||||
assert captured.out == """example_of_class_method. event=xxx, data='42'
|
||||
example_of_static_method. event=xxx, data='42'
|
||||
example_of_class_method. event=xxx, data='42'
|
||||
"""
|
||||
|
||||
service = sheerka.services[SheerkaEventManager.NAME]
|
||||
service.reset_topic(topic)
|
||||
@@ -32,7 +32,8 @@ class TestSheerkaHistoryManager(TestUsingMemoryBasedSheerka):
|
||||
hist("xxx", False),
|
||||
hist("one", True),
|
||||
hist("def concept one as 1", True),
|
||||
hist("Initializing Sheerka.", None)]
|
||||
hist("Initializing Sheerka.", None)
|
||||
]
|
||||
|
||||
h = list(sheerka.history(2))
|
||||
assert h == [
|
||||
|
||||
@@ -15,7 +15,7 @@ class TestSheerkaMemory(TestUsingMemoryBasedSheerka):
|
||||
foo = Concept("foo")
|
||||
sheerka.add_to_short_term_memory(None, "a", foo)
|
||||
|
||||
assert service.short_term_objects.copy() == {":a": foo}
|
||||
assert service.short_term_objects.copy() == {'global': {'a': foo}}
|
||||
assert id(sheerka.get_from_short_term_memory(None, "a")) == id(foo)
|
||||
|
||||
def test_i_can_add_context_short_term_memory(self):
|
||||
@@ -26,23 +26,36 @@ class TestSheerkaMemory(TestUsingMemoryBasedSheerka):
|
||||
sheerka.add_to_short_term_memory(context, "a", foo)
|
||||
|
||||
context_id = ExecutionContext.ids[context.event.get_digest()]
|
||||
assert service.short_term_objects.copy() == {f"{context_id}:a": foo}
|
||||
assert service.short_term_objects.copy() == {context_id: {'a': foo}}
|
||||
assert id(sheerka.get_from_short_term_memory(context, "a")) == id(foo)
|
||||
assert sheerka.get_from_short_term_memory(None, "a") is None
|
||||
|
||||
def test_i_can_add_many(self):
|
||||
sheerka, context = self.init_concepts()
|
||||
bag = {"a": "foo", "b": "bar", }
|
||||
context_id = ExecutionContext.ids[context.event.get_digest()]
|
||||
service = sheerka.services[SheerkaMemory.NAME]
|
||||
|
||||
sheerka.add_many_to_short_term_memory(context, bag)
|
||||
assert service.short_term_objects.copy() == {context_id: bag}
|
||||
|
||||
def test_i_can_get_obj_from_parents(self):
|
||||
sheerka, context = self.init_concepts()
|
||||
service = sheerka.services[SheerkaMemory.NAME]
|
||||
foo = Concept("foo")
|
||||
|
||||
sheerka.add_to_short_term_memory(None, "a", foo)
|
||||
sheerka.add_to_short_term_memory(context, "b", foo)
|
||||
|
||||
with context.push(BuiltinConcepts.TESTING, None) as sub_context:
|
||||
assert service.short_term_objects.copy() == {":a": foo}
|
||||
assert id(sheerka.get_from_short_term_memory(sub_context, "a")) == id(foo)
|
||||
assert id(sheerka.get_from_short_term_memory(context, "a")) == id(foo)
|
||||
assert id(sheerka.get_from_short_term_memory(None, "a")) == id(foo)
|
||||
|
||||
def test_entry_are_removed_on_context_exit(self):
|
||||
assert id(sheerka.get_from_short_term_memory(sub_context, "b")) == id(foo)
|
||||
assert id(sheerka.get_from_short_term_memory(context, "b")) == id(foo)
|
||||
assert sheerka.get_from_short_term_memory(None, "b") is None
|
||||
|
||||
def test_short_term_memory_entries_are_removed_on_context_exit(self):
|
||||
sheerka, context = self.init_concepts()
|
||||
|
||||
with context.push(BuiltinConcepts.TESTING, None) as sub_context:
|
||||
@@ -52,6 +65,17 @@ class TestSheerkaMemory(TestUsingMemoryBasedSheerka):
|
||||
|
||||
assert sheerka.get_from_short_term_memory(sub_context, "a") is None
|
||||
|
||||
def test_short_term_memory_entries_are_removed_on_context_exit_2(self):
|
||||
# this time we test the bulk insert
|
||||
sheerka, context = self.init_concepts()
|
||||
|
||||
with context.push(BuiltinConcepts.TESTING, None) as sub_context:
|
||||
foo = Concept("foo")
|
||||
sheerka.add_many_to_short_term_memory(sub_context, {"a": foo})
|
||||
assert id(sheerka.get_from_short_term_memory(sub_context, "a")) == id(foo)
|
||||
|
||||
assert sheerka.get_from_short_term_memory(sub_context, "a") is None
|
||||
|
||||
def test_i_can_add_and_retrieve_from_memory(self):
|
||||
sheerka, context = self.init_concepts()
|
||||
service = sheerka.services[SheerkaMemory.NAME]
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
from core.builtin_concepts import BuiltinConcepts
|
||||
from core.concept import Concept, ConceptParts
|
||||
from core.concept import Concept, ConceptParts, get_concept_attrs
|
||||
|
||||
from tests.TestUsingFileBasedSheerka import TestUsingFileBasedSheerka
|
||||
from tests.TestUsingMemoryBasedSheerka import TestUsingMemoryBasedSheerka
|
||||
@@ -10,8 +10,10 @@ class TestSheerkaModifyConcept(TestUsingMemoryBasedSheerka):
|
||||
def test_i_can_modify_a_concept(self):
|
||||
sheerka, context, foo, bar = self.init_concepts("foo", "bar", create_new=True, cache_only=False)
|
||||
|
||||
assert get_concept_attrs(foo) == []
|
||||
|
||||
foo_instance = sheerka.new("foo")
|
||||
foo_instance.metadata.body = "metadata value" # modify metadata
|
||||
foo_instance.get_metadata().body = "metadata value" # modify metadata
|
||||
foo_instance.def_var("var_name", "default value") # modify definition of variables
|
||||
foo_instance.add_prop(BuiltinConcepts.ISA, bar) # modify property
|
||||
foo_instance.set_value(ConceptParts.BODY, "body value") # modify value
|
||||
@@ -20,30 +22,31 @@ class TestSheerkaModifyConcept(TestUsingMemoryBasedSheerka):
|
||||
|
||||
assert res.status
|
||||
assert sheerka.isinstance(res.body, BuiltinConcepts.NEW_CONCEPT)
|
||||
assert res.body.body.metadata.body == "metadata value"
|
||||
assert res.body.body.metadata.variables == [("var_name", "default value")]
|
||||
assert res.body.body.get_metadata().body == "metadata value"
|
||||
assert res.body.body.get_metadata().variables == [("var_name", "default value")]
|
||||
assert res.body.body.get_prop(BuiltinConcepts.ISA) == {bar}
|
||||
assert res.body.body.body == "body value"
|
||||
assert res.body.body.get_value("var_name") == "var value"
|
||||
assert get_concept_attrs(foo) == ["var_name"]
|
||||
|
||||
# test that object
|
||||
foo_from_sheerka = sheerka.get_by_key("foo")
|
||||
assert foo_from_sheerka.metadata.body == "metadata value"
|
||||
assert foo_from_sheerka.metadata.variables == [("var_name", "default value")]
|
||||
assert foo_from_sheerka.get_metadata().body == "metadata value"
|
||||
assert foo_from_sheerka.get_metadata().variables == [("var_name", "default value")]
|
||||
assert foo_from_sheerka.get_prop(BuiltinConcepts.ISA) == {bar}
|
||||
assert foo_from_sheerka.body == "body value"
|
||||
assert foo_from_sheerka.get_value("var_name") == "var value"
|
||||
|
||||
# other caches are also updated
|
||||
assert sheerka.get_by_id(foo.id).metadata.body == "metadata value"
|
||||
assert sheerka.get_by_name(foo.name).metadata.body == "metadata value"
|
||||
assert sheerka.get_by_hash(foo_instance.get_definition_hash()).metadata.body == "metadata value"
|
||||
assert sheerka.get_by_id(foo.id).get_metadata().body == "metadata value"
|
||||
assert sheerka.get_by_name(foo.name).get_metadata().body == "metadata value"
|
||||
assert sheerka.get_by_hash(foo_instance.get_definition_hash()).get_metadata().body == "metadata value"
|
||||
|
||||
# sdp can be updated
|
||||
sheerka.cache_manager.commit(context)
|
||||
from_sdp = sheerka.sdp.get(sheerka.CONCEPTS_BY_ID_ENTRY, foo.id)
|
||||
assert from_sdp.metadata.body == "metadata value"
|
||||
assert from_sdp.metadata.variables == [("var_name", "default value")]
|
||||
assert from_sdp.get_metadata().body == "metadata value"
|
||||
assert from_sdp.get_metadata().variables == [("var_name", "default value")]
|
||||
assert from_sdp.get_prop(BuiltinConcepts.ISA) == {bar}
|
||||
assert from_sdp.body == "body value"
|
||||
assert from_sdp.get_value("var_name") == "var value"
|
||||
@@ -81,16 +84,16 @@ class TestSheerkaModifyConcept(TestUsingMemoryBasedSheerka):
|
||||
Concept("foo", body="2"), create_new=True)
|
||||
|
||||
foo2_instance = sheerka.new("foo")[1]
|
||||
foo2_instance.metadata.body = "value"
|
||||
foo2_instance.get_metadata().body = "value"
|
||||
|
||||
res = sheerka.modify_concept(context, foo2_instance)
|
||||
assert res.status
|
||||
assert sheerka.isinstance(res.body, BuiltinConcepts.NEW_CONCEPT)
|
||||
assert res.body.body.metadata.body == "value"
|
||||
assert res.body.body.get_metadata().body == "value"
|
||||
|
||||
foo_from_sheerka = sheerka.new("foo")
|
||||
assert foo_from_sheerka[0].metadata.body == "1"
|
||||
assert foo_from_sheerka[1].metadata.body == "value"
|
||||
assert foo_from_sheerka[0].get_metadata().body == "1"
|
||||
assert foo_from_sheerka[1].get_metadata().body == "value"
|
||||
|
||||
def test_i_can_get_and_set_attribute(self):
|
||||
sheerka, context = self.init_concepts()
|
||||
|
||||
@@ -0,0 +1,355 @@
|
||||
import ast
|
||||
|
||||
import pytest
|
||||
from core.builtin_concepts import BuiltinConcepts
|
||||
from core.concept import Concept
|
||||
from core.global_symbols import RULE_COMPARISON_CONTEXT
|
||||
from core.rule import Rule
|
||||
from core.sheerka.services.SheerkaRuleManager import SheerkaRuleManager, FormatRuleParser, \
|
||||
FormatAstRawText, FormatAstVariable, FormatAstSequence, FormatAstFunction, \
|
||||
FormatRuleSyntaxError, FormatAstList, UnexpectedEof, FormatAstColor, RulePredicate
|
||||
from core.tokenizer import Token, TokenKind
|
||||
from parsers.BaseNodeParser import SourceCodeWithConceptNode, SourceCodeNode
|
||||
from parsers.PythonParser import PythonNode
|
||||
|
||||
from tests.TestUsingFileBasedSheerka import TestUsingFileBasedSheerka
|
||||
from tests.TestUsingMemoryBasedSheerka import TestUsingMemoryBasedSheerka
|
||||
|
||||
seq = FormatAstSequence
|
||||
raw = FormatAstRawText
|
||||
var = FormatAstVariable
|
||||
func = FormatAstFunction
|
||||
lst = FormatAstList
|
||||
|
||||
PYTHON_EVALUATOR_NAME = "Python"
|
||||
CONCEPT_EVALUATOR_NAME = "Concept"
|
||||
|
||||
|
||||
class TestSheerkaRuleManager(TestUsingMemoryBasedSheerka):
|
||||
|
||||
@pytest.mark.parametrize("action_type, cache_entry", [
|
||||
("print", SheerkaRuleManager.FORMAT_RULE_ENTRY),
|
||||
("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)
|
||||
previous_rules_number = sheerka.cache_manager.caches[sheerka.CONCEPTS_KEYS_ENTRY].cache.copy()[
|
||||
SheerkaRuleManager.RULE_IDS]
|
||||
|
||||
rule = Rule(action_type, "name", "True", "Hello world")
|
||||
|
||||
res = sheerka.create_new_rule(context, rule)
|
||||
expected_id = str(previous_rules_number + 1)
|
||||
|
||||
assert res.status
|
||||
assert sheerka.isinstance(res.body, BuiltinConcepts.NEW_RULE)
|
||||
|
||||
created_rule = res.body.body
|
||||
assert created_rule.metadata.id == expected_id
|
||||
assert created_rule.metadata.name == "name"
|
||||
assert created_rule.metadata.predicate == "True"
|
||||
assert created_rule.metadata.action_type == action_type
|
||||
assert created_rule.metadata.action == "Hello world"
|
||||
|
||||
# saved in cache
|
||||
assert len(sheerka.cache_manager.caches[cache_entry].cache) > 0
|
||||
from_cache = sheerka.cache_manager.get(cache_entry, expected_id)
|
||||
assert from_cache.metadata.id == expected_id
|
||||
assert from_cache.metadata.name == "name"
|
||||
assert from_cache.metadata.predicate == "True"
|
||||
assert from_cache.metadata.action_type == action_type
|
||||
assert from_cache.metadata.action == "Hello world"
|
||||
|
||||
sheerka.cache_manager.commit(context)
|
||||
|
||||
# saved in sdp
|
||||
from_sdp = sheerka.sdp.get(cache_entry, expected_id)
|
||||
assert from_sdp.metadata.id == expected_id
|
||||
assert from_sdp.metadata.name == "name"
|
||||
assert from_sdp.metadata.predicate == "True"
|
||||
assert from_sdp.metadata.action_type == action_type
|
||||
assert from_sdp.metadata.action == "Hello world"
|
||||
|
||||
def test_i_can_create_multiple_rules(self):
|
||||
sheerka, context = self.init_concepts(cache_only=False)
|
||||
previous_rules_number = len(sheerka.cache_manager.caches[SheerkaRuleManager.FORMAT_RULE_ENTRY].cache)
|
||||
|
||||
sheerka.create_new_rule(context, Rule("print", "name1", "True", "Hello world"))
|
||||
sheerka.create_new_rule(context, Rule("print", "name2", "value() is __EXPLANATION", "list(value())"))
|
||||
|
||||
assert len(
|
||||
sheerka.cache_manager.caches[SheerkaRuleManager.FORMAT_RULE_ENTRY].cache) == 2 + previous_rules_number
|
||||
|
||||
@pytest.mark.parametrize("text, expected", [
|
||||
("", FormatAstRawText("")),
|
||||
(" ", FormatAstRawText(" ")),
|
||||
(" raw text ", FormatAstRawText(" raw text ")),
|
||||
("{variable}", FormatAstVariable("variable")),
|
||||
("{ variable }", FormatAstVariable("variable")),
|
||||
(" xy {v} z", seq([raw(" xy "), var("v"), raw(" z")])),
|
||||
(r"\{variable}", FormatAstRawText("{variable}")),
|
||||
(r"\\{variable}", seq([raw("\\"), var("variable")])),
|
||||
(r"\\\{variable}", FormatAstRawText(r"\{variable}")),
|
||||
(r"{var1}{var2}", seq([var("var1"), var("var2")])),
|
||||
("func()", FormatAstFunction("func", [], {})),
|
||||
("func(a, 'string value', c)", FormatAstFunction("func", ["a", "'string value'", "c"], {})),
|
||||
("func(a=10, b='string value')", FormatAstFunction("func", [], {"a": "10", "b": "'string value'"})),
|
||||
("func('string value'='another string value')", func("func", [], {"'string value'": "'another string value'"})),
|
||||
("red(' xy {v}')", FormatAstColor("red", seq([raw(" xy "), var("v")]))),
|
||||
('blue(" xy {v}")', FormatAstColor("blue", seq([raw(" xy "), var("v")]))),
|
||||
('green( xy )', FormatAstColor("green", var("xy"))),
|
||||
('green()', FormatAstColor("green", raw(""))),
|
||||
('green("")', FormatAstColor("green", raw(""))),
|
||||
("list(var_name, 2, 'children')", FormatAstList("var_name", recurse_on="children", recursion_depth=2)),
|
||||
("list(var_name, recursion_depth=2, recurse_on='children')", FormatAstList("var_name",
|
||||
recurse_on="children",
|
||||
recursion_depth=2)),
|
||||
("list(var_name, recursion_depth=2, 'children')", FormatAstList("var_name", recursion_depth=2)),
|
||||
("list(var_name, 'children', recursion_depth=2)", FormatAstList("var_name", recursion_depth=2)),
|
||||
("list(var_name)", FormatAstList("var_name")),
|
||||
("{obj.prop1.prop2[0].prop3['value']}", FormatAstVariable("obj.prop1.prop2[0].prop3['value']")),
|
||||
("[{id}]", seq([raw("["), var("id"), raw("]")])),
|
||||
("{variable:format}", FormatAstVariable("variable", "format")),
|
||||
("{variable:3}", FormatAstVariable("variable", "3")),
|
||||
(r"\not_a_function(a={var})", seq([raw("not_a_function(a="), var("var"), raw(")")])),
|
||||
])
|
||||
def test_i_can_parse_format_rule(self, text, expected):
|
||||
assert FormatRuleParser(text).parse() == expected
|
||||
|
||||
@pytest.mark.parametrize("text, expected_error", [
|
||||
("{", UnexpectedEof("while parsing variable", Token(TokenKind.LBRACE, "{", 0, 1, 1))),
|
||||
("{var_name", UnexpectedEof("while parsing variable", Token(TokenKind.LBRACE, "{", 0, 1, 1))),
|
||||
("{}", FormatRuleSyntaxError("variable name not found", None)),
|
||||
("func(", UnexpectedEof("while parsing function", Token(TokenKind.IDENTIFIER, "func", 0, 1, 1))),
|
||||
("func(a,b,c", UnexpectedEof("while parsing function", Token(TokenKind.IDENTIFIER, "func", 0, 1, 1))),
|
||||
("func(a,,c", FormatRuleSyntaxError("no parameter found", Token(TokenKind.COMMA, ",", 7, 1, 8))),
|
||||
("func(a,,c)", FormatRuleSyntaxError("no parameter found", Token(TokenKind.COMMA, ",", 7, 1, 8))),
|
||||
("red(a,b)", FormatRuleSyntaxError("only one parameter supported", Token(TokenKind.IDENTIFIER, "b", 6, 1, 7))),
|
||||
("red(a=b)", FormatRuleSyntaxError("keyword arguments are not supported", None)),
|
||||
("red(xy {v})", FormatRuleSyntaxError("Invalid identifier", None)),
|
||||
("list()", FormatRuleSyntaxError("variable name not found", None)),
|
||||
("list(recursion_depth=2)", FormatRuleSyntaxError("variable name not found", None)),
|
||||
("list(a,b,c,d)", FormatRuleSyntaxError("too many positional arguments",
|
||||
Token(TokenKind.IDENTIFIER, "d", 11, 1, 12))),
|
||||
("list(a, recursion_depth=hello)", FormatRuleSyntaxError("'hello' is not numeric", None)),
|
||||
("list(a, recursion_depth='hello')", FormatRuleSyntaxError("'recursion_depth' must be an integer", None)),
|
||||
])
|
||||
def test_i_cannot_parse_invalid_format(self, text, expected_error):
|
||||
parser = FormatRuleParser(text)
|
||||
parser.parse()
|
||||
|
||||
assert parser.error_sink == expected_error
|
||||
|
||||
@pytest.mark.parametrize("text", [
|
||||
"a == 5",
|
||||
"foo == 5",
|
||||
"func() == 5",
|
||||
])
|
||||
def test_i_can_compile_predicate_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_)
|
||||
|
||||
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) == expected_python_node
|
||||
assert res[0].concept is None
|
||||
|
||||
@pytest.mark.parametrize("text, expected_type", [
|
||||
("isinstance(a, int)", SourceCodeWithConceptNode),
|
||||
("func()", SourceCodeNode),
|
||||
])
|
||||
def test_i_can_compile_predicates_that_resolve_to_python(self, text, expected_type):
|
||||
sheerka, context, *concepts = self.init_concepts()
|
||||
service = sheerka.services[SheerkaRuleManager.NAME]
|
||||
ast_ = ast.parse(text, "<source>", 'eval')
|
||||
expected_python_node = 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 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_concepts(Concept("foo bar"), create_new=True)
|
||||
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 res[0].concept is None
|
||||
|
||||
@pytest.mark.parametrize("text, expected_variables", [
|
||||
("cat is an animal", ["cat", "animal"]),
|
||||
("a is an animal", ["a", "animal"]),
|
||||
("cat is an b", ["cat", "b"]),
|
||||
])
|
||||
def test_i_can_compile_predicate_when_exact_concept(self, text, expected_variables):
|
||||
sheerka, context, *concepts = self.init_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
|
||||
)
|
||||
service = sheerka.services[SheerkaRuleManager.NAME]
|
||||
|
||||
expected = concepts[0]
|
||||
expected.get_metadata().variables = [('x', expected_variables[0]), ('y', expected_variables[1])]
|
||||
|
||||
res = service.compile_when(context, "test", text)
|
||||
|
||||
assert len(res) == 1
|
||||
assert isinstance(res[0], RulePredicate)
|
||||
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, expected_variables", [
|
||||
("a cat is an animal", ["cat", "animal"]),
|
||||
("a cat is an b", ["a", "animal"]),
|
||||
])
|
||||
def test_i_can_compile_predicate_when_sya_node_parser(self, text, expected_variables):
|
||||
sheerka, context, *concepts = self.init_concepts(
|
||||
Concept("x is an y", pre="is_question()", body="isinstance(x, y)").def_var("x").def_var("y"),
|
||||
Concept("a cat"),
|
||||
Concept("animal"),
|
||||
create_new=True
|
||||
)
|
||||
service = sheerka.services[SheerkaRuleManager.NAME]
|
||||
expected = concepts[0]
|
||||
|
||||
res = service.compile_when(context, "test", text)
|
||||
|
||||
assert len(res) == 1
|
||||
assert isinstance(res[0], RulePredicate)
|
||||
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_bnf_node_parser(self):
|
||||
sheerka, context, *concepts = self.init_concepts(
|
||||
Concept("animal"),
|
||||
Concept("x is an y", pre="is_question()", definition="('cat'|'bird')=x 'is an' animal").def_var("x"),
|
||||
create_new=True
|
||||
)
|
||||
service = sheerka.services[SheerkaRuleManager.NAME]
|
||||
expected = concepts[1]
|
||||
|
||||
res = service.compile_when(context, "test", "cat is an animal")
|
||||
|
||||
assert len(res) == 1
|
||||
assert isinstance(res[0], RulePredicate)
|
||||
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_multiple_choices(self):
|
||||
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"),
|
||||
create_new=True
|
||||
)
|
||||
service = sheerka.services[SheerkaRuleManager.NAME]
|
||||
|
||||
res = service.compile_when(context, "test", "a is a b")
|
||||
|
||||
assert len(res) == 2
|
||||
assert isinstance(res[0], RulePredicate)
|
||||
assert res[0].evaluator == CONCEPT_EVALUATOR_NAME
|
||||
assert sheerka.isinstance(res[0].predicate, BuiltinConcepts.RETURN_VALUE)
|
||||
assert sheerka.objvalue(res[0].predicate)[0].concept == concepts[0]
|
||||
assert res[0].concept == concepts[0]
|
||||
|
||||
assert isinstance(res[1], RulePredicate)
|
||||
assert res[1].evaluator == CONCEPT_EVALUATOR_NAME
|
||||
assert sheerka.isinstance(res[1].predicate, BuiltinConcepts.RETURN_VALUE)
|
||||
assert sheerka.objvalue(res[1].predicate)[0].concept == concepts[1]
|
||||
assert res[1].concept == concepts[1]
|
||||
|
||||
# @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
|
||||
|
||||
|
||||
class TestSheerkaRuleManagerUsingFileBasedSheerka(TestUsingFileBasedSheerka):
|
||||
def test_rules_are_initialized_at_startup(self):
|
||||
sheerka, context, *rules = self.init_format_rules(
|
||||
Rule("print", "name1", "True", "Hello world"),
|
||||
Rule("print", "name2", "value() is __EXPLANATION", "list(value())")
|
||||
)
|
||||
sheerka.set_is_greater_than(context, BuiltinConcepts.PRECEDENCE,
|
||||
rules[0],
|
||||
rules[1],
|
||||
RULE_COMPARISON_CONTEXT)
|
||||
|
||||
sheerka.cache_manager.commit(context)
|
||||
assert len(sheerka.cache_manager.copy(SheerkaRuleManager.FORMAT_RULE_ENTRY)) == len(rules)
|
||||
|
||||
sheerka = self.get_sheerka() # new instance
|
||||
assert len(sheerka.cache_manager.copy(SheerkaRuleManager.FORMAT_RULE_ENTRY)) == len(rules)
|
||||
|
||||
# manually update the rules (I need their new priorities)
|
||||
service = sheerka.services[SheerkaRuleManager.NAME]
|
||||
rules = [service.format_rule_cache.get(rule_id) for rule_id in service.format_rule_cache]
|
||||
|
||||
# check if the rules are correctly initialized
|
||||
rules_as_map = {rule.id: rule for rule in rules}
|
||||
for rule_id in service.format_rule_cache:
|
||||
actual = service.format_rule_cache.get(rule_id)
|
||||
expected = rules_as_map[rule_id]
|
||||
assert actual.metadata.is_compiled == expected.metadata.is_compiled
|
||||
assert actual.metadata.is_enabled == expected.metadata.is_enabled
|
||||
assert actual.compiled_action == expected.compiled_action
|
||||
assert actual.compiled_predicate == expected.compiled_predicate
|
||||
assert actual.priority is not None
|
||||
assert actual.priority == expected.priority
|
||||
@@ -268,12 +268,12 @@ class TestSheerkaSetsManager(TestUsingMemoryBasedSheerka):
|
||||
create_new=True
|
||||
)
|
||||
|
||||
assert twenties.bnf.elements[1].recurse_id is None
|
||||
assert twenties.get_bnf().elements[1].recurse_id is None
|
||||
|
||||
# update number
|
||||
sheerka.set_isa(context, sheerka.new("one"), number)
|
||||
|
||||
assert twenties.bnf.elements[1].recurse_id == "1003#1002(number)"
|
||||
assert twenties.get_bnf().elements[1].recurse_id == "1003#1002(number)"
|
||||
|
||||
def test_concepts_in_group_cache_is_updated(self):
|
||||
sheerka, context, one, two, number = self.init_concepts("one", "two", "number")
|
||||
@@ -306,7 +306,8 @@ class TestSheerkaSetsManagerUsingFileBasedSheerka(TestUsingFileBasedSheerka):
|
||||
assert sheerka.add_concept_to_set(context, foo, group).status
|
||||
sheerka.cache_manager.commit(context)
|
||||
|
||||
sheerka = self.get_sheerka() # another session
|
||||
sheerka = self.get_sheerka(reset_attrs=False) # another session
|
||||
context = self.get_context(sheerka)
|
||||
assert sheerka.add_concept_to_set(context, bar, group).status
|
||||
|
||||
# I can get the elements
|
||||
@@ -319,7 +320,8 @@ class TestSheerkaSetsManagerUsingFileBasedSheerka(TestUsingFileBasedSheerka):
|
||||
}
|
||||
|
||||
# I can also add a group another elements
|
||||
sheerka = self.get_sheerka()
|
||||
sheerka = self.get_sheerka(reset_attrs=False)
|
||||
context = self.get_context(sheerka)
|
||||
foo3 = Concept("foo3")
|
||||
foo4 = Concept("foo4")
|
||||
for c in [foo3, foo4]:
|
||||
@@ -348,19 +350,19 @@ class TestSheerkaSetsManagerUsingFileBasedSheerka(TestUsingFileBasedSheerka):
|
||||
|
||||
# nothing was previously in ISA
|
||||
foo = sheerka.new(foo.key)
|
||||
assert BuiltinConcepts.ISA not in foo.metadata.props
|
||||
assert BuiltinConcepts.ISA not in foo.get_metadata().props
|
||||
res = sheerka.set_isa(context, foo, group)
|
||||
assert res.status
|
||||
sheerka.cache_manager.commit(context)
|
||||
|
||||
sheerka = self.get_sheerka()
|
||||
sheerka = self.get_sheerka(reset_attrs=False)
|
||||
assert foo.get_prop(BuiltinConcepts.ISA) == {group}
|
||||
assert sheerka.isa(foo, group)
|
||||
assert sheerka.isinset(foo, group)
|
||||
assert sheerka.isaset(context, group)
|
||||
|
||||
# I can do the same for bar
|
||||
sheerka = self.get_sheerka()
|
||||
sheerka = self.get_sheerka(reset_attrs=False)
|
||||
res = sheerka.set_isa(context, bar, group)
|
||||
assert res.status
|
||||
assert bar.get_prop(BuiltinConcepts.ISA) == {group}
|
||||
@@ -371,7 +373,7 @@ class TestSheerkaSetsManagerUsingFileBasedSheerka(TestUsingFileBasedSheerka):
|
||||
sheerka.cache_manager.commit(context)
|
||||
|
||||
# they are both in the same group
|
||||
sheerka = self.get_sheerka()
|
||||
sheerka = self.get_sheerka(reset_attrs=False)
|
||||
all_entries = sheerka.sdp.get(SheerkaSetsManager.CONCEPTS_GROUPS_ENTRY)
|
||||
assert all_entries == {
|
||||
group.id: {foo.id, bar.id}
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
from core.concept import Concept, ConceptParts
|
||||
from core.sheerka.services.SheerkaVariableManager import SheerkaVariableManager
|
||||
|
||||
from tests.TestUsingFileBasedSheerka import TestUsingFileBasedSheerka
|
||||
from tests.TestUsingMemoryBasedSheerka import TestUsingMemoryBasedSheerka
|
||||
|
||||
|
||||
@@ -9,8 +10,8 @@ class TestSheerkaVariable(TestUsingMemoryBasedSheerka):
|
||||
sheerka = self.get_sheerka(cache_only=False)
|
||||
context = self.get_context(sheerka)
|
||||
|
||||
sheerka.record(context, "TestSheerkaVariable", "my_variable", 1)
|
||||
res = sheerka.load("TestSheerkaVariable", "my_variable")
|
||||
sheerka.record_var(context, "TestSheerkaVariable", "my_variable", 1)
|
||||
res = sheerka.load_var("TestSheerkaVariable", "my_variable")
|
||||
assert res == 1
|
||||
|
||||
# I can persist in db
|
||||
@@ -30,8 +31,8 @@ class TestSheerkaVariable(TestUsingMemoryBasedSheerka):
|
||||
|
||||
concept = Concept("foo").set_value("a", "alpha").set_value(ConceptParts.BODY, 3.14)
|
||||
|
||||
sheerka.record(context, "TestSheerkaVariable", "my_variable", concept)
|
||||
res = sheerka.load("TestSheerkaVariable", "my_variable")
|
||||
sheerka.record_var(context, "TestSheerkaVariable", "my_variable", concept)
|
||||
res = sheerka.load_var("TestSheerkaVariable", "my_variable")
|
||||
|
||||
assert res == concept
|
||||
assert res.body == concept.body
|
||||
@@ -43,19 +44,19 @@ class TestSheerkaVariable(TestUsingMemoryBasedSheerka):
|
||||
|
||||
concept = Concept("foo")
|
||||
|
||||
sheerka.record(context, "TestSheerkaVariable", "my_variable", concept)
|
||||
assert sheerka.load("TestSheerkaVariable", "my_variable") is not None
|
||||
sheerka.record_var(context, "TestSheerkaVariable", "my_variable", concept)
|
||||
assert sheerka.load_var("TestSheerkaVariable", "my_variable") is not None
|
||||
|
||||
sheerka.delete(context, "TestSheerkaVariable", "my_variable")
|
||||
assert sheerka.load("TestSheerkaVariable", "my_variable") is None
|
||||
sheerka.delete_var(context, "TestSheerkaVariable", "my_variable")
|
||||
assert sheerka.load_var("TestSheerkaVariable", "my_variable") is None
|
||||
|
||||
def test_i_can_set_and_get_a_value(self):
|
||||
sheerka = self.get_sheerka(cache_only=False)
|
||||
context = self.get_context(sheerka)
|
||||
context.event.user_id = "Test_user"
|
||||
|
||||
sheerka.set(context, "my_variable", "my value")
|
||||
res = sheerka.get(context, "my_variable")
|
||||
sheerka.set_var(context, "my_variable", "my value")
|
||||
res = sheerka.get_var(context, "my_variable")
|
||||
assert res == "my value"
|
||||
|
||||
# I can persist in db
|
||||
@@ -69,13 +70,33 @@ class TestSheerkaVariable(TestUsingMemoryBasedSheerka):
|
||||
assert loaded.who == "Test_user"
|
||||
assert loaded.parents is None
|
||||
|
||||
|
||||
class TestSheerkaVariableUsingFileBasedSdp(TestUsingFileBasedSheerka):
|
||||
|
||||
def test_i_can_bound_variables_to_sheerka(self):
|
||||
sheerka, context = self.init_concepts()
|
||||
|
||||
old_value = sheerka.enable_process_return_values
|
||||
new_value = not old_value
|
||||
sheerka.record_var(context, "TestSheerkaVariable", "sheerka.enable_process_return_values", new_value)
|
||||
sheerka.cache_manager.commit(context)
|
||||
|
||||
assert sheerka.enable_process_return_values == new_value
|
||||
|
||||
# the modification is persisted upon new Sheerka creation
|
||||
sheerka = self.get_sheerka()
|
||||
assert sheerka.enable_process_return_values == new_value
|
||||
|
||||
# reset old value
|
||||
sheerka.enable_process_return_values = old_value
|
||||
|
||||
# def test_i_can_get_the_parent_when_modified(self):
|
||||
# sheerka = self.get_sheerka()
|
||||
# context = self.get_context(sheerka)
|
||||
#
|
||||
# sheerka.record(context, "TestSheerkaVariable", "my_variable", 1)
|
||||
# sheerka.record(context, "TestSheerkaVariable", "my_variable", 2)
|
||||
# res = sheerka.load("TestSheerkaVariable", "my_variable")
|
||||
# sheerka.record_var(context, "TestSheerkaVariable", "my_variable", 1)
|
||||
# sheerka.record_var(context, "TestSheerkaVariable", "my_variable", 2)
|
||||
# res = sheerka.load_var("TestSheerkaVariable", "my_variable")
|
||||
# assert res == 2
|
||||
#
|
||||
# loaded = sheerka.sdp.get(SheerkaVariableManager.VARIABLES_ENTRY, "TestSheerkaVariable.my_variable")
|
||||
@@ -96,8 +117,8 @@ class TestSheerkaVariable(TestUsingMemoryBasedSheerka):
|
||||
# sheerka = self.get_sheerka(singleton=True)
|
||||
# context = self.get_context(sheerka)
|
||||
#
|
||||
# sheerka.record(context, "TestSheerkaVariable", "my_variable", 1)
|
||||
# sheerka.record(context, "TestSheerkaVariable", "my_variable", 1)
|
||||
# sheerka.record_var(context, "TestSheerkaVariable", "my_variable", 1)
|
||||
# sheerka.record_var(context, "TestSheerkaVariable", "my_variable", 1)
|
||||
#
|
||||
# loaded = sheerka.sdp.get(SheerkaVariableManager.VARIABLES_ENTRY, "TestSheerkaVariable.my_variable")
|
||||
# assert loaded.event_id == context.event.get_digest()
|
||||
|
||||
@@ -1,174 +0,0 @@
|
||||
import ast
|
||||
|
||||
import core.ast.nodes
|
||||
import pytest
|
||||
from core.ast.nodes import NodeParent, GenericNodeConcept
|
||||
from core.ast.visitors import ConceptNodeVisitor, UnreferencedNamesVisitor
|
||||
from core.builtin_concepts import BuiltinConcepts
|
||||
from core.sheerka.Sheerka import Sheerka
|
||||
|
||||
|
||||
def get_sheerka():
|
||||
sheerka = Sheerka(cache_only=True)
|
||||
sheerka.initialize("mem://")
|
||||
|
||||
return sheerka
|
||||
|
||||
|
||||
class TestNameVisitor(ConceptNodeVisitor):
|
||||
"""
|
||||
Test class for a basic Visitor test
|
||||
"""
|
||||
|
||||
def __init__(self):
|
||||
self.names = []
|
||||
|
||||
def visit_Name(self, node):
|
||||
self.names.append(node)
|
||||
|
||||
|
||||
def test_i_can_transform_simple_ast_using_generic_node():
|
||||
source = """
|
||||
def my_function(a,b):
|
||||
for i in range(b):
|
||||
a = a+b
|
||||
return a
|
||||
"""
|
||||
tree = ast.parse(source)
|
||||
tree_as_concept = core.ast.nodes.python_to_concept(tree)
|
||||
sheerka = get_sheerka()
|
||||
|
||||
assert tree_as_concept.node_type == "Module"
|
||||
assert sheerka.isinstance(tree_as_concept.get_value("body"), BuiltinConcepts.LIST)
|
||||
|
||||
def_func = tree_as_concept.get_value("body").body[0]
|
||||
assert sheerka.isinstance(def_func, BuiltinConcepts.GENERIC_NODE)
|
||||
assert def_func.node_type == "FunctionDef"
|
||||
assert def_func.parent == NodeParent(tree_as_concept, "body")
|
||||
assert def_func.get_value("name") == "my_function"
|
||||
|
||||
def_func_args = def_func.get_value("args")
|
||||
assert sheerka.isinstance(def_func_args, BuiltinConcepts.GENERIC_NODE)
|
||||
assert def_func_args.node_type == "arguments"
|
||||
|
||||
def_func_args_real_args = def_func_args.get_value("args")
|
||||
assert sheerka.isinstance(def_func_args_real_args, BuiltinConcepts.LIST)
|
||||
assert len(def_func_args_real_args.body) == 2
|
||||
|
||||
assert sheerka.isinstance(def_func_args_real_args.body[0], BuiltinConcepts.GENERIC_NODE)
|
||||
assert def_func_args_real_args.body[0].node_type == "arg"
|
||||
assert def_func_args_real_args.body[0].parent == NodeParent(def_func_args, "args")
|
||||
assert def_func_args_real_args.body[0].get_value("arg") == "a"
|
||||
assert sheerka.isinstance(def_func_args_real_args.body[1], BuiltinConcepts.GENERIC_NODE)
|
||||
assert def_func_args_real_args.body[1].node_type == "arg"
|
||||
assert def_func_args_real_args.body[1].parent == NodeParent(def_func_args, "args")
|
||||
assert def_func_args_real_args.body[1].get_value("arg") == "b"
|
||||
|
||||
def_fun_body = def_func.get_value("body")
|
||||
assert sheerka.isinstance(def_fun_body, BuiltinConcepts.LIST)
|
||||
assert len(def_fun_body.body) == 2
|
||||
|
||||
def_fun_body_for = def_fun_body.body[0]
|
||||
assert sheerka.isinstance(def_fun_body_for, BuiltinConcepts.GENERIC_NODE)
|
||||
assert def_fun_body_for.node_type == "For"
|
||||
assert def_fun_body_for.parent == NodeParent(def_func, "body")
|
||||
|
||||
def_fun_body_return = def_fun_body.body[1]
|
||||
assert sheerka.isinstance(def_fun_body_return, BuiltinConcepts.GENERIC_NODE)
|
||||
assert def_fun_body_return.node_type == "Return"
|
||||
assert def_fun_body_return.parent == NodeParent(def_func, "body")
|
||||
|
||||
|
||||
def test_i_can_visit_concept_node():
|
||||
source = """
|
||||
def my_function(a,b):
|
||||
for i in range(b):
|
||||
a = a+b
|
||||
return a
|
||||
"""
|
||||
|
||||
node = ast.parse(source)
|
||||
concept_node = core.ast.nodes.python_to_concept(node)
|
||||
|
||||
visitor = TestNameVisitor()
|
||||
visitor.visit(concept_node)
|
||||
|
||||
sheerka = get_sheerka()
|
||||
assert sheerka.objvalue(visitor.names[0]) == "i"
|
||||
assert sheerka.objvalue(visitor.names[1]) == "range"
|
||||
assert sheerka.objvalue(visitor.names[2]) == "b"
|
||||
assert sheerka.objvalue(visitor.names[3]) == "a"
|
||||
assert sheerka.objvalue(visitor.names[4]) == "a"
|
||||
assert sheerka.objvalue(visitor.names[5]) == "b"
|
||||
assert sheerka.objvalue(visitor.names[6]) == "a"
|
||||
|
||||
|
||||
def test_i_can_get_unreferenced_variables():
|
||||
source = """
|
||||
def my_function(a,b):
|
||||
for i in range(b):
|
||||
a = a+b
|
||||
return a
|
||||
|
||||
my_function(x,y)
|
||||
"""
|
||||
|
||||
sheerka = get_sheerka()
|
||||
|
||||
node = ast.parse(source)
|
||||
concept_node = core.ast.nodes.python_to_concept(node)
|
||||
|
||||
visitor = UnreferencedNamesVisitor(sheerka)
|
||||
visitor.visit(concept_node)
|
||||
values = visitor.names
|
||||
|
||||
assert len(visitor.names) == 2
|
||||
assert "x" in values
|
||||
assert "y" in values
|
||||
|
||||
|
||||
@pytest.mark.parametrize("source, expected", [
|
||||
("a,b", ["a", "b"]),
|
||||
("isinstance(a, int)", ["a", "int"])
|
||||
|
||||
])
|
||||
def test_i_can_get_unreferenced_variables_from_simple_expressions(source, expected):
|
||||
sheerka = get_sheerka()
|
||||
|
||||
node = ast.parse(source)
|
||||
concept_node = core.ast.nodes.python_to_concept(node)
|
||||
|
||||
visitor = UnreferencedNamesVisitor(sheerka)
|
||||
visitor.visit(concept_node)
|
||||
|
||||
assert sorted(list(visitor.names)) == expected
|
||||
|
||||
|
||||
def test_i_can_compare_NodeParent_with_tuple():
|
||||
node_parent = NodeParent(GenericNodeConcept("For", None), "target")
|
||||
assert node_parent == ("For", "target")
|
||||
|
||||
|
||||
def test_i_can_transform_back():
|
||||
source = """
|
||||
def my_function(a,b):
|
||||
for i in range(b):
|
||||
a = a + b
|
||||
return a
|
||||
|
||||
|
||||
my_function(x, y)
|
||||
"""
|
||||
|
||||
node = ast.parse(source)
|
||||
concept_node = core.ast.nodes.python_to_concept(node)
|
||||
|
||||
transformed_back = core.ast.nodes.concept_to_python(concept_node)
|
||||
assert dump_ast(transformed_back) == dump_ast(node)
|
||||
|
||||
|
||||
def dump_ast(node):
|
||||
dump = ast.dump(node)
|
||||
for to_remove in [", ctx=Load()", ", kind=None", ", type_ignores=[]"]:
|
||||
dump = dump.replace(to_remove, "")
|
||||
return dump
|
||||
@@ -0,0 +1,44 @@
|
||||
import ast
|
||||
|
||||
import pytest
|
||||
from core.ast_helpers import UnreferencedNamesVisitor, UnreferencedVariablesVisitor
|
||||
|
||||
from tests.TestUsingMemoryBasedSheerka import TestUsingMemoryBasedSheerka
|
||||
|
||||
|
||||
class TestAstHelper(TestUsingMemoryBasedSheerka):
|
||||
@pytest.mark.parametrize("source, expected", [
|
||||
("a,b", {"a", "b"}),
|
||||
("isinstance(a, int)", {"isinstance", "a", "int"}),
|
||||
("date.today()", {"date"}),
|
||||
("test()", {"test"}),
|
||||
("sheerka.test()", {"sheerka"}),
|
||||
("for i in range(10): pass", set())
|
||||
|
||||
])
|
||||
def test_i_can_get_unreferenced_names_from_simple_expressions(self, source, expected):
|
||||
context = self.get_context()
|
||||
|
||||
ast_ = ast.parse(source)
|
||||
visitor = UnreferencedNamesVisitor(context)
|
||||
visitor.visit(ast_)
|
||||
|
||||
assert visitor.names == expected
|
||||
|
||||
@pytest.mark.parametrize("source, expected", [
|
||||
("a,b", {"a", "b"}),
|
||||
("isinstance(a, int)", {"a", "int"}),
|
||||
("date.today()", set()),
|
||||
("test()", set()),
|
||||
("sheerka.test()", set()),
|
||||
("for i in range(10): pass", set())
|
||||
|
||||
])
|
||||
def test_i_can_get_unreferenced_variables_from_simple_expressions(self, source, expected):
|
||||
context = self.get_context()
|
||||
|
||||
ast_ = ast.parse(source)
|
||||
visitor = UnreferencedVariablesVisitor(context)
|
||||
visitor.visit(ast_)
|
||||
|
||||
assert visitor.names == expected
|
||||
@@ -105,44 +105,44 @@ class TestBuiltinHelpers(TestUsingMemoryBasedSheerka):
|
||||
assert not res.status
|
||||
assert res == item
|
||||
|
||||
@pytest.mark.parametrize("expression, vars_to_include, vars_to_exclude, expected_expr", [
|
||||
("a == 1", [], [], []),
|
||||
("a == 1", ["a"], [], ["a == 1"]),
|
||||
("a == 1", [], ["a"], []),
|
||||
("predicate(a)", [], [], []),
|
||||
("predicate(a)", ["a"], [], ["predicate(a)"]),
|
||||
("predicate(a, b)", ["a"], [], ["predicate(a, b)"]),
|
||||
("predicate(a, b)", ["b"], [], ["predicate(a, b)"]),
|
||||
("predicate(a, b)", ["a", "b"], [], ["predicate(a, b)"]),
|
||||
("predicate(a, b)", ["a"], ["b"], []),
|
||||
("a + b == 1", [], [], []),
|
||||
("a + b == 1", ["a"], [], ["a + b == 1"]),
|
||||
("a + b == 1", ["a"], ["b"], []),
|
||||
("a + b == 1", ["b"], [], ["a + b == 1"]),
|
||||
("a + b == 1", ["a", "b"], [], ["a + b == 1"]),
|
||||
("a == 1 and b == 2", [], [], []),
|
||||
("a == 1 and b == 2", ["a"], [], ["a == 1"]),
|
||||
("a == 1 and b == 2", ["b"], [], ["b == 2"]),
|
||||
("a == 1 and b == 2", ["a"], ["b"], ["a == 1"]),
|
||||
("a == 1 and b == 2", ["a", "b"], [], ["a == 1 and b == 2"]),
|
||||
("predicate(a,c) and predicate(b,c)", ["a", "b"], [], ["predicate(a,c) and predicate(b,c)"]),
|
||||
("not(a == 1)", [], [], []),
|
||||
("not(a == 1)", ["a"], [], ["not(a==1)"]),
|
||||
("a == 1 or b == 2", [], [], []),
|
||||
("a == 1 or b == 2", ["a"], [], ["a == 1"]),
|
||||
("a == 1 or b == 2", ["b"], [], ["b == 2"]),
|
||||
("a == 1 or b == 2", ["a", "b"], [], ["a == 1 or b == 2"]),
|
||||
("predicate(a,c) or predicate(b,c)", ["a", "b"], [], ["predicate(a,c) or predicate(b,c)"]),
|
||||
("a < 1 and a > b", ["a"], [], ["a < 1 and a > b"]),
|
||||
])
|
||||
def test_i_can_extract_predicates(self, expression, vars_to_include, vars_to_exclude, expected_expr):
|
||||
sheerka = self.get_sheerka()
|
||||
expected = [ast.parse(expr, mode="eval") for expr in expected_expr]
|
||||
|
||||
actual = core.builtin_helpers.extract_predicates(sheerka, expression, vars_to_include, vars_to_exclude)
|
||||
assert len(actual) == len(expected)
|
||||
for i in range(len(actual)):
|
||||
assert self.dump_ast(actual[i]) == self.dump_ast(expected[i])
|
||||
# @pytest.mark.parametrize("expression, vars_to_include, vars_to_exclude, expected_expr", [
|
||||
# ("a == 1", [], [], []),
|
||||
# ("a == 1", ["a"], [], ["a == 1"]),
|
||||
# ("a == 1", [], ["a"], []),
|
||||
# ("predicate(a)", [], [], []),
|
||||
# ("predicate(a)", ["a"], [], ["predicate(a)"]),
|
||||
# ("predicate(a, b)", ["a"], [], ["predicate(a, b)"]),
|
||||
# ("predicate(a, b)", ["b"], [], ["predicate(a, b)"]),
|
||||
# ("predicate(a, b)", ["a", "b"], [], ["predicate(a, b)"]),
|
||||
# ("predicate(a, b)", ["a"], ["b"], []),
|
||||
# ("a + b == 1", [], [], []),
|
||||
# ("a + b == 1", ["a"], [], ["a + b == 1"]),
|
||||
# ("a + b == 1", ["a"], ["b"], []),
|
||||
# ("a + b == 1", ["b"], [], ["a + b == 1"]),
|
||||
# ("a + b == 1", ["a", "b"], [], ["a + b == 1"]),
|
||||
# ("a == 1 and b == 2", [], [], []),
|
||||
# ("a == 1 and b == 2", ["a"], [], ["a == 1"]),
|
||||
# ("a == 1 and b == 2", ["b"], [], ["b == 2"]),
|
||||
# ("a == 1 and b == 2", ["a"], ["b"], ["a == 1"]),
|
||||
# ("a == 1 and b == 2", ["a", "b"], [], ["a == 1 and b == 2"]),
|
||||
# ("predicate(a,c) and predicate(b,c)", ["a", "b"], [], ["predicate(a,c) and predicate(b,c)"]),
|
||||
# ("not(a == 1)", [], [], []),
|
||||
# ("not(a == 1)", ["a"], [], ["not(a==1)"]),
|
||||
# ("a == 1 or b == 2", [], [], []),
|
||||
# ("a == 1 or b == 2", ["a"], [], ["a == 1"]),
|
||||
# ("a == 1 or b == 2", ["b"], [], ["b == 2"]),
|
||||
# ("a == 1 or b == 2", ["a", "b"], [], ["a == 1 or b == 2"]),
|
||||
# ("predicate(a,c) or predicate(b,c)", ["a", "b"], [], ["predicate(a,c) or predicate(b,c)"]),
|
||||
# ("a < 1 and a > b", ["a"], [], ["a < 1 and a > b"]),
|
||||
# ])
|
||||
# def test_i_can_extract_predicates(self, expression, vars_to_include, vars_to_exclude, expected_expr):
|
||||
# sheerka = self.get_sheerka()
|
||||
# expected = [ast.parse(expr, mode="eval") for expr in expected_expr]
|
||||
#
|
||||
# actual = core.builtin_helpers.extract_predicates(sheerka, expression, vars_to_include, vars_to_exclude)
|
||||
# assert len(actual) == len(expected)
|
||||
# for i in range(len(actual)):
|
||||
# assert self.dump_ast(actual[i]) == self.dump_ast(expected[i])
|
||||
|
||||
@pytest.mark.parametrize("concepts, expected", [
|
||||
([], []),
|
||||
|
||||
+50
-13
@@ -1,6 +1,7 @@
|
||||
import pytest
|
||||
from core.builtin_concepts import BuiltinConcepts
|
||||
|
||||
from core.concept import Concept, ConceptParts, DEFINITION_TYPE_DEF
|
||||
from core.concept import Concept, ConceptParts, DEFINITION_TYPE_DEF, ALL_ATTRIBUTES, get_concept_attrs
|
||||
|
||||
|
||||
@pytest.mark.parametrize("name, variables, expected", [
|
||||
@@ -24,7 +25,7 @@ from core.concept import Concept, ConceptParts, DEFINITION_TYPE_DEF
|
||||
def test_i_can_compute_the_key(name, variables, expected):
|
||||
concept = Concept(name)
|
||||
for var_name in variables:
|
||||
concept.metadata.variables.append((var_name, None))
|
||||
concept.get_metadata().variables.append((var_name, None))
|
||||
concept.init_key()
|
||||
|
||||
assert concept.key == expected
|
||||
@@ -33,17 +34,17 @@ def test_i_can_compute_the_key(name, variables, expected):
|
||||
def test_i_can_compute_the_key_when_from_definition():
|
||||
# if definition is not defined, use the name
|
||||
concept = Concept()
|
||||
concept.metadata.name = "hello a"
|
||||
concept.metadata.variables = [("a", None)]
|
||||
concept.get_metadata().name = "hello a"
|
||||
concept.get_metadata().variables = [("a", None)]
|
||||
concept.init_key()
|
||||
assert concept.key == "hello __var__0"
|
||||
|
||||
# if definition is defined, use it
|
||||
concept = Concept()
|
||||
concept.metadata.name = "greetings"
|
||||
concept.metadata.definition = "hello a"
|
||||
concept.metadata.definition_type = DEFINITION_TYPE_DEF
|
||||
concept.metadata.variables = [("a", None)]
|
||||
concept.get_metadata().name = "greetings"
|
||||
concept.get_metadata().definition = "hello a"
|
||||
concept.get_metadata().definition_type = DEFINITION_TYPE_DEF
|
||||
concept.get_metadata().variables = [("a", None)]
|
||||
concept.init_key()
|
||||
assert concept.key == "hello __var__0"
|
||||
|
||||
@@ -52,7 +53,7 @@ def test_key_does_not_use_variable_when_definition_is_set():
|
||||
concept = Concept("plus").def_var('plus')
|
||||
|
||||
concept.init_key()
|
||||
assert concept.metadata.key == "plus"
|
||||
assert concept.get_metadata().key == "plus"
|
||||
|
||||
|
||||
def test_i_can_serialize():
|
||||
@@ -181,6 +182,8 @@ def test_i_can_compare_concepts():
|
||||
|
||||
|
||||
def test_i_can_detect_concept_differences():
|
||||
ALL_ATTRIBUTES.clear()
|
||||
|
||||
assert Concept(name="concept_name") != Concept()
|
||||
assert Concept(is_builtin=True) != Concept()
|
||||
assert Concept(is_unique=True) != Concept()
|
||||
@@ -197,14 +200,18 @@ def test_i_can_detect_concept_differences():
|
||||
assert Concept().add_prop("a", "b") != Concept()
|
||||
assert Concept().set_value("a", "b") != Concept()
|
||||
|
||||
|
||||
def test_compiled_is_not_used_when_comparing_concepts():
|
||||
ALL_ATTRIBUTES.clear()
|
||||
|
||||
concept = Concept()
|
||||
concept.compiled["foo"] = "value"
|
||||
concept.get_compiled()["foo"] = "value"
|
||||
assert concept == Concept() # compiled is not used in the comparison
|
||||
|
||||
|
||||
def test_i_can_compare_concept_with_circular_reference():
|
||||
foo = Concept("foo")
|
||||
foo.metadata.body = foo
|
||||
foo.get_metadata().body = foo
|
||||
|
||||
assert foo == foo
|
||||
|
||||
@@ -213,7 +220,7 @@ def test_i_can_compare_concept_with_sophisticated_circular_reference():
|
||||
foo = Concept("foo")
|
||||
bar = Concept("foo", body=foo)
|
||||
baz = Concept("foo", body=bar)
|
||||
foo.metadata.body = baz
|
||||
foo.get_metadata().body = baz
|
||||
|
||||
assert foo != bar
|
||||
|
||||
@@ -222,12 +229,14 @@ def test_i_can_compare_concept_with_sophisticated_circular_reference_in_other_me
|
||||
foo = Concept("foo")
|
||||
bar = Concept("foo", pre=foo)
|
||||
baz = Concept("foo", pre=bar)
|
||||
foo.metadata.pre = baz
|
||||
foo.get_metadata().pre = baz
|
||||
|
||||
assert foo != bar
|
||||
|
||||
|
||||
def test_i_can_update_from():
|
||||
ALL_ATTRIBUTES.clear()
|
||||
|
||||
template = Concept(
|
||||
name="concept_name",
|
||||
is_builtin=True,
|
||||
@@ -242,6 +251,9 @@ def test_i_can_update_from():
|
||||
desc="this this the desc",
|
||||
id="123456"
|
||||
).def_var("a", "10").def_var("b", None)
|
||||
template.add_prop(BuiltinConcepts.ISA, Concept("foo").def_var("x", "value_x"))
|
||||
template.add_prop(BuiltinConcepts.HASA, Concept("bar").def_var("x", "value_x"))
|
||||
template.set_prop(BuiltinConcepts.AUTO_EVAL, True)
|
||||
|
||||
# make sure origin is preserved
|
||||
setattr(template, "##origin##", "digest")
|
||||
@@ -257,3 +269,28 @@ def test_i_can_update_from():
|
||||
|
||||
assert concept == template
|
||||
assert getattr(concept, "##origin##") == "digest"
|
||||
|
||||
|
||||
def test_i_can_manage_concepts_attributes():
|
||||
ALL_ATTRIBUTES.clear()
|
||||
concept = Concept("foo")
|
||||
assert get_concept_attrs(concept) == []
|
||||
assert concept.values() == {}
|
||||
|
||||
concept.set_value(ConceptParts.BODY, "I have a body!")
|
||||
assert concept.values() == {"#body#": "I have a body!"}
|
||||
|
||||
|
||||
def test_attributes_are_generated_once_for_all():
|
||||
ALL_ATTRIBUTES.clear()
|
||||
concept = Concept("foo")
|
||||
concept.get_metadata().id = "id"
|
||||
|
||||
concept.set_value("key1", "value1")
|
||||
concept.set_value("key2", "value2")
|
||||
assert get_concept_attrs(concept) == ["key1", "key2"]
|
||||
assert concept.values() == {"key1": "value1", "key2": "value2"}
|
||||
|
||||
concept.set_value("key3", "value3") # too late for it !
|
||||
assert get_concept_attrs(concept) == ["key1", "key2"]
|
||||
assert concept.values() == {"key1": "value1", "key2": "value2"}
|
||||
|
||||
+36
-36
@@ -1,8 +1,8 @@
|
||||
import os
|
||||
|
||||
import pytest
|
||||
from core.builtin_concepts import BuiltinConcepts, ReturnValueConcept, UserInputConcept
|
||||
from core.concept import Concept, PROPERTIES_TO_SERIALIZE, ConceptParts
|
||||
from core.builtin_concepts import BuiltinConcepts, ReturnValueConcept, UserInputConcept, AllBuiltinConcepts
|
||||
from core.concept import Concept, PROPERTIES_TO_SERIALIZE, ConceptParts, NotInit
|
||||
from core.sheerka.Sheerka import Sheerka, BASE_NODE_PARSER_CLASS
|
||||
from core.tokenizer import Token, TokenKind
|
||||
|
||||
@@ -31,7 +31,7 @@ class TestSheerkaUsingMemoryBasedSheerka(TestUsingMemoryBasedSheerka):
|
||||
assert "parsers.DefConceptParser.DefConceptParser" in sheerka.parsers
|
||||
assert "parsers.BnfNodeParser.BnfNodeParser" in sheerka.parsers
|
||||
assert "parsers.SyaNodeParser.SyaNodeParser" in sheerka.parsers
|
||||
assert "parsers.AtomNodeParser.AtomNodeParser" in sheerka.parsers
|
||||
assert "parsers.SequenceNodeParser.SequenceNodeParser" in sheerka.parsers
|
||||
|
||||
# make sure BaseNodeParser is properly initialized
|
||||
assert BASE_NODE_PARSER_CLASS not in sheerka.parsers
|
||||
@@ -70,7 +70,7 @@ class TestSheerkaUsingMemoryBasedSheerka(TestUsingMemoryBasedSheerka):
|
||||
assert loaded is not None
|
||||
assert sheerka.isinstance(loaded, BuiltinConcepts.UNKNOWN_CONCEPT)
|
||||
assert loaded.body == ("key", "key_that_does_not_exist")
|
||||
assert loaded.metadata.is_evaluated
|
||||
assert loaded.get_metadata().is_evaluated
|
||||
|
||||
def test_i_cannot_get_when_id_is_not_found(self):
|
||||
sheerka = self.get_sheerka()
|
||||
@@ -80,7 +80,7 @@ class TestSheerkaUsingMemoryBasedSheerka(TestUsingMemoryBasedSheerka):
|
||||
assert loaded is not None
|
||||
assert sheerka.isinstance(loaded, BuiltinConcepts.UNKNOWN_CONCEPT)
|
||||
assert loaded.body == ("id", "id_that_does_not_exist")
|
||||
assert loaded.metadata.is_evaluated
|
||||
assert loaded.get_metadata().is_evaluated
|
||||
|
||||
def test_i_can_instantiate_a_builtin_concept_when_it_has_its_own_class(self):
|
||||
sheerka = self.get_sheerka()
|
||||
@@ -112,7 +112,7 @@ class TestSheerkaUsingMemoryBasedSheerka(TestUsingMemoryBasedSheerka):
|
||||
|
||||
assert sheerka.isinstance(new, concept)
|
||||
for prop in PROPERTIES_TO_SERIALIZE:
|
||||
assert getattr(new.metadata, prop) == getattr(concept.metadata, prop)
|
||||
assert getattr(new.get_metadata(), prop) == getattr(concept.get_metadata(), prop)
|
||||
|
||||
assert new.get_value("a") == 10
|
||||
assert new.get_value("b") == "value"
|
||||
@@ -127,17 +127,17 @@ class TestSheerkaUsingMemoryBasedSheerka(TestUsingMemoryBasedSheerka):
|
||||
concepts = sheerka.new("foo")
|
||||
assert len(concepts) == 2
|
||||
assert concepts[0].id == "1001"
|
||||
assert concepts[0].metadata.body == "foo1"
|
||||
assert concepts[0].get_metadata().body == "foo1"
|
||||
assert concepts[1].id == "1002"
|
||||
assert concepts[1].metadata.body == "foo2"
|
||||
assert concepts[1].get_metadata().body == "foo2"
|
||||
|
||||
# only one instance if the id is given
|
||||
foo1 = sheerka.new(("foo", "1001"))
|
||||
assert foo1.metadata.body == "foo1"
|
||||
assert foo1.get_metadata().body == "foo1"
|
||||
|
||||
# only one instance if the id is given
|
||||
foo2 = sheerka.new(("foo", "1002"))
|
||||
assert foo2.metadata.body == "foo2"
|
||||
assert foo2.get_metadata().body == "foo2"
|
||||
|
||||
def test_instances_are_different_when_asking_for_new(self):
|
||||
sheerka, context, concept = self.init_concepts(self.get_default_concept(), create_new=True)
|
||||
@@ -152,18 +152,18 @@ class TestSheerkaUsingMemoryBasedSheerka(TestUsingMemoryBasedSheerka):
|
||||
sheerka, context, foo, bar = self.init_concepts("foo", "bar", create_new=True)
|
||||
|
||||
new_foo = sheerka.new("foo")
|
||||
new_foo.metadata.body = "metadata value" # modify metadata
|
||||
new_foo.get_metadata().body = "metadata value" # modify metadata
|
||||
new_foo.def_var("var_name", "default value") # modify definition of variables
|
||||
new_foo.add_prop(BuiltinConcepts.ISA, bar) # modify property
|
||||
new_foo.compiled["var_name"] = "'var value'"
|
||||
new_foo.get_compiled()["var_name"] = "'var value'"
|
||||
new_foo.set_value(ConceptParts.BODY, "body value") # modify value
|
||||
new_foo.set_value("var_name", "var value") # modify value
|
||||
|
||||
assert new_foo.metadata.body != foo.metadata.body
|
||||
assert new_foo.metadata.variables != foo.metadata.variables
|
||||
assert new_foo.metadata.props != foo.metadata.props
|
||||
assert new_foo.get_metadata().body != foo.get_metadata().body
|
||||
assert new_foo.get_metadata().variables != foo.get_metadata().variables
|
||||
assert new_foo.get_metadata().props != foo.get_metadata().props
|
||||
assert new_foo.values != foo.values
|
||||
assert new_foo.compiled != foo.compiled
|
||||
assert new_foo.get_compiled() != foo.get_compiled()
|
||||
|
||||
def test_i_get_the_same_instance_when_is_unique_is_true(self):
|
||||
sheerka, context, concept = self.init_concepts(Concept(name="unique", is_unique=True), create_new=True)
|
||||
@@ -181,16 +181,16 @@ class TestSheerkaUsingMemoryBasedSheerka(TestUsingMemoryBasedSheerka):
|
||||
eval_body=True)
|
||||
|
||||
sheerka.evaluate_concept(context, sheerka.get_by_id(template.id))
|
||||
assert template.metadata.is_evaluated
|
||||
assert template.get_metadata().is_evaluated
|
||||
assert template.body == "foo body"
|
||||
|
||||
new = sheerka.new(template.key)
|
||||
assert not new.metadata.is_evaluated
|
||||
assert new.body == BuiltinConcepts.NOT_INITIALIZED
|
||||
assert not new.get_metadata().is_evaluated
|
||||
assert new.body == NotInit
|
||||
|
||||
new = sheerka.new((None, template.id))
|
||||
assert not new.metadata.is_evaluated
|
||||
assert new.body == BuiltinConcepts.NOT_INITIALIZED
|
||||
assert not new.get_metadata().is_evaluated
|
||||
assert new.body == NotInit
|
||||
|
||||
def test_i_cannot_instantiate_an_unknown_concept(self):
|
||||
sheerka = self.get_sheerka()
|
||||
@@ -230,7 +230,7 @@ class TestSheerkaUsingMemoryBasedSheerka(TestUsingMemoryBasedSheerka):
|
||||
new = sheerka.new(("foo", "invalid_id"))
|
||||
|
||||
assert sheerka.isinstance(new, "foo")
|
||||
assert new.metadata.body == "foo1"
|
||||
assert new.get_metadata().body == "foo1"
|
||||
|
||||
def test_i_cannot_instantiate_when_properties_are_not_recognized(self):
|
||||
sheerka, context, concept = self.init_concepts(self.get_default_concept(), create_new=True)
|
||||
@@ -242,16 +242,16 @@ class TestSheerkaUsingMemoryBasedSheerka(TestUsingMemoryBasedSheerka):
|
||||
assert sheerka.isinstance(new.concept, concept)
|
||||
|
||||
@pytest.mark.parametrize("concept, reduce_simple_list, expected", [
|
||||
# (None, False, None),
|
||||
# (3.14, False, 3.14),
|
||||
# ("foo", False, "foo"),
|
||||
# (True, False, True),
|
||||
# (Concept("name", body="foo"), False, "foo"),
|
||||
# (Concept("name"), False, Concept("name")),
|
||||
# (ConceptWithGetObjValue("name").set_value("my_prop", "my_value"), False, "my_value"),
|
||||
# (ReturnValueConcept(value="return_value"), False, "return_value"),
|
||||
# (ReturnValueConcept(value=Concept(key=BuiltinConcepts.USER_INPUT, body="text"), status=True), False, "text"),
|
||||
# (ReturnValueConcept(value=UserInputConcept("text"), status=True), False, "text"),
|
||||
(None, False, None),
|
||||
(3.14, False, 3.14),
|
||||
("foo", False, "foo"),
|
||||
(True, False, True),
|
||||
(Concept("name", body="foo"), False, "foo"),
|
||||
(Concept("name"), False, Concept("name")),
|
||||
(ConceptWithGetObjValue("name").set_value("my_prop", "my_value"), False, "my_value"),
|
||||
(ReturnValueConcept(value="return_value"), False, "return_value"),
|
||||
(ReturnValueConcept(value=Concept(key=BuiltinConcepts.USER_INPUT, body="text"), status=True), False, "text"),
|
||||
(ReturnValueConcept(value=UserInputConcept("text"), status=True), False, "text"),
|
||||
(ReturnValueConcept(value=Concept("foo", body=False).auto_init(), status=True), False, False),
|
||||
(Concept("name", body=["foo", "bar"]), False, ["foo", "bar"]),
|
||||
(Concept("name", body=["foo"]), True, "foo"),
|
||||
@@ -342,7 +342,7 @@ class TestSheerkaUsingFileBasedSheerka(TestUsingFileBasedSheerka):
|
||||
|
||||
def test_builtin_concepts_are_initialized(self):
|
||||
sheerka = self.get_sheerka()
|
||||
for concept_name in BuiltinConcepts:
|
||||
for concept_name in AllBuiltinConcepts:
|
||||
assert sheerka.has_key(str(concept_name))
|
||||
assert sheerka.sdp.get(sheerka.CONCEPTS_BY_KEY_ENTRY, str(concept_name)) is not None
|
||||
|
||||
@@ -360,15 +360,15 @@ class TestSheerkaUsingFileBasedSheerka(TestUsingFileBasedSheerka):
|
||||
def test_builtin_concepts_can_be_updated(self):
|
||||
sheerka = self.get_sheerka()
|
||||
before_parsing = sheerka.get_by_key(BuiltinConcepts.BEFORE_PARSING)
|
||||
before_parsing.metadata.desc = "I have a description"
|
||||
before_parsing.metadata.full_serialization = True
|
||||
before_parsing.get_metadata().desc = "I have a description"
|
||||
before_parsing.get_metadata().full_serialization = True
|
||||
with sheerka.sdp.get_transaction("Test") as transac:
|
||||
transac.add(sheerka.CONCEPTS_BY_KEY_ENTRY, before_parsing.key, before_parsing, use_ref=True)
|
||||
|
||||
sheerka = self.get_sheerka() # another fresh new instance
|
||||
before_parsing = sheerka.get_by_key(BuiltinConcepts.BEFORE_PARSING)
|
||||
|
||||
assert before_parsing.metadata.desc == "I have a description"
|
||||
assert before_parsing.get_metadata().desc == "I have a description"
|
||||
|
||||
def test_i_first_look_in_local_cache(self):
|
||||
sheerka, context, concept = self.init_concepts("foo", create_new=True)
|
||||
|
||||
@@ -1,6 +1,8 @@
|
||||
import types
|
||||
|
||||
import pytest
|
||||
from core.builtin_concepts import BuiltinConcepts
|
||||
from core.sheerka.ExecutionContext import ExecutionContext
|
||||
from core.sheerka.services.SheerkaResultManager import SheerkaResultConcept
|
||||
from sdp.sheerkaDataProvider import Event
|
||||
|
||||
@@ -8,21 +10,28 @@ from tests.TestUsingMemoryBasedSheerka import TestUsingMemoryBasedSheerka
|
||||
|
||||
|
||||
class TestSheerkaResultManager(TestUsingMemoryBasedSheerka):
|
||||
io_cache = None
|
||||
|
||||
@classmethod
|
||||
def setup_class(cls):
|
||||
sheerka = cls().get_sheerka()
|
||||
sheerka.save_execution_context = True
|
||||
sheerka.evaluate_user_input("def concept one as 1")
|
||||
cls.io_cache = sheerka.sdp.io.cache.copy()
|
||||
|
||||
@classmethod
|
||||
def teardown_class(cls):
|
||||
sheerka = cls().get_sheerka()
|
||||
sheerka.save_execution_context = False
|
||||
|
||||
def test_i_can_get_the_result_by_digest(self):
|
||||
def init_test(self):
|
||||
sheerka, context = self.init_concepts()
|
||||
sheerka.sdp.io.cache = self.io_cache.copy()
|
||||
return sheerka, context
|
||||
|
||||
def test_i_can_get_the_result_by_digest(self):
|
||||
sheerka, context = self.init_test()
|
||||
|
||||
sheerka.evaluate_user_input("def concept one as 1")
|
||||
digest = sheerka.get_last_execution().event.get_digest()
|
||||
|
||||
res = sheerka.get_results_by_digest(context, digest)
|
||||
@@ -32,7 +41,7 @@ class TestSheerkaResultManager(TestUsingMemoryBasedSheerka):
|
||||
assert res.digest == digest
|
||||
assert isinstance(res.body, types.GeneratorType)
|
||||
|
||||
assert sheerka.load(SheerkaResultConcept.NAME, "digest") == digest
|
||||
assert sheerka.load_var(SheerkaResultConcept.NAME, "digest") == digest
|
||||
|
||||
previous_results = list(res.body)
|
||||
|
||||
@@ -58,11 +67,9 @@ class TestSheerkaResultManager(TestUsingMemoryBasedSheerka):
|
||||
assert sheerka.get_results(context) is None
|
||||
|
||||
def test_i_can_get_the_result_by_command_name(self):
|
||||
sheerka, context = self.init_concepts()
|
||||
sheerka, context = self.init_test()
|
||||
|
||||
sheerka.evaluate_user_input("def concept one as 1")
|
||||
digest = sheerka.get_last_execution().event.get_digest()
|
||||
|
||||
sheerka.evaluate_user_input("one") # another command
|
||||
|
||||
res = sheerka.get_results_by_command(context, "def concept")
|
||||
@@ -72,9 +79,8 @@ class TestSheerkaResultManager(TestUsingMemoryBasedSheerka):
|
||||
assert isinstance(res.body, types.GeneratorType)
|
||||
|
||||
def test_i_can_get_the_result_by_command_when_not_in_the_same_page_size(self):
|
||||
sheerka, context = self.init_concepts()
|
||||
sheerka, context = self.init_test()
|
||||
|
||||
sheerka.evaluate_user_input("def concept one as 1")
|
||||
sheerka.evaluate_user_input("one")
|
||||
sheerka.evaluate_user_input("one")
|
||||
sheerka.evaluate_user_input("one")
|
||||
@@ -92,9 +98,8 @@ class TestSheerkaResultManager(TestUsingMemoryBasedSheerka):
|
||||
assert res.body == {'command': 'def concept'}
|
||||
|
||||
def test_i_cannot_get_result_from_command_if_the_command_does_not_exists_multiple_pages(self):
|
||||
sheerka, context = self.init_concepts()
|
||||
sheerka, context = self.init_test()
|
||||
|
||||
sheerka.evaluate_user_input("def concept one as 1")
|
||||
sheerka.evaluate_user_input("one")
|
||||
sheerka.evaluate_user_input("one")
|
||||
sheerka.evaluate_user_input("one")
|
||||
@@ -105,9 +110,8 @@ class TestSheerkaResultManager(TestUsingMemoryBasedSheerka):
|
||||
assert res.body == {'command': 'fake command'}
|
||||
|
||||
def test_i_can_get_last_results(self):
|
||||
sheerka, context = self.init_concepts()
|
||||
sheerka, context = self.init_test()
|
||||
|
||||
sheerka.evaluate_user_input("def concept one as 1")
|
||||
sheerka.evaluate_user_input("one")
|
||||
|
||||
res = sheerka.get_last_results(context)
|
||||
@@ -144,4 +148,106 @@ class TestSheerkaResultManager(TestUsingMemoryBasedSheerka):
|
||||
assert sheerka.isinstance(res, BuiltinConcepts.NOT_FOUND)
|
||||
assert res.body == {'query': 'last'}
|
||||
|
||||
@pytest.mark.parametrize('kwargs', [
|
||||
{"desc": "Evaluating 'def concept one as 1'"},
|
||||
{"id": 0},
|
||||
{"desc": "Evaluating 'def concept one as 1'", "id": 0}
|
||||
])
|
||||
def test_i_can_get_last_results_using_kwarg(self, kwargs):
|
||||
sheerka, context = self.init_test()
|
||||
ExecutionContext.ids.clear()
|
||||
|
||||
res = sheerka.get_last_results(context, **kwargs)
|
||||
items = list(res.body)
|
||||
|
||||
assert len(items) == 1
|
||||
for k, v in kwargs.items():
|
||||
assert getattr(items[0], k) == v
|
||||
|
||||
@pytest.mark.parametrize('predicate, expected', [
|
||||
('desc.startswith("Evaluating \'def concept one as 1\'")', {"desc": "Evaluating 'def concept one as 1'"}),
|
||||
("id == 0", {"id": 0}),
|
||||
("'def concept one as 1' in desc and id == 0", {"desc": "Evaluating 'def concept one as 1'", "id": 0})
|
||||
])
|
||||
def test_i_can_get_last_results_using_filter(self, predicate, expected):
|
||||
sheerka, context = self.init_test()
|
||||
ExecutionContext.ids.clear()
|
||||
|
||||
res = sheerka.get_last_results(context, filter=predicate)
|
||||
items = list(res.body)
|
||||
|
||||
assert len(items) == 1
|
||||
for k, v in expected.items():
|
||||
assert getattr(items[0], k) == v
|
||||
|
||||
@pytest.mark.parametrize('predicate, expected', [
|
||||
('desc.startswith("Evaluating \'def concept one as 1\'")', {"desc": "Evaluating 'def concept one as 1'"}),
|
||||
("id == 0", {"id": 0}),
|
||||
("'def concept one as 1' in desc and id == 0", {"desc": "Evaluating 'def concept one as 1'", "id": 0})
|
||||
])
|
||||
def test_i_can_get_last_results_using_the_first_argument_to_filter(self, predicate, expected):
|
||||
sheerka, context = self.init_test()
|
||||
ExecutionContext.ids.clear()
|
||||
|
||||
res = sheerka.get_last_results(context, predicate)
|
||||
items = list(res.body)
|
||||
|
||||
assert len(items) == 1
|
||||
for k, v in expected.items():
|
||||
assert getattr(items[0], k) == v
|
||||
|
||||
@pytest.mark.parametrize('kwargs', [
|
||||
{"desc": "Evaluating 'def concept one as 1'"},
|
||||
{"id": 0},
|
||||
{"desc": "Evaluating 'def concept one as 1'", "id": 0}
|
||||
])
|
||||
def test_i_can_get_results_using_kwarg(self, kwargs):
|
||||
sheerka, context = self.init_test()
|
||||
ExecutionContext.ids.clear()
|
||||
sheerka.get_last_results(context)
|
||||
|
||||
res = sheerka.get_results(context, **kwargs)
|
||||
items = list(res.body)
|
||||
|
||||
assert len(items) == 1
|
||||
for k, v in kwargs.items():
|
||||
assert getattr(items[0], k) == v
|
||||
|
||||
@pytest.mark.parametrize('predicate, expected', [
|
||||
('desc.startswith("Evaluating \'def concept one as 1\'")', {"desc": "Evaluating 'def concept one as 1'"}),
|
||||
("id == 0", {"id": 0}),
|
||||
("'def concept one as 1' in desc and id == 0", {"desc": "Evaluating 'def concept one as 1'", "id": 0})
|
||||
])
|
||||
def test_i_can_get_results_using_filter(self, predicate, expected):
|
||||
sheerka, context = self.init_test()
|
||||
ExecutionContext.ids.clear()
|
||||
sheerka.get_last_results(context)
|
||||
|
||||
res = sheerka.get_results(context, filter=predicate)
|
||||
items = list(res.body)
|
||||
|
||||
assert len(items) == 1
|
||||
for k, v in expected.items():
|
||||
assert getattr(items[0], k) == v
|
||||
|
||||
@pytest.mark.parametrize('predicate, expected', [
|
||||
('desc.startswith("Evaluating \'def concept one as 1\'")', {"desc": "Evaluating 'def concept one as 1'"}),
|
||||
("id == 0", {"id": 0}),
|
||||
("'def concept one as 1' in desc and id == 0", {"desc": "Evaluating 'def concept one as 1'", "id": 0})
|
||||
])
|
||||
def test_i_can_get_results_using_the_first_argument_to_filter(self, predicate, expected):
|
||||
sheerka, context = self.init_test()
|
||||
ExecutionContext.ids.clear()
|
||||
sheerka.get_last_results(context)
|
||||
|
||||
res = sheerka.get_results(context, predicate)
|
||||
items = list(res.body)
|
||||
|
||||
assert len(items) == 1
|
||||
for k, v in expected.items():
|
||||
assert getattr(items[0], k) == v
|
||||
|
||||
def test_i_can_manage_invalid_predicates(self):
|
||||
predicate = {"filter": "a b c"}
|
||||
with pytest.raises(SyntaxError):
|
||||
SheerkaResultConcept.get_predicate(**predicate)
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
from core.builtin_concepts import BuiltinConcepts
|
||||
from core.concept import Concept
|
||||
from core.sheerka.services.SheerkaExecute import SheerkaExecute
|
||||
from evaluators.BaseEvaluator import OneReturnValueEvaluator, BaseEvaluator, AllReturnValuesEvaluator
|
||||
|
||||
from tests.BaseTest import BaseTest
|
||||
@@ -15,16 +16,18 @@ class Out:
|
||||
target = [str(r.body.key) for r in return_value]
|
||||
else:
|
||||
target = str(return_value.body.key)
|
||||
step = str(context.step)
|
||||
text = f"{step} [{context.iteration}] "
|
||||
step = str(context.action_context["step"])
|
||||
iteration = context.action_context["iteration"]
|
||||
text = f"{step} [{iteration}] "
|
||||
text += f"{name} - {method} - target={target}"
|
||||
self.debug_out.append(text)
|
||||
|
||||
def out_all(self, method, name, context, return_values):
|
||||
name = name[len(BaseEvaluator.PREFIX):]
|
||||
target = [str(r.body.key) for r in return_values]
|
||||
step = str(context.step)
|
||||
text = f"{step} [{context.iteration}] "
|
||||
step = str(context.action_context["step"])
|
||||
iteration = context.action_context["iteration"]
|
||||
text = f"{step} [{iteration}] "
|
||||
text += f"{name} - {method} - target={target}"
|
||||
self.debug_out.append(text)
|
||||
|
||||
@@ -295,6 +298,8 @@ class TestSheerkaExecuteEvaluators(TestUsingMemoryBasedSheerka):
|
||||
EvaluatorOneWithPriority10,
|
||||
EvaluatorOneWithPriority15,
|
||||
EvaluatorAllWithPriority20, ]
|
||||
service = sheerka.services[SheerkaExecute.NAME]
|
||||
service.reset_evaluators()
|
||||
|
||||
entries = [self.tretval(sheerka, Concept("foo"))]
|
||||
Out.debug_out = []
|
||||
@@ -318,6 +323,8 @@ class TestSheerkaExecuteEvaluators(TestUsingMemoryBasedSheerka):
|
||||
def test_that_predicate_is_checked_before_evaluation_for_one_return(self):
|
||||
sheerka = self.get_sheerka()
|
||||
sheerka.evaluators = [EvaluatorOneModifyFoo]
|
||||
service = sheerka.services[SheerkaExecute.NAME]
|
||||
service.reset_evaluators()
|
||||
|
||||
entries = [self.tretval(sheerka, Concept("foo")), self.tretval(sheerka, Concept("baz"))]
|
||||
Out.debug_out = []
|
||||
@@ -334,6 +341,8 @@ class TestSheerkaExecuteEvaluators(TestUsingMemoryBasedSheerka):
|
||||
def test_that_predicate_is_checked_before_evaluation_for_all_return(self):
|
||||
sheerka = self.get_sheerka()
|
||||
sheerka.evaluators = [EvaluatorAllReduceFooBar]
|
||||
service = sheerka.services[SheerkaExecute.NAME]
|
||||
service.reset_evaluators()
|
||||
|
||||
entries = [self.tretval(sheerka, Concept("foo")), self.tretval(sheerka, Concept("bar"))]
|
||||
Out.debug_out = []
|
||||
@@ -354,6 +363,8 @@ class TestSheerkaExecuteEvaluators(TestUsingMemoryBasedSheerka):
|
||||
def test_evaluation_continue_until_no_more_modification(self):
|
||||
sheerka = self.get_sheerka()
|
||||
sheerka.evaluators = [EvaluatorOneModifyFoo, EvaluatorOneModifyBar]
|
||||
service = sheerka.services[SheerkaExecute.NAME]
|
||||
service.reset_evaluators()
|
||||
|
||||
entries = [self.tretval(sheerka, Concept("foo")), self.tretval(sheerka, Concept("baz"))]
|
||||
Out.debug_out = []
|
||||
@@ -379,6 +390,8 @@ class TestSheerkaExecuteEvaluators(TestUsingMemoryBasedSheerka):
|
||||
def test_evaluation_steps_are_respected(self):
|
||||
sheerka = self.get_sheerka()
|
||||
sheerka.evaluators = [EvaluatorOneWithPriority10, EvaluatorOnePreEvaluation]
|
||||
service = sheerka.services[SheerkaExecute.NAME]
|
||||
service.reset_evaluators()
|
||||
|
||||
entries = [self.tretval(sheerka, Concept("foo"))]
|
||||
Out.debug_out = []
|
||||
@@ -392,6 +405,8 @@ class TestSheerkaExecuteEvaluators(TestUsingMemoryBasedSheerka):
|
||||
def test_evaluation_multi_steps_are_respected(self):
|
||||
sheerka = self.get_sheerka()
|
||||
sheerka.evaluators = [EvaluatorOneMultiSteps]
|
||||
service = sheerka.services[SheerkaExecute.NAME]
|
||||
service.reset_evaluators()
|
||||
|
||||
entries = [self.tretval(sheerka, Concept("foo"))]
|
||||
Out.debug_out = []
|
||||
@@ -405,9 +420,88 @@ class TestSheerkaExecuteEvaluators(TestUsingMemoryBasedSheerka):
|
||||
'__EVALUATION [0] multiStep - eval - target=foo',
|
||||
]
|
||||
|
||||
def test_evaluators_can_be_selected_in_the_context(self):
|
||||
sheerka, context = self.init_concepts()
|
||||
sheerka.evaluators = [EvaluatorOneWithPriority20,
|
||||
EvaluatorAllWithPriority15,
|
||||
EvaluatorAllWithPriority10, ]
|
||||
service = sheerka.services[SheerkaExecute.NAME]
|
||||
service.reset_evaluators()
|
||||
context.preprocess_evaluators = [EvaluatorAllWithPriority10().short_name] # it will be the only one to be evaluated
|
||||
|
||||
entries = [self.tretval(sheerka, Concept("foo"))]
|
||||
|
||||
Out.debug_out = []
|
||||
sheerka.execute(context, entries, [BuiltinConcepts.EVALUATION])
|
||||
assert Out.debug_out == [
|
||||
"__EVALUATION [0] all_priority10 - matches - target=['foo']",
|
||||
"__EVALUATION [0] all_priority10 - eval - target=['foo']"
|
||||
]
|
||||
|
||||
# grouped evaluator is in cache
|
||||
service = sheerka.services[SheerkaExecute.NAME]
|
||||
assert "__EVALUATION|all_priority10" in service.grouped_evaluators_cache
|
||||
|
||||
def test_evaluators_priorities_can_be_tweaked_by_the_context(self):
|
||||
sheerka, context = self.init_concepts()
|
||||
sheerka.evaluators = [EvaluatorOneWithPriority20,
|
||||
EvaluatorOneWithPriority15,
|
||||
EvaluatorOneWithPriority10, ]
|
||||
service = sheerka.services[SheerkaExecute.NAME]
|
||||
service.reset_evaluators()
|
||||
|
||||
# invert the priorities
|
||||
context.add_preprocess(EvaluatorOneWithPriority20().name, priority=1)
|
||||
context.add_preprocess(EvaluatorOneWithPriority15().name, priority=2)
|
||||
context.add_preprocess(EvaluatorOneWithPriority10().name, priority=3)
|
||||
|
||||
entries = [self.tretval(sheerka, Concept("foo"))]
|
||||
|
||||
Out.debug_out = []
|
||||
sheerka.execute(context, entries, [BuiltinConcepts.EVALUATION])
|
||||
assert Out.debug_out == [
|
||||
"__EVALUATION [0] priority10 - matches - target=foo",
|
||||
"__EVALUATION [0] priority10 - eval - target=foo",
|
||||
"__EVALUATION [0] priority15 - matches - target=foo",
|
||||
"__EVALUATION [0] priority15 - eval - target=foo",
|
||||
'__EVALUATION [0] priority20 - matches - target=foo',
|
||||
'__EVALUATION [0] priority20 - eval - target=foo',
|
||||
]
|
||||
|
||||
# grouped evaluator is in cache
|
||||
service = sheerka.services[SheerkaExecute.NAME]
|
||||
assert "__EVALUATION|evaluators.priority20|evaluators.priority15|evaluators.priority10" in service.grouped_evaluators_cache
|
||||
|
||||
def test_evaluators_enabled_can_be_tweaked_by_the_context(self):
|
||||
sheerka, context = self.init_concepts()
|
||||
sheerka.evaluators = [EvaluatorOneWithPriority20,
|
||||
EvaluatorOneWithPriority15,
|
||||
EvaluatorOneWithPriority10, ]
|
||||
service = sheerka.services[SheerkaExecute.NAME]
|
||||
service.reset_evaluators()
|
||||
|
||||
# invert the priorities
|
||||
context.add_preprocess(EvaluatorOneWithPriority20().name, enabled=False)
|
||||
context.add_preprocess(EvaluatorOneWithPriority15().name, enabled=False)
|
||||
|
||||
entries = [self.tretval(sheerka, Concept("foo"))]
|
||||
|
||||
Out.debug_out = []
|
||||
sheerka.execute(context, entries, [BuiltinConcepts.EVALUATION])
|
||||
assert Out.debug_out == [
|
||||
"__EVALUATION [0] priority10 - matches - target=foo",
|
||||
"__EVALUATION [0] priority10 - eval - target=foo",
|
||||
]
|
||||
|
||||
# grouped evaluator is in cache
|
||||
service = sheerka.services[SheerkaExecute.NAME]
|
||||
assert "__EVALUATION|evaluators.priority10" in service.grouped_evaluators_cache
|
||||
|
||||
def test_evaluators_can_be_pre_processed(self):
|
||||
sheerka = self.get_sheerka()
|
||||
sheerka.evaluators = [EvaluatorOneModifyFoo]
|
||||
service = sheerka.services[SheerkaExecute.NAME]
|
||||
service.reset_evaluators()
|
||||
|
||||
entries = [self.tretval(sheerka, Concept("foo"))]
|
||||
|
||||
@@ -418,7 +512,7 @@ class TestSheerkaExecuteEvaluators(TestUsingMemoryBasedSheerka):
|
||||
sheerka.execute(context, entries, [BuiltinConcepts.EVALUATION])
|
||||
assert Out.debug_out == []
|
||||
|
||||
# other contextes are not impacted
|
||||
# other evaluations are not impacted
|
||||
Out.debug_out = []
|
||||
sheerka.execute(self.get_context(sheerka), entries, [BuiltinConcepts.EVALUATION])
|
||||
assert Out.debug_out == [
|
||||
@@ -430,6 +524,8 @@ class TestSheerkaExecuteEvaluators(TestUsingMemoryBasedSheerka):
|
||||
def test_i_can_initialize_evaluator_if_initialize_evaluator_is_defined(self):
|
||||
sheerka, context, foo, bar, baz = self.init_concepts("foo", "bar", "baz")
|
||||
sheerka.evaluators = [EvaluatorOneInitializationOnce]
|
||||
service = sheerka.services[SheerkaExecute.NAME]
|
||||
service.reset_evaluators()
|
||||
|
||||
entries = [
|
||||
self.tretval(sheerka, foo),
|
||||
@@ -451,6 +547,8 @@ class TestSheerkaExecuteEvaluators(TestUsingMemoryBasedSheerka):
|
||||
def test_i_can_initialize_evaluators_multiple_times(self):
|
||||
sheerka, context, foo, bar, baz = self.init_concepts("foo", "bar", "baz")
|
||||
sheerka.evaluators = [EvaluatorOneInitializationMultiple]
|
||||
service = sheerka.services[SheerkaExecute.NAME]
|
||||
service.reset_evaluators()
|
||||
|
||||
entries = [
|
||||
self.tretval(sheerka, foo),
|
||||
@@ -479,6 +577,8 @@ class TestSheerkaExecuteEvaluators(TestUsingMemoryBasedSheerka):
|
||||
"""
|
||||
sheerka = self.get_sheerka()
|
||||
sheerka.evaluators = [EvaluatorOneDoNotModifyExecutionFlow]
|
||||
service = sheerka.services[SheerkaExecute.NAME]
|
||||
service.reset_evaluators()
|
||||
|
||||
entries = [self.tretval(sheerka, Concept("foo"))]
|
||||
Out.debug_out = []
|
||||
@@ -499,6 +599,8 @@ class TestSheerkaExecuteEvaluators(TestUsingMemoryBasedSheerka):
|
||||
"""
|
||||
sheerka = self.get_sheerka()
|
||||
sheerka.evaluators = [EvaluatorOneModifyFoo]
|
||||
service = sheerka.services[SheerkaExecute.NAME]
|
||||
service.reset_evaluators()
|
||||
|
||||
entries = [self.tretval(sheerka, Concept("foo"))]
|
||||
Out.debug_out = []
|
||||
@@ -516,6 +618,8 @@ class TestSheerkaExecuteEvaluators(TestUsingMemoryBasedSheerka):
|
||||
def test_i_can_remove_return_values_from_the_execution_workflow(self):
|
||||
sheerka = self.get_sheerka()
|
||||
sheerka.evaluators = [EvaluatorAllSuppressEntries]
|
||||
service = sheerka.services[SheerkaExecute.NAME]
|
||||
service.reset_evaluators()
|
||||
|
||||
entries = [self.tretval(sheerka, Concept("foo")),
|
||||
self.tretval(sheerka, Concept("bar")),
|
||||
|
||||
@@ -353,25 +353,21 @@ second : 'value d'
|
||||
sheerka.print(lst)
|
||||
captured = capsys.readouterr()
|
||||
assert captured.out == """(1001)foo a b
|
||||
a : 'value a'
|
||||
var.a: *name 'var' is not defined*
|
||||
b : 'value b'
|
||||
var.b: *name 'var' is not defined*
|
||||
id : '1001'
|
||||
name : 'foo a b'
|
||||
key : 'foo __var__0 __var__1'
|
||||
body : __NOT_INITIALIZED
|
||||
self : (1001)foo a b
|
||||
a : 'value a'
|
||||
b : 'value b'
|
||||
id : '1001'
|
||||
name: 'foo a b'
|
||||
key : 'foo __var__0 __var__1'
|
||||
body: **NotInit**
|
||||
self: (1001)foo a b
|
||||
(1001)foo a b
|
||||
a : 'value c'
|
||||
var.a: *name 'var' is not defined*
|
||||
b : 'value d'
|
||||
var.b: *name 'var' is not defined*
|
||||
id : '1001'
|
||||
name : 'foo a b'
|
||||
key : 'foo __var__0 __var__1'
|
||||
body : __NOT_INITIALIZED
|
||||
self : (1001)foo a b
|
||||
a : 'value c'
|
||||
b : 'value d'
|
||||
id : '1001'
|
||||
name: 'foo a b'
|
||||
key : 'foo __var__0 __var__1'
|
||||
body: **NotInit**
|
||||
self: (1001)foo a b
|
||||
"""
|
||||
|
||||
def test_i_can_format_d_when_dictionary(self, capsys):
|
||||
@@ -391,34 +387,32 @@ self : (1001)foo a b
|
||||
sheerka.print(lst)
|
||||
captured = capsys.readouterr()
|
||||
assert captured.out == """(1001)foo a b
|
||||
a : 'value a'
|
||||
var.a: *name 'var' is not defined*
|
||||
b : {'a' : 'value a'
|
||||
'beta' : {'b1': 10
|
||||
'b2': Obj(a='10', b=15)
|
||||
'b3': ['items',
|
||||
'in',
|
||||
'a',
|
||||
'list']}
|
||||
'gamma' : {'list' : ["'quoted string'",
|
||||
""double" 'single'",
|
||||
'c3']
|
||||
'empty': []}
|
||||
'epsilon': ['a',
|
||||
'b',
|
||||
'c']
|
||||
'g' : {'tuple': ('tuple-a',
|
||||
'tuple-b',
|
||||
'tuple-b')
|
||||
'empty': ()}
|
||||
'h' : {'set' : {'set-a'}
|
||||
'empty': {}}}
|
||||
var.b: *name 'var' is not defined*
|
||||
id : '1001'
|
||||
name : 'foo a b'
|
||||
key : 'foo __var__0 __var__1'
|
||||
body : __NOT_INITIALIZED
|
||||
self : (1001)foo a b
|
||||
a : 'value a'
|
||||
b : {'a' : 'value a'
|
||||
'beta' : {'b1': 10
|
||||
'b2': Obj(a='10', b=15)
|
||||
'b3': ['items',
|
||||
'in',
|
||||
'a',
|
||||
'list']}
|
||||
'gamma' : {'list' : ["'quoted string'",
|
||||
""double" 'single'",
|
||||
'c3']
|
||||
'empty': []}
|
||||
'epsilon': ['a',
|
||||
'b',
|
||||
'c']
|
||||
'g' : {'tuple': ('tuple-a',
|
||||
'tuple-b',
|
||||
'tuple-b')
|
||||
'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
|
||||
"""
|
||||
|
||||
def test_i_can_manage_when_property_does_not_exist(self, capsys):
|
||||
|
||||
@@ -4,7 +4,7 @@ from core.tokenizer import Tokenizer, Token, TokenKind, LexerError
|
||||
|
||||
def test_i_can_tokenize():
|
||||
source = "+*-/{}[]() ,;:.?\n\n\r\r\r\nidentifier_0\t \t10.15 10 'string\n' \"another string\"=|&<>c:name:"
|
||||
source += "$£€!_identifier°~_^\\`==#__var__10r/regex\nregex/"
|
||||
source += "$£€!_identifier°~_^\\`==#__var__10r/regex\nregex/r:xxx|1:"
|
||||
tokens = list(Tokenizer(source))
|
||||
assert tokens[0] == Token(TokenKind.PLUS, "+", 0, 1, 1)
|
||||
assert tokens[1] == Token(TokenKind.STAR, "*", 1, 1, 2)
|
||||
@@ -56,12 +56,15 @@ def test_i_can_tokenize():
|
||||
assert tokens[47] == Token(TokenKind.HASH, '#', 111, 6, 54)
|
||||
assert tokens[48] == Token(TokenKind.VAR_DEF, '__var__10', 112, 6, 55)
|
||||
assert tokens[49] == Token(TokenKind.REGEX, '/regex\nregex/', 121, 6, 64)
|
||||
assert tokens[50] == Token(TokenKind.RULE, ("xxx", "1"), 135, 7, 7)
|
||||
|
||||
assert tokens[50] == Token(TokenKind.EOF, '', 135, 7, 7)
|
||||
assert tokens[51] == Token(TokenKind.EOF, '', 143, 7, 15)
|
||||
|
||||
|
||||
@pytest.mark.parametrize("text, expected", [
|
||||
("_ident", True),
|
||||
("__ident", True),
|
||||
("___ident", True),
|
||||
("ident", True),
|
||||
("ident123", True),
|
||||
("ident_123", True),
|
||||
@@ -168,3 +171,29 @@ def test_i_can_parse_concept_token(text, expected):
|
||||
|
||||
assert tokens[0].type == TokenKind.CONCEPT
|
||||
assert tokens[0].value == expected
|
||||
|
||||
@pytest.mark.parametrize("text, expected", [
|
||||
("r:key:", ("key", None)),
|
||||
("r:key|id:", ("key", "id")),
|
||||
("r:key|:", ("key", None)),
|
||||
("r:|id:", (None, "id")),
|
||||
("r:125:", ("125", None)),
|
||||
])
|
||||
def test_i_can_parse_concept_token(text, expected):
|
||||
tokens = list(Tokenizer(text))
|
||||
|
||||
assert tokens[0].type == TokenKind.RULE
|
||||
assert tokens[0].value == expected
|
||||
|
||||
|
||||
@pytest.mark.parametrize("text, expected", [
|
||||
("r|regex|", "|regex|"),
|
||||
("r/regex/", "/regex/"),
|
||||
("r'regex'", "'regex'"),
|
||||
('r"regex"', '"regex"'),
|
||||
])
|
||||
def test_i_can_parse_regex_token(text, expected):
|
||||
tokens = list(Tokenizer(text))
|
||||
|
||||
assert tokens[0].type == TokenKind.REGEX
|
||||
assert tokens[0].value == expected
|
||||
|
||||
@@ -2,8 +2,8 @@ from dataclasses import dataclass
|
||||
|
||||
import core.utils
|
||||
import pytest
|
||||
from core.concept import ConceptParts, Concept
|
||||
from core.tokenizer import Token, TokenKind
|
||||
from core.concept import Concept
|
||||
from core.tokenizer import Token, TokenKind, Tokenizer, Keywords
|
||||
|
||||
|
||||
@dataclass
|
||||
@@ -15,6 +15,12 @@ class Obj:
|
||||
return hash((self.prop1, self.prop1))
|
||||
|
||||
|
||||
@dataclass
|
||||
class Obj2:
|
||||
prop1: object
|
||||
prop2: object
|
||||
|
||||
|
||||
def get_tokens(lst):
|
||||
res = []
|
||||
for e in lst:
|
||||
@@ -134,11 +140,25 @@ def test_i_can_product(a, b, expected):
|
||||
|
||||
])
|
||||
def test_i_can_strip(input_as_list, expected_as_list):
|
||||
actual = core.utils.strip_tokens(get_tokens(input_as_list))
|
||||
actual = core.utils.strip_tokens(get_tokens(input_as_list)) # KSI 20201007 Why not use Tokenizer ?!! For perf ?
|
||||
expected = get_tokens(expected_as_list)
|
||||
assert actual == expected
|
||||
|
||||
|
||||
@pytest.mark.parametrize("text, value, expected", [
|
||||
("xxx=yyy", "=", 1),
|
||||
("xxx", "=", -1),
|
||||
("xxx = yyy", "=", 2),
|
||||
("xxx = yyy", " = ", -1),
|
||||
])
|
||||
def test_i_can_index(text, value, expected):
|
||||
assert core.utils.index_tokens(Tokenizer(text), value) == expected
|
||||
|
||||
|
||||
def test_i_can_manage_non_in_index_tokens():
|
||||
assert core.utils.index_tokens(None, "=") == -1
|
||||
|
||||
|
||||
def test_by_default_eof_is_not_stripped():
|
||||
actual = core.utils.strip_tokens(get_tokens(["one", "two", " ", "\n", "<EOF>"]))
|
||||
expected = get_tokens(["one", "two", " ", "\n", "<EOF>"])
|
||||
@@ -176,6 +196,16 @@ def test_i_can_unstr_concept(text, expected_key, expected_id):
|
||||
assert i == expected_id
|
||||
|
||||
|
||||
@pytest.mark.parametrize("text, expected_key, expected_id", [
|
||||
("r:key:", "key", None),
|
||||
("r:key|id:", "key", "id"),
|
||||
])
|
||||
def test_i_can_unstr_concept_rules(text, expected_key, expected_id):
|
||||
k, i = core.utils.unstr_concept(text, prefix="r:")
|
||||
assert k == expected_key
|
||||
assert i == expected_id
|
||||
|
||||
|
||||
def test_i_can_str_concept():
|
||||
assert core.utils.str_concept(("key", "id")) == "c:key|id:"
|
||||
assert core.utils.str_concept((None, "id")) == "c:|id:"
|
||||
@@ -186,10 +216,12 @@ def test_i_can_str_concept():
|
||||
concept = Concept("foo").init_key()
|
||||
assert core.utils.str_concept(concept) == "c:foo:"
|
||||
|
||||
concept.metadata.id = "1001"
|
||||
concept.get_metadata().id = "1001"
|
||||
assert core.utils.str_concept(concept) == "c:foo|1001:"
|
||||
assert core.utils.str_concept(concept, drop_name=True) == "c:|1001:"
|
||||
|
||||
assert core.utils.str_concept(("key", "id"), prefix='r:') == "r:key|id:"
|
||||
|
||||
|
||||
@pytest.mark.parametrize("text, expected", [
|
||||
(None, None),
|
||||
@@ -198,7 +230,7 @@ def test_i_can_str_concept():
|
||||
("xxx", None),
|
||||
("xxx.", None),
|
||||
("xxx.yyy", None),
|
||||
("core.concept.ConceptParts.BODY", ConceptParts.BODY),
|
||||
("core.tokenizer.Keywords.CONCEPT", Keywords.CONCEPT),
|
||||
])
|
||||
def test_i_can_decode_enum(text, expected):
|
||||
actual = core.utils.decode_enum(text)
|
||||
@@ -214,15 +246,24 @@ def test_encode_concept_key_id():
|
||||
concept = Concept("foo").init_key()
|
||||
assert core.utils.encode_concept(concept) == "__C__KEY_foo__ID_00None00__C__"
|
||||
|
||||
concept.metadata.id = "1001"
|
||||
concept.get_metadata().id = "1001"
|
||||
assert core.utils.encode_concept(concept) == "__C__KEY_foo__ID_1001__C__"
|
||||
|
||||
assert core.utils.encode_concept(("key", "id"), "R") == "__R__KEY_key__ID_id__R__"
|
||||
assert core.utils.encode_concept((None, "id"), "R") == "__R__KEY_00None00__ID_id__R__"
|
||||
assert core.utils.encode_concept(("key", None), "R") == "__R__KEY_key__ID_00None00__R__"
|
||||
assert core.utils.encode_concept(("k + y", "id"), "R") == "__R__KEY_k000y__ID_id__R__"
|
||||
|
||||
|
||||
def test_decode_concept_key_id():
|
||||
assert core.utils.decode_concept("__C__KEY_key__ID_id__C__") == ("key", "id")
|
||||
assert core.utils.decode_concept("__C__KEY_00None00__ID_id__C__") == (None, "id")
|
||||
assert core.utils.decode_concept("__C__KEY_key__ID_00None00__C__") == ("key", None)
|
||||
|
||||
assert core.utils.decode_concept("__R__KEY_key__ID_id__R__", "R") == ("key", "id")
|
||||
assert core.utils.decode_concept("__R__KEY_00None00__ID_id__R__", "R") == (None, "id")
|
||||
assert core.utils.decode_concept("__R__KEY_key__ID_00None00__R__", "R") == ("key", None)
|
||||
|
||||
|
||||
@pytest.mark.parametrize("a,b,expected", [
|
||||
([], [], []),
|
||||
@@ -246,3 +287,54 @@ def test_i_can_make_unique():
|
||||
assert core.utils.make_unique(["a", "a", "b", "c", "c"]) == ["a", "b", "c"]
|
||||
assert core.utils.make_unique([Obj("a", "b"), Obj("a", "c"), Obj("a", "b")]) == [Obj("a", "b"), Obj("a", "c")]
|
||||
assert core.utils.make_unique([Obj("a", "b"), Obj("a", "c")], lambda o: o.prop1) == [Obj("a", "b")]
|
||||
|
||||
|
||||
@pytest.mark.parametrize("expression, bag, expected", [
|
||||
("", {}, None),
|
||||
(None, {}, None),
|
||||
("a", {"a": 1}, 1),
|
||||
("a.x", {"a.x": 1}, 1),
|
||||
("a.prop1", {"a": Obj("prop1", "prop2")}, "prop1"),
|
||||
("a.prop1.prop2.prop1", {"a": Obj2(Obj2("prop11", Obj2("prop121", "prop122")), "2")}, "prop121"),
|
||||
("a.prop1.prop2.prop1", {"a": Obj2(Obj2("prop11", None), "2")}, None),
|
||||
("a[1]", {"a": ['lst-first', 'lst-second']}, 'lst-second'),
|
||||
("a['bar']", {"a": {'foo': 'dict-first', 'bar': 'dict-second'}}, 'dict-second'),
|
||||
("a.prop1[0]", {"a": Obj2(['lst-first', 'lst-second'], None)}, 'lst-first'),
|
||||
("a.prop2['bar']", {"a": Obj2(None, {'foo': 'dict-first', 'bar': 'dict-second'})}, 'dict-second'),
|
||||
("a.bar", {"a": {'foo': 'dict-first', 'bar': 'dict-second'}}, 'dict-second'),
|
||||
("a.prop2.bar", {"a": Obj2(None, {'foo': 'dict-first', 'bar': 'dict-second'})}, 'dict-second'),
|
||||
])
|
||||
def test_i_can_evaluate_expression(expression, bag, expected):
|
||||
assert core.utils.evaluate_expression(expression, bag) == expected
|
||||
|
||||
|
||||
@pytest.mark.parametrize("expression, bag, expected_error, prop_name", [
|
||||
("a", {}, NameError, "a"),
|
||||
("a.prop3", {"a": Obj("prop1", "prop2")}, NameError, "prop3"),
|
||||
])
|
||||
def test_i_cannot_evaluate_expression(expression, bag, expected_error, prop_name):
|
||||
with pytest.raises(expected_error) as e:
|
||||
core.utils.evaluate_expression(expression, bag)
|
||||
|
||||
assert e.value.args == (prop_name,)
|
||||
|
||||
|
||||
@pytest.mark.parametrize("text, expected_text", [
|
||||
("hello world", "hello world"),
|
||||
("'hello' 'world'", "'hello' 'world'"),
|
||||
("def concept a from", "def concept a from"),
|
||||
("()[]{}1=1.5+-/*><&é", "()[]{}1=1.5+-/*><&é"),
|
||||
("execute(c:concept_name:)", "execute(c:concept_name:)")
|
||||
|
||||
])
|
||||
def test_i_can_get_text_from_tokens(text, expected_text):
|
||||
tokens = list(Tokenizer(text))
|
||||
assert core.utils.get_text_from_tokens(tokens) == expected_text
|
||||
|
||||
|
||||
@pytest.mark.parametrize("text, custom, expected_text", [
|
||||
("execute(c:concept_name:)", {TokenKind.CONCEPT: lambda t: f"__C__{t.value[0]}"}, "execute(__C__concept_name)")
|
||||
])
|
||||
def test_i_can_get_text_from_tokens_with_custom_switcher(text, custom, expected_text):
|
||||
tokens = list(Tokenizer(text))
|
||||
assert core.utils.get_text_from_tokens(tokens, custom) == expected_text
|
||||
|
||||
Reference in New Issue
Block a user