First implementation of questions management
This commit is contained in:
+11
-2
@@ -15,9 +15,9 @@ class BaseTest:
|
||||
def get_context(self, sheerka=None, eval_body=False, eval_where=False):
|
||||
context = ExecutionContext("test", Event(), sheerka or self.get_sheerka(), BuiltinConcepts.TESTING, None)
|
||||
if eval_body:
|
||||
context.local_hints.add(BuiltinConcepts.EVAL_BODY_REQUESTED)
|
||||
context.protected_hints.add(BuiltinConcepts.EVAL_BODY_REQUESTED)
|
||||
if eval_where:
|
||||
context.local_hints.add(BuiltinConcepts.EVAL_WHERE_REQUESTED)
|
||||
context.protected_hints.add(BuiltinConcepts.EVAL_WHERE_REQUESTED)
|
||||
|
||||
return context
|
||||
|
||||
@@ -78,6 +78,15 @@ class BaseTest:
|
||||
|
||||
return sheerka, context, *result
|
||||
|
||||
@staticmethod
|
||||
def get_concept_instance(sheerka, concept, **kwargs):
|
||||
instance = sheerka.new(concept.key if isinstance(concept, Concept) else concept)
|
||||
for i, var in enumerate(instance.metadata.variables):
|
||||
if var[0] in kwargs:
|
||||
instance.metadata.variables[i] = (var[0], kwargs[var[0]])
|
||||
|
||||
return instance
|
||||
|
||||
@staticmethod
|
||||
def retval(obj, who="who", status=True):
|
||||
"""ret_val"""
|
||||
|
||||
@@ -35,7 +35,7 @@ def test_i_can_push():
|
||||
concepts={"bar": Concept("bar")})
|
||||
a.preprocess = set()
|
||||
a.preprocess.add("preprocess")
|
||||
a.local_hints.add(BuiltinConcepts.EVAL_BODY_REQUESTED)
|
||||
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")
|
||||
@@ -54,7 +54,7 @@ def test_i_can_push():
|
||||
assert b.id == a.id + 1
|
||||
assert b._tab == a._tab + " "
|
||||
assert b.preprocess == a.preprocess
|
||||
assert b.local_hints == {BuiltinConcepts.EVAL_BODY_REQUESTED}
|
||||
assert b.protected_hints == {BuiltinConcepts.EVAL_BODY_REQUESTED}
|
||||
assert b.global_hints == a.global_hints
|
||||
|
||||
|
||||
@@ -64,10 +64,10 @@ def test_children_i_created_when_i_push():
|
||||
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")
|
||||
|
||||
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")
|
||||
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")
|
||||
|
||||
|
||||
def test_i_can_add_variable_when_i_push():
|
||||
@@ -81,17 +81,17 @@ def test_i_can_add_variable_when_i_push():
|
||||
|
||||
def test_local_hints_are_local_and_global_hints_are_global():
|
||||
a = ExecutionContext("foo", Event("event_1"), "fake_sheerka", BuiltinConcepts.NOP, None)
|
||||
a.local_hints.add("local hint 1")
|
||||
a.protected_hints.add("local hint 1")
|
||||
a.global_hints.add("global hint 1")
|
||||
|
||||
b = a.push(BuiltinConcepts.NOP, None)
|
||||
b.local_hints.add("local hint 2")
|
||||
b.protected_hints.add("local hint 2")
|
||||
b.global_hints.add("global hint 2")
|
||||
|
||||
assert a.local_hints == {"local hint 1"}
|
||||
assert a.protected_hints == {"local hint 1"}
|
||||
assert a.global_hints == {"global hint 1", "global hint 2"}
|
||||
|
||||
assert b.local_hints == {"local hint 1", "local hint 2"}
|
||||
assert b.protected_hints == {"local hint 1", "local hint 2"}
|
||||
assert b.global_hints == {"global hint 1", "global hint 2"}
|
||||
|
||||
|
||||
|
||||
@@ -284,6 +284,49 @@ class TestSheerkaEvaluateConcept(TestUsingMemoryBasedSheerka):
|
||||
evaluated = sheerka.evaluate_concept(self.get_context(sheerka, True), concept)
|
||||
assert evaluated.get_value("prop") == 2
|
||||
|
||||
def test_i_can_evaluate_when_body_is_a_concept_with_its_own_variables(self):
|
||||
sheerka, context, plus, add = self.init_concepts(
|
||||
Concept("a plus b", body="a + b").def_var("a").def_var("b"),
|
||||
Concept("add a b", body="a plus b").def_var("a").def_var("b"),
|
||||
eval_body=True)
|
||||
|
||||
add_instance = self.get_concept_instance(sheerka, add, a="1", b="2")
|
||||
|
||||
evaluated = sheerka.evaluate_concept(context, add_instance)
|
||||
|
||||
assert evaluated.key == add_instance.key
|
||||
assert evaluated.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):
|
||||
sheerka, context, plus, add = self.init_concepts(
|
||||
Concept("a plus b", body="a + b").def_var("a").def_var("b"),
|
||||
Concept("add x y", body="x plus y").def_var("x").def_var("y"),
|
||||
eval_body=True)
|
||||
|
||||
add_instance = self.get_concept_instance(sheerka, add, x="1", y="2")
|
||||
|
||||
evaluated = sheerka.evaluate_concept(context, add_instance)
|
||||
|
||||
assert evaluated.key == add_instance.key
|
||||
assert evaluated.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):
|
||||
sheerka, context, plus, add, inc = self.init_concepts(
|
||||
Concept("a plus b", body="a + b").def_var("a").def_var("b"),
|
||||
Concept("add x y", body="x plus y").def_var("x").def_var("y"),
|
||||
Concept("inc number", body="add number 1").def_var("number"),
|
||||
eval_body=True)
|
||||
|
||||
inc_instance = self.get_concept_instance(sheerka, inc, number="1")
|
||||
|
||||
evaluated = sheerka.evaluate_concept(context, inc_instance)
|
||||
|
||||
assert evaluated.key == inc_instance.key
|
||||
assert evaluated.metadata.is_evaluated
|
||||
assert sheerka.objvalue(evaluated) == 2
|
||||
|
||||
def test_i_can_reference_sheerka(self):
|
||||
sheerka = self.get_sheerka()
|
||||
|
||||
@@ -354,21 +397,24 @@ class TestSheerkaEvaluateConcept(TestUsingMemoryBasedSheerka):
|
||||
|
||||
assert evaluated.key == concept.init_key().key
|
||||
|
||||
@pytest.mark.parametrize("where_clause, expected, expected_body", [
|
||||
("True", True, BuiltinConcepts.NOT_INITIALIZED),
|
||||
("False", False, BuiltinConcepts.NOT_INITIALIZED),
|
||||
("self < 10", False, 10),
|
||||
("self < 11", True, 10),
|
||||
("a < 20", False, BuiltinConcepts.NOT_INITIALIZED),
|
||||
("a > 19", True, BuiltinConcepts.NOT_INITIALIZED),
|
||||
("a + self > 20", True, 10),
|
||||
@pytest.mark.parametrize("where_clause, expected, expected_prop, expected_body", [
|
||||
("True", True, None, BuiltinConcepts.NOT_INITIALIZED),
|
||||
("False", False, ConceptParts.WHERE, BuiltinConcepts.NOT_INITIALIZED),
|
||||
("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 + self > 20", True, None, 10),
|
||||
("a + self < 20", False, ConceptParts.WHERE, 10),
|
||||
])
|
||||
def test_i_can_evaluate_simple_where(self, where_clause, expected, expected_body):
|
||||
def test_i_can_evaluate_simple_where(self, where_clause, expected, expected_prop, expected_body):
|
||||
# We check that the WHERE condition is correctly evaluated
|
||||
# We also check that the body is evaluated only when it's mandatory
|
||||
|
||||
sheerka, context, concept = self.init_concepts(
|
||||
Concept("foo", body="10", where=where_clause).def_var("a", "20"),
|
||||
eval_body=False, # to check when the evaluation is forced
|
||||
eval_where=True,
|
||||
)
|
||||
|
||||
evaluated = sheerka.evaluate_concept(self.get_context(sheerka, False, True), concept, eval_body=False)
|
||||
@@ -380,7 +426,7 @@ class TestSheerkaEvaluateConcept(TestUsingMemoryBasedSheerka):
|
||||
assert sheerka.isinstance(evaluated, BuiltinConcepts.CONDITION_FAILED)
|
||||
assert evaluated.body == where_clause
|
||||
assert evaluated.concept == concept
|
||||
assert evaluated.prop == ConceptParts.WHERE
|
||||
assert evaluated.prop == expected_prop
|
||||
assert concept.body == expected_body
|
||||
|
||||
def test_i_can_evaluate_where_when_using_other_concept(self):
|
||||
@@ -402,6 +448,116 @@ class TestSheerkaEvaluateConcept(TestUsingMemoryBasedSheerka):
|
||||
evaluated = sheerka.evaluate_concept(self.get_context(sheerka, False, False), concept)
|
||||
assert evaluated.key == concept.key
|
||||
|
||||
def test_i_can_apply_intermediate_where_condition_using_python(self):
|
||||
sheerka, context, one_1, one_str, plus = self.init_concepts(
|
||||
Concept("one", body="1"),
|
||||
Concept("one", body="'one'"),
|
||||
Concept("a plus b", body="a + b", where="isinstance(a, int)").def_var("a", "one").def_var("b", "2"),
|
||||
eval_body=True,
|
||||
eval_where=True,
|
||||
)
|
||||
|
||||
evaluated = sheerka.evaluate_concept(context, plus)
|
||||
assert evaluated.key == plus.key
|
||||
assert evaluated.body == 3
|
||||
|
||||
def test_i_can_apply_intermediate_where_condition_when_multiple_variables_using_python(self):
|
||||
sheerka, context, one_1, one_str, two_2, two_str, plus = self.init_concepts(
|
||||
Concept("one", body="1"),
|
||||
Concept("one", body="'one'"),
|
||||
Concept("two", body="2"),
|
||||
Concept("two", body="'two'"),
|
||||
Concept("a plus b",
|
||||
body="a + b",
|
||||
where="isinstance(a, int) and isinstance(b, int)").def_var("a", "one").def_var("b", "two"),
|
||||
eval_body=True,
|
||||
eval_where=True,
|
||||
)
|
||||
|
||||
evaluated = sheerka.evaluate_concept(context, plus)
|
||||
assert evaluated.key == plus.key
|
||||
assert evaluated.body == 3
|
||||
|
||||
def test_i_can_apply_intermediate_where_condition_using_other_concepts(self):
|
||||
sheerka, context, one_1, one_str, is_an_int, plus = self.init_concepts(
|
||||
Concept("one", body="1"),
|
||||
Concept("one", body="'one'"),
|
||||
Concept("x is an int", body="isinstance(x, int)").def_var("x"),
|
||||
Concept("a plus b", body="a + b", where="a is an int").def_var("a", "one").def_var("b", "2"),
|
||||
eval_body=True,
|
||||
eval_where=True,
|
||||
)
|
||||
|
||||
evaluated = sheerka.evaluate_concept(context, plus)
|
||||
assert evaluated.key == plus.key
|
||||
assert evaluated.body == 3
|
||||
|
||||
def test_i_can_apply_intermediate_where_condition_when_multiple_levels(self):
|
||||
sheerka, context, one_1, one_str, is_an_int, is_an_integer, plus = self.init_concepts(
|
||||
Concept("one", body="1"),
|
||||
Concept("one", body="'one'"),
|
||||
Concept("x is an int", body="isinstance(x, int)").def_var("x"),
|
||||
Concept("y is an integer", body="y is an int").def_var("y"),
|
||||
Concept("a plus b", body="a + b", where="a is an integer").def_var("a", "one").def_var("b", "2"),
|
||||
eval_body=True,
|
||||
eval_where=True,
|
||||
)
|
||||
|
||||
evaluated = sheerka.evaluate_concept(context, plus)
|
||||
assert evaluated.key == plus.key
|
||||
assert evaluated.body == 3
|
||||
|
||||
def test_i_can_apply_intermediate_where_condition_choosing_the_correct_where_concept(self):
|
||||
# in this test, there are two where conditions with the same name
|
||||
# We need to use the 'PRE' condition to select the correct one
|
||||
sheerka, context, one_1, one_str, is_an_int, is_an_integer, plus = self.init_concepts(
|
||||
Concept("one", body="1"),
|
||||
Concept("one", body="'one'"),
|
||||
Concept("x is an int",
|
||||
body="isinstance(x, int)",
|
||||
pre="in_context(BuiltinConcepts.EVAL_QUESTION_REQUESTED)").def_var("x"),
|
||||
Concept("x is an int", body="False").def_var("x"),
|
||||
Concept("a plus b", body="a + b", where="a is an int").def_var("a", "one").def_var("b", "2"),
|
||||
eval_body=True,
|
||||
eval_where=True,
|
||||
)
|
||||
|
||||
evaluated = sheerka.evaluate_concept(context, plus)
|
||||
assert evaluated.key == plus.key
|
||||
assert evaluated.body == 3
|
||||
|
||||
@pytest.mark.skip("Not ready for that")
|
||||
def test_i_can_apply_intermediate_where_condition_when_multiple_variables(self):
|
||||
sheerka, context, one_1, one_str, two_2, two_str, is_an_int, plus = self.init_concepts(
|
||||
Concept("one", body="1"),
|
||||
Concept("one", body="'one'"),
|
||||
Concept("two", body="2"),
|
||||
Concept("two", body="'two'"),
|
||||
Concept("x is an int", body="isinstance(x, int)").def_var("x"),
|
||||
Concept("a plus b",
|
||||
body="a + b",
|
||||
where="a is an int and isinstance(b, int)").def_var("a", "one").def_var("b", "two"),
|
||||
eval_body=True,
|
||||
eval_where=True,
|
||||
)
|
||||
|
||||
evaluated = sheerka.evaluate_concept(context, plus)
|
||||
assert evaluated.key == plus.key
|
||||
assert evaluated.body == 3
|
||||
|
||||
def test_i_cannot_evaluate_when_intermediate_where_condition_fails(self):
|
||||
sheerka, context, one_1, is_an_int, plus = self.init_concepts(
|
||||
Concept("one", body="'one'"),
|
||||
Concept("x is an int", body="isinstance(x, int)").def_var("x"),
|
||||
Concept("a plus b", body="a + b", where="a is an int").def_var("a", "one").def_var("b", "2"),
|
||||
eval_body=True,
|
||||
eval_where=True,
|
||||
)
|
||||
|
||||
evaluated = sheerka.evaluate_concept(context, plus)
|
||||
assert evaluated.key == BuiltinConcepts.CONDITION_FAILED
|
||||
assert evaluated.body == "a is an int"
|
||||
|
||||
def test_i_can_enable_disable_where_clause_evaluation(self):
|
||||
sheerka, context, concept = self.init_concepts(
|
||||
Concept("foo", body="10", where="a > 10").def_var("a", None),
|
||||
@@ -409,7 +565,7 @@ class TestSheerkaEvaluateConcept(TestUsingMemoryBasedSheerka):
|
||||
evaluated = sheerka.evaluate_concept(context, concept)
|
||||
assert evaluated.key == concept.key
|
||||
|
||||
context.local_hints.add(BuiltinConcepts.EVAL_WHERE_REQUESTED)
|
||||
context.protected_hints.add(BuiltinConcepts.EVAL_WHERE_REQUESTED)
|
||||
evaluated = sheerka.evaluate_concept(context, concept)
|
||||
assert sheerka.isinstance(evaluated, BuiltinConcepts.CONCEPT_EVAL_ERROR)
|
||||
|
||||
@@ -495,6 +651,16 @@ class TestSheerkaEvaluateConcept(TestUsingMemoryBasedSheerka):
|
||||
assert sheerka.isinstance(evaluated, BuiltinConcepts.CHICKEN_AND_EGG)
|
||||
assert evaluated.body == {foo}
|
||||
|
||||
# def test_i_can_detect_auto_recursion_when_evaluating_another_concept(self):
|
||||
# sheerka, context, one_1, one_str, plus = self.init_concepts(
|
||||
# Concept("one", body="1"),
|
||||
# Concept("one", body="one"),
|
||||
# Concept("a plus b", body="a + b", where="isinstance(a, int)").def_var("a", "one").def_var("b", "2")
|
||||
# )
|
||||
#
|
||||
# evaluated = sheerka.evaluate_concept(context, plus, eval_body=True)
|
||||
# sheerka.isinstance(evaluated, BuiltinConcepts.CHICKEN_AND_EGG)
|
||||
|
||||
def test_i_can_manage_auto_recursion_when_constant(self):
|
||||
sheerka = self.get_sheerka()
|
||||
|
||||
@@ -566,7 +732,7 @@ class TestSheerkaEvaluateConcept(TestUsingMemoryBasedSheerka):
|
||||
assert captured.out == ""
|
||||
|
||||
def test_python_builtin_function_are_forbidden_in_where_pre_post_ret(self, capsys):
|
||||
# I do the test only for PRE, as it will be the same for the other CounceptPart
|
||||
# I do the test only for PRE, as it will be the same for the other ConceptPart
|
||||
sheerka, context, foo, bar = self.init_concepts(
|
||||
Concept("foo", body="print('10')"), # print will be executed
|
||||
Concept("bar", pre="print('10')"), # print won't be executed
|
||||
@@ -658,8 +824,8 @@ class TestSheerkaEvaluateConcept(TestUsingMemoryBasedSheerka):
|
||||
sheerka, context, concept = self.init_concepts(
|
||||
Concept("foo", pre="'pre'", post="'post'", ret="'ret'", where="'where'", body="'body'").def_var("a", "'a'")
|
||||
)
|
||||
context.local_hints.add(BuiltinConcepts.EVAL_WHERE_REQUESTED) # to prove that we do not care
|
||||
context.local_hints.add(BuiltinConcepts.EVAL_BODY_REQUESTED) # to prove that we do not care
|
||||
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')}
|
||||
|
||||
@@ -197,11 +197,11 @@ class TestSheerkaFilter(TestUsingMemoryBasedSheerka):
|
||||
assert len(res) == 2
|
||||
format_instructions = res[0].get_prop(BuiltinConcepts.FORMAT_INSTRUCTIONS)
|
||||
assert isinstance(format_instructions, FormatInstructions)
|
||||
assert format_instructions.recursive_props["children"] == 10
|
||||
assert format_instructions.recursive_props["_children"] == 10
|
||||
|
||||
format_instructions = res[1].get_prop(BuiltinConcepts.FORMAT_INSTRUCTIONS)
|
||||
assert isinstance(format_instructions, FormatInstructions)
|
||||
assert format_instructions.recursive_props["children"] == 10
|
||||
assert format_instructions.recursive_props["_children"] == 10
|
||||
|
||||
res = lst | Pipe(SheerkaFilter.pipe_recurse)(15, "other_prop")
|
||||
res = list(res)
|
||||
@@ -209,7 +209,7 @@ class TestSheerkaFilter(TestUsingMemoryBasedSheerka):
|
||||
assert len(res) == 2
|
||||
format_instructions = res[0].get_prop(BuiltinConcepts.FORMAT_INSTRUCTIONS)
|
||||
assert isinstance(format_instructions, FormatInstructions)
|
||||
assert format_instructions.recursive_props["children"] == 10
|
||||
assert format_instructions.recursive_props["_children"] == 10
|
||||
assert format_instructions.recursive_props["other_prop"] == 15
|
||||
|
||||
def test_i_can_inspect_obj(self):
|
||||
|
||||
@@ -0,0 +1,52 @@
|
||||
from core.builtin_concepts import BuiltinConcepts
|
||||
from core.concept import Concept
|
||||
from core.sheerka.ExecutionContext import ExecutionContext
|
||||
from core.sheerka.services.SheerkaShortTermMemory import SheerkaShortTermMemory
|
||||
|
||||
from tests.TestUsingMemoryBasedSheerka import TestUsingMemoryBasedSheerka
|
||||
|
||||
|
||||
class TestSheerkaShortTermMemory(TestUsingMemoryBasedSheerka):
|
||||
def test_i_can_add_to_global_short_term_memory(self):
|
||||
sheerka = self.get_sheerka()
|
||||
service = sheerka.services[SheerkaShortTermMemory.NAME]
|
||||
|
||||
foo = Concept("foo")
|
||||
sheerka.add_to_short_term_memory(None, "a", foo)
|
||||
|
||||
assert service.objects.copy() == {":a": foo}
|
||||
assert id(sheerka.get_from_short_term_memory(None, "a")) == id(foo)
|
||||
|
||||
def test_i_can_add_context_short_term_memory(self):
|
||||
sheerka, context = self.init_concepts()
|
||||
service = sheerka.services[SheerkaShortTermMemory.NAME]
|
||||
|
||||
foo = Concept("foo")
|
||||
sheerka.add_to_short_term_memory(context, "a", foo)
|
||||
|
||||
context_id = ExecutionContext.ids[context.event.get_digest()]
|
||||
assert service.objects.copy() == {f"{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_get_obj_from_parents(self):
|
||||
sheerka, context = self.init_concepts()
|
||||
service = sheerka.services[SheerkaShortTermMemory.NAME]
|
||||
foo = Concept("foo")
|
||||
sheerka.add_to_short_term_memory(None, "a", foo)
|
||||
|
||||
with context.push(BuiltinConcepts.TESTING, None) as sub_context:
|
||||
assert service.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):
|
||||
sheerka, context = self.init_concepts()
|
||||
|
||||
with context.push(BuiltinConcepts.TESTING, None) as sub_context:
|
||||
foo = Concept("foo")
|
||||
sheerka.add_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
|
||||
+11
-10
@@ -242,16 +242,17 @@ 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"),
|
||||
(Concept("name", body=Concept("foo")), False, Concept("foo")),
|
||||
|
||||
@@ -210,7 +210,7 @@ class EvaluatorAllSuppressEntries(EvaluatorAllWithPriority):
|
||||
return context.sheerka.ret(
|
||||
self.name,
|
||||
True,
|
||||
[],
|
||||
BuiltinConcepts.NO_RESULT,
|
||||
parents=to_remove)
|
||||
|
||||
|
||||
|
||||
@@ -114,6 +114,21 @@ class TestAddConceptEvaluator(TestUsingMemoryBasedSheerka):
|
||||
assert created_concept.metadata.definition == "hello a"
|
||||
assert created_concept.metadata.definition_type == "bnf"
|
||||
|
||||
def test_i_can_add_concept_with_the_correct_variables_when_referencing_other_concepts(self):
|
||||
context = self.get_context()
|
||||
def_concept_return_value = self.get_def_concept(
|
||||
name="x plus y",
|
||||
where=self.pretval(Concept("u is a v").def_var("u").def_var("v"), source="x is a number"),
|
||||
body=self.pretval(Concept("add a b").def_var("a").def_var("b"), source="add x y"),)
|
||||
|
||||
evaluated = AddConceptEvaluator().eval(context, def_concept_return_value)
|
||||
|
||||
assert evaluated.status
|
||||
assert context.sheerka.isinstance(evaluated.body, BuiltinConcepts.NEW_CONCEPT)
|
||||
|
||||
created_concept = evaluated.body.body
|
||||
assert created_concept.metadata.variables == [("x", None), ("y", None)]
|
||||
|
||||
def test_that_the_source_is_correctly_set_for_concept_with_simple_definition(self):
|
||||
context = self.get_context()
|
||||
def_concept_return_value = self.get_def_concept(
|
||||
@@ -195,14 +210,6 @@ class TestAddConceptEvaluator(TestUsingMemoryBasedSheerka):
|
||||
|
||||
assert AddConceptEvaluator.get_variables(context.sheerka, ret_val, ["a"]) == []
|
||||
|
||||
def test_i_can_get_variables_from_another_concept(self):
|
||||
concept = Concept("hello").def_var("a").def_var("b")
|
||||
ret_val = ReturnValueConcept(who="some_parser",
|
||||
status=True,
|
||||
value=ParserResultConcept(value=concept))
|
||||
|
||||
assert AddConceptEvaluator.get_variables(self.get_sheerka(), ret_val, []) == {"a", "b"}
|
||||
|
||||
def test_i_can_get_variables_from_definition(self):
|
||||
parsing_expression = Sequence(ConceptExpression('mult'),
|
||||
ZeroOrMore(Sequence(StrMatch("+"), ConceptExpression("add"))))
|
||||
|
||||
@@ -20,7 +20,7 @@ class TestAddConceptEvaluator(TestUsingMemoryBasedSheerka):
|
||||
|
||||
def test_i_can_evaluate_concept(self):
|
||||
context = self.get_context()
|
||||
context.local_hints.update({BuiltinConcepts.EVAL_BODY_REQUESTED, BuiltinConcepts.EVAL_WHERE_REQUESTED})
|
||||
context.protected_hints.update({BuiltinConcepts.EVAL_BODY_REQUESTED, BuiltinConcepts.EVAL_WHERE_REQUESTED})
|
||||
concept = Concept(name="foo",
|
||||
where="True",
|
||||
pre="2 > 1",
|
||||
@@ -45,7 +45,7 @@ class TestAddConceptEvaluator(TestUsingMemoryBasedSheerka):
|
||||
|
||||
def test_body_is_returned_when_defined_and_requested(self):
|
||||
context = self.get_context()
|
||||
context.local_hints.add(BuiltinConcepts.EVAL_BODY_REQUESTED)
|
||||
context.protected_hints.add(BuiltinConcepts.EVAL_BODY_REQUESTED)
|
||||
concept = Concept(name="foo",
|
||||
body="'I have a value'",
|
||||
where="True",
|
||||
@@ -94,7 +94,7 @@ class TestAddConceptEvaluator(TestUsingMemoryBasedSheerka):
|
||||
|
||||
def test_i_cannot_recognize_a_concept_if_one_of_the_prop_is_unknown(self):
|
||||
context = self.get_context()
|
||||
context.local_hints.add(BuiltinConcepts.EVAL_BODY_REQUESTED)
|
||||
context.protected_hints.add(BuiltinConcepts.EVAL_BODY_REQUESTED)
|
||||
context.sheerka.add_in_cache(Concept(name="one").init_key())
|
||||
concept_plus = context.sheerka.add_in_cache(Concept(name="a plus b")
|
||||
.def_var("a", "one")
|
||||
|
||||
@@ -2,7 +2,7 @@ import pytest
|
||||
from core.builtin_concepts import ReturnValueConcept, BuiltinConcepts
|
||||
from core.concept import Concept
|
||||
from core.sheerka.services.SheerkaSetsManager import SheerkaSetsManager
|
||||
from evaluators.EvalEvaluator import EvalEvaluator
|
||||
from evaluators.ReturnBodyEvaluator import ReturnBodyEvaluator
|
||||
|
||||
from tests.TestUsingMemoryBasedSheerka import TestUsingMemoryBasedSheerka
|
||||
|
||||
@@ -15,7 +15,7 @@ def retval(obj, who="who", status=True):
|
||||
class TestEvalEvaluator(TestUsingMemoryBasedSheerka):
|
||||
def test_i_can_match_and_eval(self):
|
||||
context = self.get_context()
|
||||
context.global_hints.add(BuiltinConcepts.RETURN_VALUE_REQUESTED)
|
||||
context.global_hints.add(BuiltinConcepts.RETURN_BODY_REQUESTED)
|
||||
|
||||
to_eval1 = ReturnValueConcept("some_name", True, Concept(name="2", body="to eval").auto_init())
|
||||
to_eval2 = ReturnValueConcept("some_name", True, Concept(name="3", body="also to eval").auto_init())
|
||||
@@ -28,7 +28,7 @@ class TestEvalEvaluator(TestUsingMemoryBasedSheerka):
|
||||
to_eval2,
|
||||
]
|
||||
|
||||
evaluator = EvalEvaluator()
|
||||
evaluator = ReturnBodyEvaluator()
|
||||
assert evaluator.matches(context, return_values)
|
||||
|
||||
evaluated = evaluator.eval(context, return_values)
|
||||
@@ -47,16 +47,16 @@ class TestEvalEvaluator(TestUsingMemoryBasedSheerka):
|
||||
])
|
||||
def test_i_cannot_match_if_eval_request_is_not_present(self, return_value):
|
||||
context = self.get_context()
|
||||
assert not EvalEvaluator().matches(context, [return_value])
|
||||
assert not ReturnBodyEvaluator().matches(context, [return_value])
|
||||
|
||||
context.global_hints.add(BuiltinConcepts.RETURN_VALUE_REQUESTED)
|
||||
assert EvalEvaluator().matches(context, [return_value])
|
||||
context.global_hints.add(BuiltinConcepts.RETURN_BODY_REQUESTED)
|
||||
assert ReturnBodyEvaluator().matches(context, [return_value])
|
||||
|
||||
def test_i_can_match_depending_on_builtin_concept_processing(self):
|
||||
context = self.get_context()
|
||||
context.global_hints.add(BuiltinConcepts.RETURN_VALUE_REQUESTED)
|
||||
context.global_hints.add(BuiltinConcepts.RETURN_BODY_REQUESTED)
|
||||
return_values = [ReturnValueConcept("some_name", True, Concept(name="2", body="to eval").auto_init())]
|
||||
evaluator = EvalEvaluator()
|
||||
evaluator = ReturnBodyEvaluator()
|
||||
|
||||
# i match when no BuiltinConcepts.PROCESSING is found
|
||||
assert evaluator.matches(context, return_values)
|
||||
@@ -80,7 +80,7 @@ class TestEvalEvaluator(TestUsingMemoryBasedSheerka):
|
||||
ReturnValueConcept("some_name", False, Concept(name="1", body="not to eval")), # no evaluated body
|
||||
]
|
||||
|
||||
evaluated = EvalEvaluator().eval(context, return_values)
|
||||
evaluated = ReturnBodyEvaluator().eval(context, return_values)
|
||||
assert evaluated is None
|
||||
|
||||
def test_i_can_evaluate_sets(self):
|
||||
@@ -92,7 +92,7 @@ class TestEvalEvaluator(TestUsingMemoryBasedSheerka):
|
||||
sets_handler = sheerka.services[SheerkaSetsManager.NAME]
|
||||
sets_handler.add_concepts_to_set(context, [foo, bar, baz], number)
|
||||
|
||||
evaluated = EvalEvaluator().eval(context, [retval(number)])
|
||||
evaluated = ReturnBodyEvaluator().eval(context, [retval(number)])
|
||||
|
||||
assert len(evaluated) == 1
|
||||
assert evaluated[0].status
|
||||
|
||||
+7
-6
@@ -2,14 +2,14 @@ import pytest
|
||||
|
||||
from core.builtin_concepts import BuiltinConcepts, ReturnValueConcept, UserInputConcept
|
||||
from core.concept import Concept
|
||||
from evaluators.PrepareEvalEvaluator import PrepareEvalEvaluator
|
||||
from evaluators.PrepareEvalBodyEvaluator import PrepareEvalBodyEvaluator
|
||||
|
||||
from tests.TestUsingMemoryBasedSheerka import TestUsingMemoryBasedSheerka
|
||||
|
||||
r = ReturnValueConcept
|
||||
|
||||
|
||||
class TestPrepareEvalEvaluator(TestUsingMemoryBasedSheerka):
|
||||
class TestPrepareEvalBodyEvaluator(TestUsingMemoryBasedSheerka):
|
||||
|
||||
@pytest.mark.parametrize("ret_val, expected", [
|
||||
(r("name", True, UserInputConcept("eval 1 + 1")), True),
|
||||
@@ -26,7 +26,7 @@ class TestPrepareEvalEvaluator(TestUsingMemoryBasedSheerka):
|
||||
])
|
||||
def test_i_can_match(self, ret_val, expected):
|
||||
context = self.get_context()
|
||||
assert PrepareEvalEvaluator().matches(context, ret_val) == expected
|
||||
assert PrepareEvalBodyEvaluator().matches(context, ret_val) == expected
|
||||
|
||||
@pytest.mark.parametrize("ret_val, expected", [
|
||||
(r("name", True, UserInputConcept("eval 1 + 1")), "1 + 1"),
|
||||
@@ -36,7 +36,7 @@ class TestPrepareEvalEvaluator(TestUsingMemoryBasedSheerka):
|
||||
context = self.get_context()
|
||||
sheerka = context.sheerka
|
||||
|
||||
prepare_evaluator = PrepareEvalEvaluator()
|
||||
prepare_evaluator = PrepareEvalBodyEvaluator()
|
||||
prepare_evaluator.matches(context, ret_val)
|
||||
res = prepare_evaluator.eval(context, ret_val)
|
||||
|
||||
@@ -44,5 +44,6 @@ class TestPrepareEvalEvaluator(TestUsingMemoryBasedSheerka):
|
||||
assert sheerka.isinstance(res.body, BuiltinConcepts.USER_INPUT)
|
||||
assert res.body.body == expected
|
||||
|
||||
assert BuiltinConcepts.EVAL_BODY_REQUESTED in context.global_hints
|
||||
assert BuiltinConcepts.RETURN_VALUE_REQUESTED in context.global_hints
|
||||
assert BuiltinConcepts.EVAL_BODY_REQUESTED in context.protected_hints
|
||||
assert BuiltinConcepts.EVAL_WHERE_REQUESTED in context.protected_hints
|
||||
assert BuiltinConcepts.RETURN_BODY_REQUESTED in context.protected_hints
|
||||
@@ -0,0 +1,49 @@
|
||||
import pytest
|
||||
|
||||
from core.builtin_concepts import BuiltinConcepts, ReturnValueConcept, UserInputConcept
|
||||
from core.concept import Concept
|
||||
from evaluators.PrepareEvalQuestionEvaluator import PrepareEvalQuestionEvaluator
|
||||
|
||||
from tests.TestUsingMemoryBasedSheerka import TestUsingMemoryBasedSheerka
|
||||
|
||||
r = ReturnValueConcept
|
||||
|
||||
|
||||
class TestPrepareEvalQuestionEvaluator(TestUsingMemoryBasedSheerka):
|
||||
|
||||
@pytest.mark.parametrize("ret_val, expected", [
|
||||
(r("name", True, UserInputConcept("question(1 + 1)")), True),
|
||||
(r("name", True, UserInputConcept(" question(1 + 1) ")), True),
|
||||
(r("name", True, UserInputConcept("question()")), False),
|
||||
(r("name", True, UserInputConcept("1+1")), False),
|
||||
(r("name", True, UserInputConcept("")), False),
|
||||
(r("name", True, UserInputConcept("question(")), False),
|
||||
(r("name", True, UserInputConcept(")")), False),
|
||||
(r("name", True, UserInputConcept([])), False),
|
||||
(r("name", True, Concept("foo")), False),
|
||||
(r("name", True, "not a concept"), False),
|
||||
(r("name", False, UserInputConcept("question(1 + 1)")), False),
|
||||
])
|
||||
def test_i_can_match(self, ret_val, expected):
|
||||
context = self.get_context()
|
||||
assert PrepareEvalQuestionEvaluator().matches(context, ret_val) == expected
|
||||
|
||||
@pytest.mark.parametrize("ret_val, expected", [
|
||||
(r("name", True, UserInputConcept("question(1 + 1)")), "1 + 1"),
|
||||
(r("name", True, UserInputConcept(" question( 1 + 1 ) ")), "1 + 1"),
|
||||
])
|
||||
def test_i_can_eval(self, ret_val, expected):
|
||||
context = self.get_context()
|
||||
sheerka = context.sheerka
|
||||
|
||||
prepare_evaluator = PrepareEvalQuestionEvaluator()
|
||||
prepare_evaluator.matches(context, ret_val)
|
||||
res = prepare_evaluator.eval(context, ret_val)
|
||||
|
||||
assert res.status
|
||||
assert sheerka.isinstance(res.body, BuiltinConcepts.USER_INPUT)
|
||||
assert res.body.body == expected
|
||||
|
||||
assert BuiltinConcepts.EVAL_QUESTION_REQUESTED in context.protected_hints
|
||||
assert BuiltinConcepts.EVAL_BODY_REQUESTED in context.protected_hints
|
||||
assert BuiltinConcepts.RETURN_BODY_REQUESTED in context.protected_hints
|
||||
@@ -137,7 +137,7 @@ class TestPythonEvaluator(TestUsingMemoryBasedSheerka):
|
||||
assert evaluated.status
|
||||
assert not evaluated.value # the first test is between Concept(foo) and int(2)
|
||||
|
||||
context.local_hints.add(BuiltinConcepts.EVAL_UNTIL_SUCCESS_REQUESTED)
|
||||
context.protected_hints.add(BuiltinConcepts.EVAL_UNTIL_SUCCESS_REQUESTED)
|
||||
evaluated = python_evaluator.eval(context, parsed)
|
||||
assert evaluated.status
|
||||
assert evaluated.value # we test until we compare foo.body and 2
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
import pytest
|
||||
from core.builtin_concepts import BuiltinConcepts
|
||||
from core.concept import Concept
|
||||
from evaluators.ResolveAmbiguityEvaluator import ResolveAmbiguityEvaluator
|
||||
|
||||
@@ -67,8 +68,26 @@ class TestResolveAmbiguityEvaluator(TestUsingMemoryBasedSheerka):
|
||||
resolved = res[0]
|
||||
|
||||
assert resolved.who == evaluator.name
|
||||
assert resolved.body == []
|
||||
assert resolved.body == BuiltinConcepts.NO_RESULT
|
||||
assert resolved.parents == [
|
||||
return_values[0],
|
||||
return_values[1],
|
||||
]
|
||||
|
||||
def test_i_can_eval_all_pass(self):
|
||||
"""
|
||||
If they all pass, that means that no concept was reduced
|
||||
-> We need to act like resolve ambiguity was not called
|
||||
:return:
|
||||
"""
|
||||
context = self.get_context()
|
||||
return_values = [
|
||||
self.pretval(Concept("hello world 1"), "hello word"),
|
||||
self.pretval(Concept("hello world 2"), "hello word"),
|
||||
]
|
||||
|
||||
evaluator = ResolveAmbiguityEvaluator()
|
||||
evaluator.matches(context, return_values)
|
||||
res = evaluator.eval(context, return_values)
|
||||
|
||||
assert res is None
|
||||
|
||||
@@ -1015,6 +1015,82 @@ as:
|
||||
assert res[0].status
|
||||
assert res[0].body == "Executed !"
|
||||
|
||||
def test_i_can_manage_question(self):
|
||||
init = [
|
||||
"def concept one",
|
||||
"def concept foo",
|
||||
"def concept number",
|
||||
"one isa number",
|
||||
"def concept x is a y as isa(x,y) pre in_context(BuiltinConcepts.EVAL_QUESTION_REQUESTED)",
|
||||
"def concept x is a y as set_isa(x,y)",
|
||||
]
|
||||
|
||||
sheerka = self.init_scenario(init)
|
||||
res = sheerka.evaluate_user_input("question(one is a number)") # automatically evaluated
|
||||
assert len(res) == 1
|
||||
assert res[0].status
|
||||
assert res[0].body
|
||||
|
||||
res = sheerka.evaluate_user_input("question(foo is a number)") # automatically evaluated
|
||||
assert len(res) == 1
|
||||
assert res[0].status
|
||||
assert not res[0].body
|
||||
|
||||
def test_where_clause_implicitly_infer_to_question(self):
|
||||
init = [
|
||||
"def concept one as 1",
|
||||
"def concept number",
|
||||
"one isa number",
|
||||
"def concept one as 10", # to make sure that it won't be rejected because of the cast
|
||||
"def concept x is a y as isa(x,y) pre in_context(BuiltinConcepts.EVAL_QUESTION_REQUESTED)",
|
||||
"def concept x is a y as set_isa(x,y)",
|
||||
]
|
||||
|
||||
# Explanations
|
||||
# There are two concepts 'one'. The first one is tagged as a number while the second one is not
|
||||
# So the first one should be picked.
|
||||
# the second concept 'one' 's value is an integer, to make sure that it won't be rejected because of its type
|
||||
|
||||
sheerka = self.init_scenario(init)
|
||||
res = sheerka.evaluate_user_input("def concept x plus y where x is a number as x + y")
|
||||
assert len(res) == 1
|
||||
assert res[0].status
|
||||
assert sheerka.isinstance(res[0].body, BuiltinConcepts.NEW_CONCEPT)
|
||||
|
||||
# Let's check that the concept is correctly understood
|
||||
res = sheerka.evaluate_user_input("eval one plus 2")
|
||||
assert len(res) == 1
|
||||
assert res[0].status
|
||||
assert res[0].body == 3 # it means that the first 'one' was chosen
|
||||
|
||||
def test_i_can_manage_concept_that_refers_to_question(self):
|
||||
init = [
|
||||
"def concept one",
|
||||
"def concept foo",
|
||||
"def concept number",
|
||||
"one isa number",
|
||||
"def concept q from q ? as question(q)",
|
||||
"def concept is_a from x is a y as isa(x,y) pre in_context(BuiltinConcepts.EVAL_QUESTION_REQUESTED)",
|
||||
"set_is_greater_than(BuiltinConcepts.PRECEDENCE, c:is_a:, c:q:)"
|
||||
]
|
||||
|
||||
sheerka = self.init_scenario(init)
|
||||
res = sheerka.evaluate_user_input("one is a number ?") # automatically evaluated
|
||||
assert len(res) == 1
|
||||
assert res[0].status
|
||||
assert res[0].body
|
||||
|
||||
res = sheerka.evaluate_user_input("foo is a number ?") # automatically evaluated
|
||||
assert len(res) == 1
|
||||
assert res[0].status
|
||||
assert not res[0].body
|
||||
|
||||
# Sanity, when there is only one 'is a' concept. It's chosen regardless of the PRE condition
|
||||
res = sheerka.evaluate_user_input("one is a number")
|
||||
assert len(res) == 1
|
||||
assert res[0].status
|
||||
assert res[0].body
|
||||
|
||||
|
||||
class TestSheerkaNonRegFile(TestUsingFileBasedSheerka):
|
||||
def test_i_can_def_several_concepts(self):
|
||||
|
||||
@@ -3,7 +3,7 @@ from dataclasses import dataclass
|
||||
|
||||
import pytest
|
||||
from core.builtin_concepts import ParserResultConcept, BuiltinConcepts, ReturnValueConcept
|
||||
from core.concept import DEFINITION_TYPE_BNF, DEFINITION_TYPE_DEF
|
||||
from core.concept import DEFINITION_TYPE_BNF, DEFINITION_TYPE_DEF, Concept, CV
|
||||
from core.sheerka.services.SheerkaExecute import ParserInput
|
||||
from core.tokenizer import Keywords, Tokenizer, LexerError
|
||||
from parsers.BnfNodeParser import OrderedChoice, ConceptExpression, StrMatch
|
||||
@@ -87,9 +87,9 @@ class PN:
|
||||
class TestDefaultParser(TestUsingMemoryBasedSheerka):
|
||||
|
||||
def init_parser(self, *concepts):
|
||||
sheerka, concept, *updated = self.init_concepts(*concepts, singleton=True)
|
||||
sheerka, context, *updated = self.init_concepts(*concepts, singleton=True)
|
||||
parser = DefaultParser()
|
||||
return sheerka, concept, parser, *updated
|
||||
return sheerka, context, parser, *updated
|
||||
|
||||
@pytest.mark.parametrize("text, expected", [
|
||||
("def concept hello", get_def_concept(name="hello")),
|
||||
@@ -313,6 +313,38 @@ def concept add one to a as
|
||||
assert isinstance(res.value, ParserResultConcept)
|
||||
assert node == expected
|
||||
|
||||
def test_i_can_parse_when_ambiguity_in_where_pre_clause(self):
|
||||
sheerka, context, parser, *concepts = self.init_parser(
|
||||
Concept("x is a y", pre="in_context(BuiltinConcepts.EVAL_QUESTION_REQUESTED)"),
|
||||
Concept("x is a y")
|
||||
)
|
||||
|
||||
text = "def concept foo x y where x is a y"
|
||||
res = parser.parse(context, ParserInput(text))
|
||||
expected_body = self.pretval(CV(concepts[0], pre=True), source="x is a y", who="parsers.Default",
|
||||
parser="parsers.ExactConcept")
|
||||
expected = get_def_concept("foo x y", where=expected_body)
|
||||
node = res.value.value
|
||||
|
||||
assert res.status
|
||||
assert res.who == parser.name
|
||||
assert res.value.source == text
|
||||
assert isinstance(res.value, ParserResultConcept)
|
||||
assert node == expected
|
||||
|
||||
text = "def concept foo x y pre x is a y"
|
||||
res = parser.parse(context, ParserInput(text))
|
||||
expected_body = self.pretval(CV(concepts[0], pre=True), source="x is a y", who="parsers.Default",
|
||||
parser="parsers.ExactConcept")
|
||||
expected = get_def_concept("foo x y", pre=expected_body)
|
||||
node = res.value.value
|
||||
|
||||
assert res.status
|
||||
assert res.who == parser.name
|
||||
assert res.value.source == text
|
||||
assert isinstance(res.value, ParserResultConcept)
|
||||
assert node == expected
|
||||
|
||||
def test_i_can_detect_not_for_me(self):
|
||||
text = "hello world"
|
||||
sheerka, context, parser = self.init_parser()
|
||||
|
||||
@@ -1,9 +1,13 @@
|
||||
from dataclasses import dataclass
|
||||
|
||||
import pytest
|
||||
from core.builtin_concepts import BuiltinConcepts, ReturnValueConcept
|
||||
from core.concept import Concept
|
||||
from core.sheerka.services.SheerkaExecute import ParserInput
|
||||
from core.tokenizer import Tokenizer, TokenKind
|
||||
from parsers.BaseParser import UnexpectedEof, UnexpectedTokenErrorNode
|
||||
from parsers.ExpressionParser import PropertyEqualsNode, PropertyEqualsSequenceNode, PropertyContainsNode, AndNode, \
|
||||
OrNode, NotNode, LambdaNode, IsaNode
|
||||
OrNode, NotNode, LambdaNode, IsaNode, NameExprNode, ExpressionParser, LeftPartNotFoundError, TrueifyVisitor
|
||||
|
||||
from tests.TestUsingMemoryBasedSheerka import TestUsingMemoryBasedSheerka
|
||||
|
||||
@@ -16,8 +20,93 @@ class Obj:
|
||||
parent: object = None
|
||||
|
||||
|
||||
def n(value):
|
||||
return NameExprNode(Tokenizer(value, yield_eof=False))
|
||||
|
||||
|
||||
class TestExpressionParser(TestUsingMemoryBasedSheerka):
|
||||
|
||||
def init_parser(self):
|
||||
sheerka, context = self.init_concepts()
|
||||
parser = ExpressionParser()
|
||||
return sheerka, context, parser
|
||||
|
||||
@pytest.mark.parametrize("expression, expected", [
|
||||
("one complicated expression", n("one complicated expression")),
|
||||
("function_call(a,b,c)", n("function_call(a,b,c)")),
|
||||
("one expression or another expression", OrNode(n("one expression"), n("another expression"))),
|
||||
("one expression and another expression", AndNode(n("one expression"), n("another expression"))),
|
||||
("one or two or three", OrNode(n("one"), n("two"), n("three"))),
|
||||
("one and two and three", AndNode(n("one"), n("two"), n("three"))),
|
||||
("one or two and three", OrNode(n("one"), AndNode(n("two"), n("three")))),
|
||||
("one and two or three", OrNode(AndNode(n("one"), n("two")), n("three"))),
|
||||
("one and (two or three)", AndNode(n("one"), OrNode(n("two"), n("three")))),
|
||||
])
|
||||
def test_i_can_parse_expression(self, expression, expected):
|
||||
sheerka, context, parser = self.init_parser()
|
||||
|
||||
res = parser.parse(context, ParserInput(expression))
|
||||
wrapper = res.body
|
||||
expressions = res.body.body
|
||||
|
||||
assert res.status
|
||||
assert sheerka.isinstance(wrapper, BuiltinConcepts.PARSER_RESULT)
|
||||
assert expressions == expected
|
||||
|
||||
@pytest.mark.parametrize("expression, expected_errors", [
|
||||
("one or", [UnexpectedEof("When parsing 'or'")]),
|
||||
("one and", [UnexpectedEof("When parsing 'and'")]),
|
||||
("and one", [LeftPartNotFoundError()]),
|
||||
("or one", [LeftPartNotFoundError()]),
|
||||
("or", [LeftPartNotFoundError(), UnexpectedEof("When parsing 'or'")]),
|
||||
("and", [LeftPartNotFoundError(), UnexpectedEof("When parsing 'and'")]),
|
||||
])
|
||||
def test_i_can_detect_error(self, expression, expected_errors):
|
||||
sheerka, context, parser = self.init_parser()
|
||||
|
||||
res = parser.parse(context, ParserInput(expression))
|
||||
assert not res.status
|
||||
assert sheerka.isinstance(res.body, BuiltinConcepts.ERROR)
|
||||
assert res.body.body == expected_errors
|
||||
|
||||
def test_i_can_detect_unbalanced_parenthesis(self):
|
||||
sheerka, context, parser = self.init_parser()
|
||||
|
||||
res = parser.parse(context, ParserInput("("))
|
||||
assert not res.status
|
||||
assert sheerka.isinstance(res.body, BuiltinConcepts.ERROR)
|
||||
assert isinstance(res.body.body[0], UnexpectedTokenErrorNode)
|
||||
assert res.body.body[0].token.type == TokenKind.EOF
|
||||
assert res.body.body[0].expected_tokens == [TokenKind.RPAR]
|
||||
|
||||
res = parser.parse(context, ParserInput(")"))
|
||||
assert not res.status
|
||||
assert sheerka.isinstance(res.body, BuiltinConcepts.ERROR)
|
||||
assert isinstance(res.body.body[0], UnexpectedTokenErrorNode)
|
||||
assert res.body.body[0].token.type == TokenKind.RPAR
|
||||
assert res.body.body[0].expected_tokens == []
|
||||
|
||||
res = parser.parse(context, ParserInput("one and two)"))
|
||||
assert not res.status
|
||||
assert sheerka.isinstance(res.body, BuiltinConcepts.ERROR)
|
||||
assert isinstance(res.body.body[0], UnexpectedTokenErrorNode)
|
||||
assert res.body.body[0].token.type == TokenKind.RPAR
|
||||
assert res.body.body[0].expected_tokens == []
|
||||
|
||||
res = parser.parse(context, ParserInput("one and two)"))
|
||||
assert not res.status
|
||||
assert sheerka.isinstance(res.body, BuiltinConcepts.ERROR)
|
||||
assert isinstance(res.body.body[0], UnexpectedTokenErrorNode)
|
||||
assert res.body.body[0].token.type == TokenKind.RPAR
|
||||
assert res.body.body[0].expected_tokens == []
|
||||
|
||||
def test_i_can_detect_empty_expression(self):
|
||||
sheerka, context, parser = self.init_parser()
|
||||
res = parser.parse(context, ParserInput(""))
|
||||
|
||||
assert not res.status
|
||||
assert sheerka.isinstance(res.body, BuiltinConcepts.IS_EMPTY)
|
||||
|
||||
def test_i_can_test_property_equals(self):
|
||||
node = PropertyEqualsNode("prop_a", "good value")
|
||||
|
||||
@@ -101,3 +190,21 @@ class TestExpressionParser(TestUsingMemoryBasedSheerka):
|
||||
assert concept_node2.eval(Concept("foo").init_key())
|
||||
assert not concept_node2.eval(Obj)
|
||||
assert not concept_node2.eval(Concept())
|
||||
|
||||
@pytest.mark.parametrize("expression, to_trueify, to_skip, expected", [
|
||||
("a", ["b"], ["a"], "a"),
|
||||
("b", ["b"], ["a"], "True"),
|
||||
("a and b", ["b"], ["a"], "a and True"),
|
||||
("b or a", ["b"], ["a"], "True or a"),
|
||||
("isinstance(b, str)", ["b"], ["a"], "True"),
|
||||
("isinstance(b, str) or instance(a, str)", ["b"], ["a"], "True or instance(a, str)"),
|
||||
("a and b or c", ["b", "c"], ["a"], "a and True or True"),
|
||||
("a + b or a + c", ["b", "c"], ["a"], "a + b or a + c"),
|
||||
])
|
||||
def test_i_can_trueify(self, expression, to_trueify, to_skip, expected):
|
||||
sheerka, context, parser = self.init_parser()
|
||||
expr_node = parser.parse(context, ParserInput(expression)).body.body
|
||||
|
||||
translated_node = TrueifyVisitor(to_trueify, to_skip).visit(expr_node)
|
||||
|
||||
assert str(translated_node) == expected
|
||||
|
||||
@@ -0,0 +1,69 @@
|
||||
from core.builtin_concepts import BuiltinConcepts
|
||||
from core.concept import Concept
|
||||
from core.sheerka.services.SheerkaExecute import ParserInput
|
||||
from parsers.ShortTermMemoryParser import ShortTermMemoryParser
|
||||
|
||||
from tests.TestUsingMemoryBasedSheerka import TestUsingMemoryBasedSheerka
|
||||
|
||||
|
||||
class TestShortTermMemoryParser(TestUsingMemoryBasedSheerka):
|
||||
def init_parser(self):
|
||||
sheerka, context = self.init_concepts()
|
||||
parser = ShortTermMemoryParser()
|
||||
return sheerka, context, parser
|
||||
|
||||
def test_i_cannot_parse_empty_string(self):
|
||||
sheerka, context, parser = self.init_parser()
|
||||
|
||||
res = parser.parse(context, ParserInput(""))
|
||||
|
||||
assert not res.status
|
||||
assert sheerka.isinstance(res.body, BuiltinConcepts.IS_EMPTY)
|
||||
|
||||
def test_i_can_get_concept_from_sheerka(self):
|
||||
sheerka, context, parser = self.init_parser()
|
||||
foo = Concept("foo")
|
||||
|
||||
sheerka.add_to_short_term_memory(None, "test", foo)
|
||||
|
||||
res = parser.parse(context, ParserInput("test"))
|
||||
|
||||
assert res.status
|
||||
assert id(res.body) == id(foo)
|
||||
|
||||
def test_i_can_get_concept_from_the_context(self):
|
||||
sheerka, context, parser = self.init_parser()
|
||||
foo = Concept("foo")
|
||||
|
||||
sheerka.add_to_short_term_memory(context, "test", foo)
|
||||
|
||||
res = parser.parse(context, ParserInput("test"))
|
||||
|
||||
assert res.status
|
||||
assert id(res.body) == id(foo)
|
||||
|
||||
def test_i_can_get_concept_from_parent_context(self):
|
||||
sheerka, context, parser = self.init_parser()
|
||||
foo = Concept("foo")
|
||||
|
||||
sheerka.add_to_short_term_memory(context, "test", foo)
|
||||
|
||||
with context.push(BuiltinConcepts.TESTING, None) as sub_context:
|
||||
res = parser.parse(sub_context, ParserInput("test"))
|
||||
|
||||
assert res.status
|
||||
assert id(res.body) == id(foo)
|
||||
|
||||
def test_i_cannot_get_concept_when_no_concept_in_memory(self):
|
||||
sheerka, context, parser = self.init_parser()
|
||||
|
||||
res = parser.parse(context, ParserInput("test"))
|
||||
|
||||
assert not res.status
|
||||
assert sheerka.isinstance(res.body, BuiltinConcepts.NOT_FOUND)
|
||||
assert res.body.body == "test"
|
||||
|
||||
def test_parser_can_only_be_called_with_parser_input(self):
|
||||
sheerka, context, parser = self.init_parser()
|
||||
|
||||
assert parser.parse(context, "not_a_parser_input") is None
|
||||
@@ -279,14 +279,14 @@ class TestSheerkaPickleHandler(TestUsingMemoryBasedSheerka):
|
||||
|
||||
def test_i_can_encode_decode_execution_context(self):
|
||||
sheerka = self.get_sheerka()
|
||||
|
||||
context = ExecutionContext("who", Event("xxx"), sheerka, BuiltinConcepts.NOP, None, "my desc")
|
||||
c = Concept("foo").def_var("a")
|
||||
context = ExecutionContext("who", Event("xxx"), sheerka, BuiltinConcepts.EVALUATE_CONCEPT, c, "my desc")
|
||||
input_list = [ReturnValueConcept("who", True, 10), ReturnValueConcept("who2", False, 20)]
|
||||
context.inputs = {"a": input_list, "b": set_full_serialization(Concept("foo"))}
|
||||
context.values = {"c": input_list, "d": set_full_serialization(Concept("bar"))}
|
||||
context.obj = set_full_serialization(Concept("baz"))
|
||||
context.push(BuiltinConcepts.NOP, None, who="who3", desc="sub_child1")
|
||||
context.push(BuiltinConcepts.NOP, None, who="who4", desc="sub_child2")
|
||||
context.push(BuiltinConcepts.EVALUATING_CONCEPT, c, who="who3", desc="sub_child1")
|
||||
context.push(BuiltinConcepts.EVALUATING_ATTRIBUTE, "a", who="who4", desc="sub_child2")
|
||||
|
||||
to_string = sheerkapickle.encode(sheerka, context)
|
||||
decoded = sheerkapickle.decode(sheerka, to_string)
|
||||
|
||||
Reference in New Issue
Block a user