Fixed #29: Parsers: Implement parsing memoization
Fixed #77 : Parser: ShortTermMemoryParser should be called separately Fixed #78 : Remove VariableNode usage Fixed #79 : ConceptManager: Implement compile caching Fixed #80 : SheerkaExecute : parsers_key is not correctly computed Fixed #81 : ValidateConceptEvaluator : Validate concept's where and pre clauses right after the parsing Fixed #82 : SheerkaIsAManager: isa() failed when the set as a body Fixed #83 : ValidateConceptEvaluator : Support BNF and SYA Concepts Fixed #84 : ExpressionParser: Implement the parser as a standard parser Fixed #85 : Services: Give order to services Fixed #86 : cannot manage smart_get_attr(the short, color)
This commit is contained in:
@@ -47,6 +47,7 @@ class TestExecutionContext(TestUsingMemoryBasedSheerka):
|
||||
a.preprocess_evaluators = ["list of evaluators"]
|
||||
a.protected_hints.add(BuiltinConcepts.EVAL_BODY_REQUESTED)
|
||||
a.global_hints.add(BuiltinConcepts.EVAL_BODY_REQUESTED)
|
||||
a.possible_variables = {"a", "b", "c"}
|
||||
|
||||
b = a.push(BuiltinConcepts.EVALUATION, "sub action context", desc="sub description")
|
||||
|
||||
@@ -65,8 +66,9 @@ class TestExecutionContext(TestUsingMemoryBasedSheerka):
|
||||
assert b.preprocess_evaluators == a.preprocess_evaluators
|
||||
assert b.protected_hints == {BuiltinConcepts.EVAL_BODY_REQUESTED}
|
||||
assert b.global_hints == a.global_hints
|
||||
assert b.possible_variables == a.possible_variables
|
||||
|
||||
def test_children_i_created_when_i_push(self):
|
||||
def test_children_are_created_when_i_push(self):
|
||||
sheerka = self.get_sheerka()
|
||||
|
||||
e = ExecutionContext("who_", Event("event"), sheerka, BuiltinConcepts.NOP, None)
|
||||
@@ -75,19 +77,9 @@ class TestExecutionContext(TestUsingMemoryBasedSheerka):
|
||||
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")
|
||||
|
||||
# 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 (e._children[0].who, e._children[0].desc) == ("a", "I do something")
|
||||
assert (e._children[1].who, e._children[1].desc) == ("b", "oups! I did a again")
|
||||
assert (e._children[2].who, e._children[2].desc) == ("c", "I do something else")
|
||||
|
||||
def test_local_hints_are_local_and_global_hints_are_global(self):
|
||||
sheerka = self.get_sheerka()
|
||||
|
||||
@@ -5,7 +5,7 @@ from core.builtin_concepts import BuiltinConcepts
|
||||
from core.builtin_helpers import ensure_bnf
|
||||
from core.concept import PROPERTIES_TO_SERIALIZE, Concept, DEFINITION_TYPE_DEF, get_concept_attrs, \
|
||||
DEFINITION_TYPE_BNF
|
||||
from core.global_symbols import NotInit, NotFound, SyaAssociativity
|
||||
from core.global_symbols import NotInit, NotFound, SyaAssociativity, CONCEPT_COMPARISON_CONTEXT
|
||||
from core.sheerka.services.SheerkaConceptManager import SheerkaConceptManager, NoModificationFound, ForbiddenAttribute, \
|
||||
UnknownAttribute, CannotRemoveMeta, ValueNotFound, ConceptIsReferenced, NoFirstTokenError
|
||||
from parsers.BnfNodeParser import Sequence, StrMatch, ConceptExpression, OrderedChoice, Optional, ZeroOrMore, OneOrMore, \
|
||||
@@ -293,8 +293,6 @@ class TestSheerkaConceptManager(TestUsingMemoryBasedSheerka):
|
||||
"definition",
|
||||
"definition_type",
|
||||
"desc",
|
||||
"is_evaluated",
|
||||
"need_validation",
|
||||
"full_serialization",
|
||||
])
|
||||
def test_i_can_modify_a_metadata_attribute(self, attr):
|
||||
@@ -1422,6 +1420,33 @@ class TestSheerkaConceptManager(TestUsingMemoryBasedSheerka):
|
||||
res = sheerka.smart_get_attr(table_instance, size)
|
||||
assert sheerka.isinstance(res, BuiltinConcepts.NOT_FOUND)
|
||||
|
||||
def test_i_can_set_concept_precedence(self):
|
||||
sheerka, context, one, two, three = self.init_concepts("one", "two", "three")
|
||||
|
||||
res = sheerka.set_precedence(context, one, two, three)
|
||||
assert sheerka.isinstance(res, BuiltinConcepts.SUCCESS)
|
||||
|
||||
weights = sheerka.get_weights(BuiltinConcepts.PRECEDENCE, comparison_context=CONCEPT_COMPARISON_CONTEXT)
|
||||
assert weights == {'c:one|1001:': 3, 'c:two|1002:': 2, 'c:three|1003:': 1}
|
||||
|
||||
def test_i_cannot_set_precedence_when_too_few_argument(self):
|
||||
sheerka, context, one = self.init_concepts("one")
|
||||
|
||||
res = sheerka.set_precedence(context)
|
||||
assert res == sheerka.err("Not enough elements")
|
||||
|
||||
res = sheerka.set_precedence(context, one)
|
||||
assert res == sheerka.err("Not enough elements")
|
||||
|
||||
def test_i_cannot_set_precedence_when_error(self):
|
||||
sheerka, context, one, two = self.init_concepts("one", "two")
|
||||
|
||||
ret = sheerka.set_precedence(context, one, two, one)
|
||||
assert not ret.status
|
||||
|
||||
weights = sheerka.get_weights(BuiltinConcepts.PRECEDENCE, comparison_context=CONCEPT_COMPARISON_CONTEXT)
|
||||
assert weights == {'c:one|1001:': 2, 'c:two|1002:': 1}
|
||||
|
||||
|
||||
class TestSheerkaConceptManagerUsingFileBasedSheerka(TestUsingFileBasedSheerka):
|
||||
def test_i_can_add_several_concepts(self):
|
||||
|
||||
@@ -672,16 +672,15 @@ class TestSheerkaDebugManager(TestUsingMemoryBasedSheerka):
|
||||
|
||||
res = sheerka.inspect(context, return_values[0], values=True)
|
||||
concept_debug_obj = ConceptDebugObj(return_values[0].body)
|
||||
assert res.body == {
|
||||
'body': concept_debug_obj,
|
||||
'#type#': 'ReturnValueConcept',
|
||||
'id': f'{self.return_value_id}',
|
||||
'key': '__RETURN_VALUE',
|
||||
'name': '__RETURN_VALUE',
|
||||
'parents': [concept_debug_obj],
|
||||
'status': True,
|
||||
'value': concept_debug_obj,
|
||||
'who': 'evaluators.OneSuccess'}
|
||||
assert res.body['body'] == concept_debug_obj
|
||||
assert res.body['#type#'] == 'ReturnValueConcept'
|
||||
assert res.body['id'] == f'{self.return_value_id}'
|
||||
assert res.body['key'] == '__RETURN_VALUE'
|
||||
assert res.body['name'] == '__RETURN_VALUE'
|
||||
assert isinstance(res.body['parents'], list)
|
||||
assert res.body['status'] == True
|
||||
assert res.body['value'] == concept_debug_obj
|
||||
assert res.body['who'] == 'evaluators.OneSuccess'
|
||||
|
||||
# I also can print it using bag
|
||||
res = sheerka.inspect(context, return_values[0], '#type#', "who", "status", "value", values=True, as_bag=True)
|
||||
|
||||
@@ -5,9 +5,13 @@ from core.concept import Concept, DoNotResolve, ConceptParts, InfiniteRecursionR
|
||||
DEFINITION_TYPE_DEF
|
||||
from core.global_symbols import NotInit, NotFound
|
||||
from core.sheerka.services.SheerkaEvaluateConcept import SheerkaEvaluateConcept
|
||||
from core.sheerka.services.SheerkaExecute import ParserInput
|
||||
from core.sheerka.services.SheerkaMemory import SheerkaMemory
|
||||
from parsers.BaseParser import BaseParser
|
||||
from parsers.ExactConceptParser import ExactConceptParser
|
||||
from parsers.ExpressionParser import ExpressionParser
|
||||
from parsers.PythonParser import PythonNode, PythonParser
|
||||
from parsers.SyaNodeParser import SyaNodeParser
|
||||
from tests.TestUsingMemoryBasedSheerka import TestUsingMemoryBasedSheerka
|
||||
from tests.evaluators.EvaluatorTestsUtils import pr_ret_val, python_ret_val
|
||||
from tests.parsers.parsers_utils import CB, compare_with_test_object
|
||||
@@ -37,7 +41,7 @@ class TestSheerkaEvaluateConcept(TestUsingMemoryBasedSheerka):
|
||||
assert evaluated.get_metadata().post is None
|
||||
assert evaluated.get_metadata().where is None
|
||||
assert evaluated.variables() == {}
|
||||
assert evaluated.get_metadata().is_evaluated
|
||||
assert evaluated.get_hints().is_evaluated
|
||||
assert len(evaluated.values()) == 0 if body is None else 1
|
||||
|
||||
assert "foo" in sheerka.services[SheerkaMemory.NAME].registration
|
||||
@@ -70,7 +74,7 @@ class TestSheerkaEvaluateConcept(TestUsingMemoryBasedSheerka):
|
||||
assert evaluated.get_metadata().where is None
|
||||
assert evaluated.get_value(ConceptParts.POST) == expected
|
||||
assert evaluated.variables() == {}
|
||||
assert not evaluated.get_metadata().is_evaluated
|
||||
assert not evaluated.get_hints().is_evaluated
|
||||
assert len(evaluated.values) == 0 if expr is None else 1
|
||||
|
||||
@pytest.mark.parametrize("expr, expected", [
|
||||
@@ -94,7 +98,7 @@ class TestSheerkaEvaluateConcept(TestUsingMemoryBasedSheerka):
|
||||
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
|
||||
assert evaluated.get_hints().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
|
||||
@@ -114,7 +118,7 @@ class TestSheerkaEvaluateConcept(TestUsingMemoryBasedSheerka):
|
||||
evaluated = sheerka.evaluate_concept(context, concept)
|
||||
|
||||
assert evaluated.body == "do not resolve"
|
||||
assert evaluated.get_metadata().is_evaluated
|
||||
assert evaluated.get_hints().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)
|
||||
@@ -123,7 +127,7 @@ class TestSheerkaEvaluateConcept(TestUsingMemoryBasedSheerka):
|
||||
evaluated = sheerka.evaluate_concept(context, concept)
|
||||
|
||||
assert evaluated.get_value("a") == "do not resolve"
|
||||
assert evaluated.get_metadata().is_evaluated
|
||||
assert evaluated.get_hints().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")
|
||||
@@ -135,7 +139,7 @@ class TestSheerkaEvaluateConcept(TestUsingMemoryBasedSheerka):
|
||||
|
||||
assert evaluated.body == "do not resolve"
|
||||
assert evaluated.get_value("a") == "do not resolve"
|
||||
assert evaluated.get_metadata().is_evaluated
|
||||
assert evaluated.get_hints().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)
|
||||
@@ -153,8 +157,8 @@ class TestSheerkaEvaluateConcept(TestUsingMemoryBasedSheerka):
|
||||
evaluated = sheerka.evaluate_concept(context, concept)
|
||||
|
||||
compare_with_test_object(evaluated, CB("foo", CB("a", NotInit)))
|
||||
assert evaluated.get_metadata().is_evaluated
|
||||
assert evaluated.body.get_metadata().is_evaluated
|
||||
assert evaluated.get_hints().is_evaluated
|
||||
assert evaluated.body.get_hints().is_evaluated
|
||||
|
||||
def test_i_can_evaluate_when_the_referenced_concept_has_a_body(self):
|
||||
sheerka, context, concept_a, concept = self.init_concepts(
|
||||
@@ -166,8 +170,8 @@ class TestSheerkaEvaluateConcept(TestUsingMemoryBasedSheerka):
|
||||
|
||||
assert evaluated.key == concept.key
|
||||
compare_with_test_object(evaluated.body, CB("a", 1))
|
||||
assert not concept_a.get_metadata().is_evaluated
|
||||
assert evaluated.get_metadata().is_evaluated
|
||||
assert not concept_a.get_hints().is_evaluated
|
||||
assert evaluated.get_hints().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(
|
||||
@@ -183,7 +187,7 @@ class TestSheerkaEvaluateConcept(TestUsingMemoryBasedSheerka):
|
||||
expected = CB("c", CB("b", CB("a", "a")))
|
||||
compare_with_test_object(evaluated.body, expected)
|
||||
assert sheerka.objvalue(evaluated) == 'a'
|
||||
assert evaluated.get_metadata().is_evaluated
|
||||
assert evaluated.get_hints().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(
|
||||
@@ -199,7 +203,7 @@ class TestSheerkaEvaluateConcept(TestUsingMemoryBasedSheerka):
|
||||
expected = CB("c", CB("b", CB("a", NotInit)))
|
||||
compare_with_test_object(evaluated.body, expected)
|
||||
compare_with_test_object(sheerka.objvalue(evaluated), CB("a", NotInit))
|
||||
assert evaluated.get_metadata().is_evaluated
|
||||
assert evaluated.get_hints().is_evaluated
|
||||
|
||||
def test_i_can_evaluate_concept_when_variables_reference_others_concepts_1(self):
|
||||
"""
|
||||
@@ -349,7 +353,7 @@ class TestSheerkaEvaluateConcept(TestUsingMemoryBasedSheerka):
|
||||
evaluated = sheerka.evaluate_concept(context, add_instance)
|
||||
|
||||
assert evaluated.key == add_instance.key
|
||||
assert evaluated.get_metadata().is_evaluated
|
||||
assert evaluated.get_hints().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):
|
||||
@@ -363,7 +367,7 @@ class TestSheerkaEvaluateConcept(TestUsingMemoryBasedSheerka):
|
||||
evaluated = sheerka.evaluate_concept(context, add_instance)
|
||||
|
||||
assert evaluated.key == add_instance.key
|
||||
assert evaluated.get_metadata().is_evaluated
|
||||
assert evaluated.get_hints().is_evaluated
|
||||
assert sheerka.objvalue(evaluated) == 3
|
||||
|
||||
def test_i_can_evaluate_when_body_is_a_concept_with_its_own_variables_multiple_levels(self):
|
||||
@@ -378,7 +382,7 @@ class TestSheerkaEvaluateConcept(TestUsingMemoryBasedSheerka):
|
||||
evaluated = sheerka.evaluate_concept(context, inc_instance)
|
||||
|
||||
assert evaluated.key == inc_instance.key
|
||||
assert evaluated.get_metadata().is_evaluated
|
||||
assert evaluated.get_hints().is_evaluated
|
||||
assert sheerka.objvalue(evaluated) == 2
|
||||
|
||||
def test_i_can_evaluate_a_concept_that_references_another_concept_twice(self):
|
||||
@@ -556,7 +560,7 @@ class TestSheerkaEvaluateConcept(TestUsingMemoryBasedSheerka):
|
||||
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("x is an int", body="isinstance(x, int)", pre="is_question()").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,
|
||||
@@ -570,8 +574,8 @@ class TestSheerkaEvaluateConcept(TestUsingMemoryBasedSheerka):
|
||||
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("x is an int", body="isinstance(x, int)", pre="is_question()").def_var("x"),
|
||||
Concept("y is an integer", body="y is an int", pre="is_question()").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,
|
||||
@@ -600,14 +604,15 @@ class TestSheerkaEvaluateConcept(TestUsingMemoryBasedSheerka):
|
||||
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):
|
||||
# The test does not work because the and condition is not correctly supported
|
||||
# We need the ExpressionParser
|
||||
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("x is an int", body="isinstance(x, int)", pre="is_question()").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"),
|
||||
@@ -622,7 +627,7 @@ class TestSheerkaEvaluateConcept(TestUsingMemoryBasedSheerka):
|
||||
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("x is an int", body="isinstance(x, int)", pre="is_question()").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,
|
||||
@@ -685,10 +690,10 @@ class TestSheerkaEvaluateConcept(TestUsingMemoryBasedSheerka):
|
||||
eval_body=True
|
||||
)
|
||||
|
||||
for concept in (c1, c2, c3, c4):
|
||||
for concept, expected in ((c1, 3), (c2, 1), (c3, 2), (c4, 3)):
|
||||
evaluated = sheerka.evaluate_concept(context, concept)
|
||||
assert evaluated.key == concept.key
|
||||
assert evaluated.body == InfiniteRecursionResolved(3)
|
||||
assert evaluated.body == InfiniteRecursionResolved(expected)
|
||||
|
||||
def test_i_can_detect_infinite_recursion_when_no_constant(self):
|
||||
sheerka, context, foo, bar, baz, qux = self.init_concepts(
|
||||
@@ -877,26 +882,31 @@ class TestSheerkaEvaluateConcept(TestUsingMemoryBasedSheerka):
|
||||
evaluated = sheerka.evaluate_concept(context, concept, eval_body=True)
|
||||
|
||||
assert evaluated.key == concept.key
|
||||
assert concept.get_metadata().is_evaluated == expected
|
||||
assert concept.get_hints().is_evaluated == expected
|
||||
|
||||
def test_i_only_compute_the_requested_metadata(self):
|
||||
sheerka, context, concept = self.init_concepts(
|
||||
Concept("foo", pre="'pre'", post="'post'", ret="'ret'", where="'where'", body="'body'").def_var("a", "'a'")
|
||||
Concept("foo", pre="True", post="'post'", ret="'ret'", where="True", body="'body'").def_var("a", "'a'")
|
||||
)
|
||||
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=[ConceptParts.PRE])
|
||||
assert evaluated.values() == {"a": NotInit, ConceptParts.PRE: 'pre'}
|
||||
assert evaluated.values() == {"a": NotInit, ConceptParts.PRE: True}
|
||||
|
||||
def test_i_can_manage_ret(self):
|
||||
sheerka, context, foo, bar = self.init_concepts("foo", Concept("bar", ret="foo"))
|
||||
|
||||
res = sheerka.evaluate_concept(context, bar)
|
||||
assert res.id == bar.id
|
||||
assert sheerka.isinstance(res, "bar")
|
||||
|
||||
res = sheerka.evaluate_concept(context, bar, eval_body=True)
|
||||
assert res.id == foo.id
|
||||
assert sheerka.isinstance(res, "foo")
|
||||
|
||||
# And the result is still the same after a second call
|
||||
assert bar.get_hints().is_evaluated
|
||||
res = sheerka.evaluate_concept(context, bar, eval_body=True)
|
||||
assert sheerka.isinstance(res, "foo")
|
||||
|
||||
def test_ret_is_evaluated_only_is_body_is_requested(self):
|
||||
sheerka, context, foo, bar = self.init_concepts("foo", Concept("bar", ret="__NOT_FOUND"))
|
||||
@@ -930,7 +940,7 @@ class TestSheerkaEvaluateConcept(TestUsingMemoryBasedSheerka):
|
||||
# 'def concept foo as foo'
|
||||
return_values = [pr_ret_val(foo, parser="ExactConcept"), python_ret_val("foo")]
|
||||
|
||||
res = evaluator.get_recursive_definitions(foo, return_values)
|
||||
res = evaluator.get_recursive_definitions(context, foo, return_values)
|
||||
|
||||
assert list(res) == [BaseParser.get_name("ExactConcept")]
|
||||
|
||||
@@ -941,7 +951,7 @@ class TestSheerkaEvaluateConcept(TestUsingMemoryBasedSheerka):
|
||||
# 'def concept foo as bar'
|
||||
return_values = [pr_ret_val(bar, parser="ExactConcept"), python_ret_val("foo")]
|
||||
|
||||
res = evaluator.get_recursive_definitions(foo, return_values)
|
||||
res = evaluator.get_recursive_definitions(context, foo, return_values)
|
||||
|
||||
assert list(res) == []
|
||||
|
||||
@@ -953,18 +963,120 @@ class TestSheerkaEvaluateConcept(TestUsingMemoryBasedSheerka):
|
||||
# i dunno how to construct the return value
|
||||
return_values = [pr_ret_val(q, parser="ExactConcept")]
|
||||
|
||||
res = evaluator.get_recursive_definitions(q, return_values)
|
||||
res = evaluator.get_recursive_definitions(context, q, return_values)
|
||||
|
||||
assert list(res) == []
|
||||
|
||||
# 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.get_compiled()) > 0
|
||||
#
|
||||
# evaluated_2 = sheerka.evaluate_concept(context, sheerka.new("foo"), eval_body=True)
|
||||
# assert evaluated_2.body == 10
|
||||
# assert len(evaluated_2.get_compiled()) == 0
|
||||
def test_i_do_not_mess_up_use_copy_when_exact_concept(self):
|
||||
sheerka, context, one, number, isa = self.init_concepts(
|
||||
"one",
|
||||
"number",
|
||||
Concept("x is a y", body="isa(x,y)", pre="is_question()").def_var("x").def_var("y"))
|
||||
|
||||
evaluator = SheerkaEvaluateConcept(sheerka)
|
||||
|
||||
parsed_return_value = ExactConceptParser().parse(context, ParserInput("one is a number"))
|
||||
concept = parsed_return_value[0].body.body
|
||||
|
||||
# just get the compiled
|
||||
context.add_to_protected_hints(BuiltinConcepts.EVAL_QUESTION_REQUESTED)
|
||||
evaluated = evaluator.evaluate_concept(context, concept)
|
||||
assert evaluated.get_compiled()["x"][0].body.body.get_hints().use_copy
|
||||
assert evaluated.get_compiled()["y"][0].body.body.get_hints().use_copy
|
||||
|
||||
# get the body
|
||||
evaluated = evaluator.evaluate_concept(context, concept, eval_body=True)
|
||||
assert evaluated.get_compiled()["x"][0].body.body.get_hints().use_copy
|
||||
assert evaluated.get_compiled()["y"][0].body.body.get_hints().use_copy
|
||||
assert not evaluated.get_value("x").get_hints().use_copy
|
||||
assert not evaluated.get_value("y").get_hints().use_copy
|
||||
|
||||
def test_i_do_not_mess_up_use_copy_when_expression_parser(self):
|
||||
sheerka, context, one, number, isa = self.init_concepts(
|
||||
"one",
|
||||
"number",
|
||||
Concept("x is a y", body="isa(x,y)", pre="is_question()").def_var("x").def_var("y"))
|
||||
|
||||
evaluator = SheerkaEvaluateConcept(sheerka)
|
||||
|
||||
parsed_return_value = ExpressionParser().parse(context, ParserInput("one is a number"))
|
||||
concept = next(iter(parsed_return_value.body.body.compiled[0].return_value.body.body.objects.values()))
|
||||
assert concept.get_compiled()["x"][0].body.body.get_hints().use_copy
|
||||
assert concept.get_compiled()["y"][0].body.body.get_hints().use_copy
|
||||
|
||||
# get the body
|
||||
context.add_to_protected_hints(BuiltinConcepts.EVAL_QUESTION_REQUESTED)
|
||||
evaluated = evaluator.evaluate_concept(context, concept, eval_body=True)
|
||||
assert evaluated.get_compiled()["x"][0].body.body.get_hints().use_copy
|
||||
assert evaluated.get_compiled()["y"][0].body.body.get_hints().use_copy
|
||||
assert not evaluated.get_value("x").get_hints().use_copy
|
||||
assert not evaluated.get_value("y").get_hints().use_copy
|
||||
|
||||
def test_i_do_not_evaluate_the_body_when_validation_only_is_set(self):
|
||||
sheerka, context, red, shirt, a_x, red_x = self.init_concepts(
|
||||
"red",
|
||||
Concept("shirt", body="set_attr(self, 'body_shirt_is_evaluated', True)"),
|
||||
Concept("a x", body="set_attr(x, 'body_ax_is_evaluated', True)", ret="x").def_var("x"),
|
||||
Concept("red x", body="set_attr(x, 'color', 'red')", ret="x").def_var("x"),
|
||||
create_new=True)
|
||||
|
||||
parsed_ret_val = SyaNodeParser().parse(context, ParserInput("a red shirt"))
|
||||
|
||||
# Sanity check for normal behaviour
|
||||
to_evaluate1 = parsed_ret_val.body.body[0].concept.copy()
|
||||
evaluated1 = sheerka.evaluate_concept(context, to_evaluate1, eval_body=True, validation_only=False)
|
||||
|
||||
assert sheerka.isinstance(evaluated1, shirt)
|
||||
assert evaluated1.get_value("body_ax_is_evaluated") == True
|
||||
assert evaluated1.get_value("body_shirt_is_evaluated") == True
|
||||
assert evaluated1.get_value("color") == "red"
|
||||
assert evaluated1.body == sheerka.new(BuiltinConcepts.SUCCESS)
|
||||
|
||||
# check validation_only behaviour
|
||||
to_evaluate2 = parsed_ret_val.body.body[0].concept.copy()
|
||||
evaluated2 = sheerka.evaluate_concept(context, to_evaluate2, eval_body=True, validation_only=True)
|
||||
|
||||
assert sheerka.isinstance(evaluated2, shirt)
|
||||
assert evaluated2.get_value("body_ax_is_evaluated") == NotInit
|
||||
assert evaluated2.get_value("body_shirt_is_evaluated") == NotInit
|
||||
assert evaluated2.get_value("color") == NotInit
|
||||
assert evaluated2.body == NotInit
|
||||
|
||||
def test_methods_with_side_effect_are_not_called_when_eval_body_is_false(self):
|
||||
sheerka, context, red, shirt, a_x, red_x = self.init_concepts(
|
||||
"red",
|
||||
Concept("shirt", body="set_attr(self, 'body_shirt_is_evaluated', True)"),
|
||||
Concept("a x", body="set_attr(x, 'body_ax_is_evaluated', True)", ret="x").def_var("x"),
|
||||
Concept("red x", body="set_attr(x, 'color', 'red')", ret="x").def_var("x"),
|
||||
create_new=True,
|
||||
)
|
||||
|
||||
parsed_ret_val = SyaNodeParser().parse(context, ParserInput("a red shirt"))
|
||||
to_evaluate = parsed_ret_val.body.body[0].concept
|
||||
|
||||
evaluated = sheerka.evaluate_concept(context, to_evaluate, eval_body=False)
|
||||
|
||||
assert sheerka.isinstance(evaluated, a_x)
|
||||
assert "x" in evaluated.get_compiled()
|
||||
assert ConceptParts.BODY in evaluated.get_compiled()
|
||||
assert ConceptParts.RET in evaluated.get_compiled()
|
||||
assert sheerka.isinstance(evaluated.get_compiled()["x"], red_x)
|
||||
assert evaluated.get_compiled()["x"].get_compiled()["x"] == shirt # so, it's not evaluated
|
||||
|
||||
# sanity check
|
||||
parsed_ret_val = SyaNodeParser().parse(context, ParserInput("a red shirt"))
|
||||
to_evaluate = parsed_ret_val.body.body[0].concept
|
||||
evaluated = sheerka.evaluate_concept(context, to_evaluate, eval_body=True)
|
||||
|
||||
assert sheerka.isinstance(evaluated, shirt)
|
||||
assert evaluated.get_value("body_ax_is_evaluated") == True
|
||||
assert evaluated.get_value("body_shirt_is_evaluated") == True
|
||||
assert evaluated.get_value("color") == "red"
|
||||
|
||||
def test_concept_is_not_evaluated_when_method_access_error(self):
|
||||
sheerka, context, foo = self.init_concepts(Concept("foo", body="set_attr(self, 'prop_name', 'prop_value')"))
|
||||
|
||||
evaluated = sheerka.evaluate_concept(context, foo, eval_body=True, validation_only=True)
|
||||
|
||||
assert sheerka.isinstance(evaluated, foo)
|
||||
assert not foo.get_hints().is_evaluated
|
||||
|
||||
@@ -2,14 +2,14 @@ import operator
|
||||
|
||||
import pytest
|
||||
|
||||
from core.builtin_concepts_ids import BuiltinConcepts
|
||||
from core.concept import Concept, DEFINITION_TYPE_DEF
|
||||
from core.rule import Rule, ACTION_TYPE_EXEC
|
||||
from core.sheerka.Sheerka import RECOGNIZED_BY_ID, RECOGNIZED_BY_NAME
|
||||
from core.sheerka.services.SheerkaEvaluateRules import SheerkaEvaluateRules, LOW_PRIORITY_RULES, DISABLED_RULES
|
||||
from core.sheerka.services.SheerkaExecute import ParserInput
|
||||
from core.sheerka.services.SheerkaRuleManager import SheerkaRuleManager, CompiledCondition
|
||||
from core.sheerka.services.SheerkaRuleManager import SheerkaRuleManager, CompiledCondition, PythonConditionExprVisitor
|
||||
from evaluators.PythonEvaluator import PythonEvaluator
|
||||
from parsers.ExpressionParser import ExpressionParser
|
||||
from parsers.PythonParser import PythonParser
|
||||
from sheerkapython.python_wrapper import Expando
|
||||
from tests.TestUsingMemoryBasedSheerka import TestUsingMemoryBasedSheerka
|
||||
@@ -40,7 +40,7 @@ class TestSheerkaEvaluateRules(TestUsingMemoryBasedSheerka):
|
||||
DISABLED_RULES: [r7]
|
||||
}
|
||||
|
||||
@pytest.mark.skip("Not ready for that")
|
||||
@pytest.mark.skip("Rete is not ready for that")
|
||||
def test_i_can_evaluate_question_concept_rules(self):
|
||||
sheerka, context, concept, r1, r2, r3, r4, r5, r6, r7, r8, r9 = self.init_test().with_concepts(
|
||||
Concept("x equals y", body="x == y", pre="is_question()").def_var("x").def_var("y"),
|
||||
@@ -152,7 +152,7 @@ class TestSheerkaEvaluateRules(TestUsingMemoryBasedSheerka):
|
||||
|
||||
there_instance = sheerka.new_from_template(there, there.key)
|
||||
if recognized_by:
|
||||
there_instance.set_hint(BuiltinConcepts.RECOGNIZED_BY, recognized_by)
|
||||
there_instance.get_hints().recognized_by = recognized_by
|
||||
ret = sheerka.ret("evaluator", True, sheerka.new(greetings, a=there_instance))
|
||||
res = service.evaluate_rules(context, [rule], {"__ret": ret}, set())
|
||||
assert res == {True: [rule]}
|
||||
@@ -175,7 +175,7 @@ class TestSheerkaEvaluateRules(TestUsingMemoryBasedSheerka):
|
||||
|
||||
my_friend_instance = sheerka.new_from_template(my_friend, my_friend.key)
|
||||
if recognized_by:
|
||||
my_friend_instance.set_hint(BuiltinConcepts.RECOGNIZED_BY, recognized_by)
|
||||
my_friend_instance.get_hints().recognized_by = recognized_by
|
||||
ret = sheerka.ret("evaluator", True, sheerka.new(greetings, a=my_friend_instance))
|
||||
res = service.evaluate_rules(context, [rule], {"__ret": ret}, set())
|
||||
assert res == {True: [rule]}
|
||||
@@ -211,7 +211,8 @@ class TestSheerkaEvaluateRules(TestUsingMemoryBasedSheerka):
|
||||
def test_i_can_evaluate_concept_rule_with_the_same_name_when_the_second_concept_is_declared_after(self):
|
||||
sheerka, context, g1, rule, g2 = self.init_test().with_concepts(
|
||||
Concept("greetings", definition="hello a", definition_type=DEFINITION_TYPE_DEF).def_var("a"),
|
||||
create_new=True).with_format_rules(Rule(predicate="recognize(__ret.body, greetings)", action="")).with_concepts(
|
||||
create_new=True).with_format_rules(
|
||||
Rule(predicate="recognize(__ret.body, greetings)", action="")).with_concepts(
|
||||
Concept("greetings", definition="hi a", definition_type=DEFINITION_TYPE_DEF).def_var("a")).unpack()
|
||||
|
||||
service = sheerka.services[SheerkaEvaluateRules.NAME]
|
||||
@@ -249,3 +250,22 @@ class TestSheerkaEvaluateRules(TestUsingMemoryBasedSheerka):
|
||||
|
||||
assert rule in evaluate_rule_service.network.rules
|
||||
assert rule.rete_net == evaluate_rule_service.network
|
||||
|
||||
def test_i_can_get_missing_variables_when_evaluate_conditions(self):
|
||||
sheerka, context = self.init_test().unpack()
|
||||
|
||||
expression = "isinstance(a, int)"
|
||||
parser = ExpressionParser()
|
||||
ret_val = parser.parse(context, ParserInput(expression))
|
||||
parsed = ret_val.body.body
|
||||
|
||||
visitor = PythonConditionExprVisitor(context)
|
||||
conditions = visitor.get_conditions(parsed)
|
||||
|
||||
missing_vars = set()
|
||||
service = sheerka.services[SheerkaEvaluateRules.NAME]
|
||||
res = service.evaluate_conditions(context, conditions, {}, missing_vars)
|
||||
|
||||
assert res == []
|
||||
assert missing_vars == {"a"}
|
||||
|
||||
|
||||
@@ -84,7 +84,19 @@ class TestSheerkaIsAManager(TestUsingMemoryBasedSheerka):
|
||||
assert sheerka.isinstance(error, BuiltinConcepts.NOT_A_SET)
|
||||
assert error.body == one
|
||||
|
||||
def test_isa_and_isa_group(self):
|
||||
def test_isa(self):
|
||||
sheerka, context, blue, color = self.init_concepts(Concept("blue"), Concept("color"))
|
||||
|
||||
assert not sheerka.isa(blue, color)
|
||||
|
||||
sheerka.set_isa(context, blue, color)
|
||||
assert sheerka.isa(blue, color)
|
||||
|
||||
# isa tests the id of a concept, not it's content
|
||||
another_color_instance_but_with_a_body = sheerka.new(color, body="a body")
|
||||
assert sheerka.isa(blue, another_color_instance_but_with_a_body)
|
||||
|
||||
def test_isaset(self):
|
||||
sheerka, context, group, foo = self.init_concepts(Concept("group"), Concept("foo"))
|
||||
|
||||
assert not sheerka.isaset(context, group)
|
||||
|
||||
@@ -4,28 +4,18 @@ from core.builtin_concepts import BuiltinConcepts, ReturnValueConcept
|
||||
from core.concept import Concept, DEFINITION_TYPE_DEF
|
||||
from core.global_symbols import RULE_COMPARISON_CONTEXT, NotFound, EVENT_RULE_DELETED
|
||||
from core.rule import Rule, ACTION_TYPE_PRINT, ACTION_TYPE_EXEC
|
||||
from core.sheerka.Sheerka import RECOGNIZED_BY_ID, RECOGNIZED_BY_NAME
|
||||
from core.sheerka.services.SheerkaExecute import ParserInput
|
||||
from core.sheerka.services.SheerkaRuleManager import SheerkaRuleManager, FormatRuleActionParser, \
|
||||
FormatAstRawText, FormatAstVariable, FormatAstSequence, FormatAstFunction, \
|
||||
FormatRuleSyntaxError, FormatAstList, UnexpectedEof, FormatAstColor, FormatAstDict, \
|
||||
FormatAstMulti, \
|
||||
PythonCodeEmitter, FormatAstNode, ReteConditionExprVisitor
|
||||
from core.sheerka.services.SheerkaRuleManager import SheerkaRuleManager, ReteConditionExprVisitor
|
||||
from core.tokenizer import Token, TokenKind
|
||||
from parsers.BaseParser import ErrorSink
|
||||
from parsers.ExpressionParser import ExpressionParser
|
||||
from parsers.FormatRuleActionParser import FormatAstNode
|
||||
from sheerkarete.conditions import FilterCondition
|
||||
from sheerkarete.network import ReteNetwork
|
||||
from tests.TestUsingFileBasedSheerka import TestUsingFileBasedSheerka
|
||||
from tests.TestUsingMemoryBasedSheerka import TestUsingMemoryBasedSheerka
|
||||
from tests.parsers.parsers_utils import get_rete_conditions, NEGCOND, NCCOND
|
||||
|
||||
seq = FormatAstSequence
|
||||
raw = FormatAstRawText
|
||||
var = FormatAstVariable
|
||||
func = FormatAstFunction
|
||||
lst = FormatAstList
|
||||
|
||||
PYTHON_EVALUATOR_NAME = "Python"
|
||||
CONCEPT_EVALUATOR_NAME = "Concept"
|
||||
|
||||
@@ -175,7 +165,7 @@ class TestSheerkaRuleManager(TestUsingMemoryBasedSheerka):
|
||||
sheerka, context = self.init_test(cache_only=False).unpack()
|
||||
service = sheerka.services[SheerkaRuleManager.NAME]
|
||||
|
||||
rule = Rule(ACTION_TYPE_EXEC, "name", "cannot build = False", "'Hello back at you !'")
|
||||
rule = Rule(action_type, "name", "cannot build = False", action)
|
||||
rule.metadata.is_enabled = True # it should be disabled
|
||||
rule = service.init_rule(context, rule)
|
||||
|
||||
@@ -209,71 +199,6 @@ class TestSheerkaRuleManager(TestUsingMemoryBasedSheerka):
|
||||
assert not rule.metadata.is_enabled
|
||||
assert rule.compiled_action is None
|
||||
|
||||
@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(")")])),
|
||||
("dict(var_name)", FormatAstDict("var_name")),
|
||||
("dict(var_name, items_prop='props')", FormatAstDict("var_name", items_prop='props')),
|
||||
("dict(var_name, debug=True)", FormatAstDict("var_name", debug=True, prefix="{", suffix="}")),
|
||||
("multi(var_name)", FormatAstMulti("var_name")),
|
||||
])
|
||||
def test_i_can_parse_format_rule(self, text, expected):
|
||||
assert FormatRuleActionParser(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,e)", FormatRuleSyntaxError("too many positional arguments",
|
||||
Token(TokenKind.IDENTIFIER, "e", 13, 1, 14))),
|
||||
("list(a, recursion_depth=hello)", FormatRuleSyntaxError("'hello' is not numeric", None)),
|
||||
("list(a, recursion_depth='hello')", FormatRuleSyntaxError("'recursion_depth' must be an integer", None)),
|
||||
("dict()", FormatRuleSyntaxError("variable name not found", None)),
|
||||
])
|
||||
def test_i_cannot_parse_invalid_format(self, text, expected_error):
|
||||
parser = FormatRuleActionParser(text)
|
||||
parser.parse()
|
||||
|
||||
assert parser.error_sink == expected_error
|
||||
|
||||
def test_i_can_get_rule_priorities(self):
|
||||
sheerka, context, rule_true, rule_false = self.init_test().with_format_rules(("True", "True"),
|
||||
("False", "False")).unpack()
|
||||
@@ -337,106 +262,6 @@ class TestSheerkaRuleManager(TestUsingMemoryBasedSheerka):
|
||||
unresolved.metadata.id_is_unresolved = True
|
||||
assert sheerka.resolve_rule(context, unresolved) == rule
|
||||
|
||||
@pytest.mark.parametrize("obj, expected", [
|
||||
("text value", "var == 'text value'"),
|
||||
("text 'value'", '''var == "text 'value'"'''),
|
||||
('text "value"', """var == 'text "value"'"""),
|
||||
(10, "var == 10"),
|
||||
(10.01, "var == 10.01"),
|
||||
])
|
||||
def test_i_can_test_python_code_emitter_for_basic_types(self, obj, expected):
|
||||
sheerka, context = self.init_test().unpack()
|
||||
|
||||
assert PythonCodeEmitter(context).recognize(obj, "var").get_text() == expected
|
||||
assert PythonCodeEmitter(context, "status").recognize(obj, "var").get_text() == "status and " + expected
|
||||
|
||||
@pytest.mark.parametrize("recognized_by, expected", [
|
||||
(RECOGNIZED_BY_ID, "isinstance(var, Concept) and var.id == '1001'"),
|
||||
(RECOGNIZED_BY_NAME, "isinstance(var, Concept) and var.name == 'greetings'"),
|
||||
(None, "isinstance(var, Concept) and var.key == 'hello'"),
|
||||
])
|
||||
def test_i_can_test_python_code_emitter_for_concepts(self, recognized_by, expected):
|
||||
sheerka, context, foo = self.init_concepts(
|
||||
Concept("greetings", definition="hello", definition_type=DEFINITION_TYPE_DEF))
|
||||
|
||||
instance = sheerka.new_from_template(foo, foo.key)
|
||||
if recognized_by:
|
||||
instance.set_hint(BuiltinConcepts.RECOGNIZED_BY, recognized_by)
|
||||
|
||||
assert PythonCodeEmitter(context).recognize(instance, "var").get_text() == expected
|
||||
assert PythonCodeEmitter(context, "status").recognize(instance, "var").get_text() == "status and " + expected
|
||||
|
||||
def test_i_can_test_python_code_emitter_for_concepts_with_variable(self):
|
||||
sheerka, context, greetings, little, foo, bar, and_concept = self.init_concepts(
|
||||
Concept("greetings", definition="hello a", definition_type=DEFINITION_TYPE_DEF).def_var("a"),
|
||||
Concept("little x").def_var("x"),
|
||||
"foo",
|
||||
"bar",
|
||||
Concept("a and b").def_var("a").def_var("b")
|
||||
)
|
||||
|
||||
# variable is a string
|
||||
greetings_instance = sheerka.new_from_template(greetings, greetings.key, a='sheerka')
|
||||
expected = "isinstance(var, Concept) and var.key == 'hello __var__0' and var.get_value('a') == 'sheerka'"
|
||||
text = PythonCodeEmitter(context).recognize(greetings_instance, "var").get_text()
|
||||
assert text == expected
|
||||
|
||||
# variable is a concept recognized by id
|
||||
foo_instance = sheerka.new_from_template(foo, foo.key)
|
||||
foo_instance.set_hint(BuiltinConcepts.RECOGNIZED_BY, RECOGNIZED_BY_ID)
|
||||
greetings_instance = sheerka.new_from_template(greetings, greetings.key, a=foo_instance)
|
||||
expected = """__x_00__ = var.get_value('a')
|
||||
isinstance(var, Concept) and var.key == 'hello __var__0' and isinstance(__x_00__, Concept) and __x_00__.id == '1003'"""
|
||||
text = PythonCodeEmitter(context).recognize(greetings_instance, "var").get_text()
|
||||
assert text == expected
|
||||
|
||||
# variable is a concept recognized by name
|
||||
foo_instance = sheerka.new_from_template(foo, foo.key)
|
||||
foo_instance.set_hint(BuiltinConcepts.RECOGNIZED_BY, RECOGNIZED_BY_NAME)
|
||||
greetings_instance = sheerka.new_from_template(greetings, greetings.key, a=foo_instance)
|
||||
expected = """__x_00__ = var.get_value('a')
|
||||
isinstance(var, Concept) and var.key == 'hello __var__0' and isinstance(__x_00__, Concept) and __x_00__.name == 'foo'"""
|
||||
text = PythonCodeEmitter(context).recognize(greetings_instance, "var").get_text()
|
||||
assert text == expected
|
||||
|
||||
# variable is a concept recognized by value
|
||||
foo_instance = sheerka.new_from_template(foo, foo.key)
|
||||
greetings_instance = sheerka.new_from_template(greetings, greetings.key, a=foo_instance)
|
||||
expected = """__x_00__ = var.get_value('a')
|
||||
isinstance(var, Concept) and var.key == 'hello __var__0' and isinstance(__x_00__, Concept) and __x_00__.key == 'foo'"""
|
||||
text = PythonCodeEmitter(context).recognize(greetings_instance, "var").get_text()
|
||||
assert text == expected
|
||||
|
||||
# variable is a concept witch has itself some variable
|
||||
foo_instance = sheerka.new_from_template(foo, foo.key)
|
||||
little_instance = sheerka.new_from_template(little, little.key, x=foo_instance)
|
||||
greetings_instance = sheerka.new_from_template(greetings, greetings.key, a=little_instance)
|
||||
expected = """__x_00__ = var.get_value('a')
|
||||
__x_01__ = __x_00__.get_value('x')
|
||||
isinstance(var, Concept) and var.key == 'hello __var__0'""" + \
|
||||
" and isinstance(__x_00__, Concept) and __x_00__.key == 'little __var__0'" + \
|
||||
" and isinstance(__x_01__, Concept) and __x_01__.key == 'foo'"""
|
||||
text = PythonCodeEmitter(context).recognize(greetings_instance, "var").get_text()
|
||||
assert text == expected
|
||||
|
||||
# concept with multiple variables (which are themselves concepts)
|
||||
foo_instance = sheerka.new_from_template(foo, foo.key)
|
||||
bar_instance = sheerka.new_from_template(bar, bar.key)
|
||||
little_instance = sheerka.new_from_template(little, little.key, x=foo_instance)
|
||||
and_instance = sheerka.new_from_template(and_concept, and_concept.key, a=bar_instance, b=little_instance)
|
||||
greetings_instance = sheerka.new_from_template(greetings, greetings.key, a=and_instance)
|
||||
expected = """__x_00__ = var.get_value('a')
|
||||
__x_01__ = __x_00__.get_value('a')
|
||||
__x_02__ = __x_00__.get_value('b')
|
||||
__x_03__ = __x_02__.get_value('x')
|
||||
isinstance(var, Concept) and var.key == 'hello __var__0'""" + \
|
||||
" and isinstance(__x_00__, Concept) and __x_00__.key == '__var__0 and __var__1'" + \
|
||||
" and isinstance(__x_01__, Concept) and __x_01__.key == 'bar'" + \
|
||||
" and isinstance(__x_02__, Concept) and __x_02__.key == 'little __var__0'" + \
|
||||
" and isinstance(__x_03__, Concept) and __x_03__.key == 'foo'"
|
||||
text = PythonCodeEmitter(context).recognize(greetings_instance, "var").get_text()
|
||||
assert text == expected
|
||||
|
||||
def test_i_can_get_format_rules(self):
|
||||
sheerka, context = self.init_test().unpack()
|
||||
service = sheerka.services[SheerkaRuleManager.NAME]
|
||||
@@ -674,3 +499,103 @@ class TestSheerkaRuleManagerUsingFileBasedSheerka(TestUsingFileBasedSheerka):
|
||||
assert rule.compiled_conditions == expected.compiled_conditions
|
||||
assert rule.priority is not None
|
||||
assert rule.priority == expected.priority
|
||||
|
||||
# @pytest.mark.parametrize("obj, expected", [
|
||||
# ("text value", "var == 'text value'"),
|
||||
# ("text 'value'", '''var == "text 'value'"'''),
|
||||
# ('text "value"', """var == 'text "value"'"""),
|
||||
# (10, "var == 10"),
|
||||
# (10.01, "var == 10.01"),
|
||||
# ])
|
||||
# def test_i_can_test_python_code_emitter_for_basic_types(self, obj, expected):
|
||||
# sheerka, context = self.init_test().unpack()
|
||||
#
|
||||
# assert PythonCodeEmitter(context).recognize(obj, "var").get_text() == expected
|
||||
# assert PythonCodeEmitter(context, "status").recognize(obj, "var").get_text() == "status and " + expected
|
||||
#
|
||||
# @pytest.mark.parametrize("recognized_by, expected", [
|
||||
# (RECOGNIZED_BY_ID, "isinstance(var, Concept) and var.id == '1001'"),
|
||||
# (RECOGNIZED_BY_NAME, "isinstance(var, Concept) and var.name == 'greetings'"),
|
||||
# (None, "isinstance(var, Concept) and var.key == 'hello'"),
|
||||
# ])
|
||||
# def test_i_can_test_python_code_emitter_for_concepts(self, recognized_by, expected):
|
||||
# sheerka, context, foo = self.init_concepts(
|
||||
# Concept("greetings", definition="hello", definition_type=DEFINITION_TYPE_DEF))
|
||||
#
|
||||
# instance = sheerka.new_from_template(foo, foo.key)
|
||||
# if recognized_by:
|
||||
# instance.get_hints().recognized_by = recognized_by
|
||||
#
|
||||
# assert PythonCodeEmitter(context).recognize(instance, "var").get_text() == expected
|
||||
# assert PythonCodeEmitter(context, "status").recognize(instance, "var").get_text() == "status and " + expected
|
||||
#
|
||||
# def test_i_can_test_python_code_emitter_for_concepts_with_variable(self):
|
||||
# sheerka, context, greetings, little, foo, bar, and_concept = self.init_concepts(
|
||||
# Concept("greetings", definition="hello a", definition_type=DEFINITION_TYPE_DEF).def_var("a"),
|
||||
# Concept("little x").def_var("x"),
|
||||
# "foo",
|
||||
# "bar",
|
||||
# Concept("a and b").def_var("a").def_var("b")
|
||||
# )
|
||||
#
|
||||
# # variable is a string
|
||||
# greetings_instance = sheerka.new_from_template(greetings, greetings.key, a='sheerka')
|
||||
# expected = "isinstance(var, Concept) and var.key == 'hello __var__0' and var.get_value('a') == 'sheerka'"
|
||||
# text = PythonCodeEmitter(context).recognize(greetings_instance, "var").get_text()
|
||||
# assert text == expected
|
||||
#
|
||||
# # variable is a concept recognized by id
|
||||
# foo_instance = sheerka.new_from_template(foo, foo.key)
|
||||
# foo_instance.get_hints().recognized_by = RECOGNIZED_BY_ID
|
||||
# greetings_instance = sheerka.new_from_template(greetings, greetings.key, a=foo_instance)
|
||||
# expected = """__x_00__ = var.get_value('a')
|
||||
# isinstance(var, Concept) and var.key == 'hello __var__0' and isinstance(__x_00__, Concept) and __x_00__.id == '1003'"""
|
||||
# text = PythonCodeEmitter(context).recognize(greetings_instance, "var").get_text()
|
||||
# assert text == expected
|
||||
#
|
||||
# # variable is a concept recognized by name
|
||||
# foo_instance = sheerka.new_from_template(foo, foo.key)
|
||||
# foo_instance.get_hints().recognized_by = RECOGNIZED_BY_NAME
|
||||
# greetings_instance = sheerka.new_from_template(greetings, greetings.key, a=foo_instance)
|
||||
# expected = """__x_00__ = var.get_value('a')
|
||||
# isinstance(var, Concept) and var.key == 'hello __var__0' and isinstance(__x_00__, Concept) and __x_00__.name == 'foo'"""
|
||||
# text = PythonCodeEmitter(context).recognize(greetings_instance, "var").get_text()
|
||||
# assert text == expected
|
||||
#
|
||||
# # variable is a concept recognized by value
|
||||
# foo_instance = sheerka.new_from_template(foo, foo.key)
|
||||
# greetings_instance = sheerka.new_from_template(greetings, greetings.key, a=foo_instance)
|
||||
# expected = """__x_00__ = var.get_value('a')
|
||||
# isinstance(var, Concept) and var.key == 'hello __var__0' and isinstance(__x_00__, Concept) and __x_00__.key == 'foo'"""
|
||||
# text = PythonCodeEmitter(context).recognize(greetings_instance, "var").get_text()
|
||||
# assert text == expected
|
||||
#
|
||||
# # variable is a concept witch has itself some variable
|
||||
# foo_instance = sheerka.new_from_template(foo, foo.key)
|
||||
# little_instance = sheerka.new_from_template(little, little.key, x=foo_instance)
|
||||
# greetings_instance = sheerka.new_from_template(greetings, greetings.key, a=little_instance)
|
||||
# expected = """__x_00__ = var.get_value('a')
|
||||
# __x_01__ = __x_00__.get_value('x')
|
||||
# isinstance(var, Concept) and var.key == 'hello __var__0'""" + \
|
||||
# " and isinstance(__x_00__, Concept) and __x_00__.key == 'little __var__0'" + \
|
||||
# " and isinstance(__x_01__, Concept) and __x_01__.key == 'foo'"""
|
||||
# text = PythonCodeEmitter(context).recognize(greetings_instance, "var").get_text()
|
||||
# assert text == expected
|
||||
#
|
||||
# # concept with multiple variables (which are themselves concepts)
|
||||
# foo_instance = sheerka.new_from_template(foo, foo.key)
|
||||
# bar_instance = sheerka.new_from_template(bar, bar.key)
|
||||
# little_instance = sheerka.new_from_template(little, little.key, x=foo_instance)
|
||||
# and_instance = sheerka.new_from_template(and_concept, and_concept.key, a=bar_instance, b=little_instance)
|
||||
# greetings_instance = sheerka.new_from_template(greetings, greetings.key, a=and_instance)
|
||||
# expected = """__x_00__ = var.get_value('a')
|
||||
# __x_01__ = __x_00__.get_value('a')
|
||||
# __x_02__ = __x_00__.get_value('b')
|
||||
# __x_03__ = __x_02__.get_value('x')
|
||||
# isinstance(var, Concept) and var.key == 'hello __var__0'""" + \
|
||||
# " and isinstance(__x_00__, Concept) and __x_00__.key == '__var__0 and __var__1'" + \
|
||||
# " and isinstance(__x_01__, Concept) and __x_01__.key == 'bar'" + \
|
||||
# " and isinstance(__x_02__, Concept) and __x_02__.key == 'little __var__0'" + \
|
||||
# " and isinstance(__x_03__, Concept) and __x_03__.key == 'foo'"
|
||||
# text = PythonCodeEmitter(context).recognize(greetings_instance, "var").get_text()
|
||||
# assert text == expected
|
||||
|
||||
@@ -4,6 +4,7 @@ import pytest
|
||||
|
||||
from core.builtin_concepts import ReturnValueConcept
|
||||
from core.builtin_concepts_ids import BuiltinConcepts
|
||||
from core.builtin_helpers import ensure_evaluated
|
||||
from core.concept import Concept, DEFINITION_TYPE_DEF
|
||||
from core.rule import Rule
|
||||
from core.sheerka.services.SheerkaEvaluateRules import SheerkaEvaluateRules
|
||||
@@ -23,6 +24,19 @@ from tests.parsers.parsers_utils import get_rete_conditions, NEGCOND
|
||||
|
||||
|
||||
class BaseTestSheerkaRuleManagerRulesCompilation(TestUsingMemoryBasedSheerka):
|
||||
|
||||
@staticmethod
|
||||
def get_conditions(context, expression):
|
||||
parser = ExpressionParser()
|
||||
error_sink = ErrorSink()
|
||||
parser_input = ParserInput(expression)
|
||||
parser.reset_parser_input(parser_input, error_sink)
|
||||
parsed = parser.parse_input(context, parser_input, error_sink)
|
||||
|
||||
visitor = PythonConditionExprVisitor(context)
|
||||
conditions = visitor.get_conditions(parsed)
|
||||
return conditions
|
||||
|
||||
@staticmethod
|
||||
def check_against_rete(rule_expression, rule_conditions, objects):
|
||||
"""
|
||||
@@ -72,6 +86,9 @@ class BaseTestSheerkaRuleManagerRulesCompilation(TestUsingMemoryBasedSheerka):
|
||||
sub_context.sheerka.add_many_to_short_term_memory(sub_context, objects)
|
||||
|
||||
evaluator = PythonEvaluator()
|
||||
for c in condition.concepts_to_reset:
|
||||
c.get_hints().is_evaluated = False
|
||||
|
||||
return evaluator.eval(sub_context, condition.return_value)
|
||||
|
||||
@classmethod
|
||||
@@ -130,15 +147,7 @@ class BaseTestSheerkaRuleManagerRulesCompilation(TestUsingMemoryBasedSheerka):
|
||||
expected_not_variables,
|
||||
expected_objects):
|
||||
sheerka = context.sheerka
|
||||
|
||||
parser = ExpressionParser()
|
||||
error_sink = ErrorSink()
|
||||
parser_input = ParserInput(expression)
|
||||
parser.reset_parser_input(parser_input, error_sink)
|
||||
parsed = parser.parse_input(context, parser_input, error_sink)
|
||||
|
||||
visitor = PythonConditionExprVisitor(context)
|
||||
conditions = visitor.get_conditions(parsed)
|
||||
conditions = BaseTestSheerkaRuleManagerRulesCompilation.get_conditions(context, expression)
|
||||
|
||||
assert len(conditions) == 1
|
||||
assert isinstance(conditions[0], CompiledCondition)
|
||||
@@ -312,6 +321,132 @@ class TestSheerkaRuleManagerRulesCompilationNotExists(BaseTestSheerkaRuleManager
|
||||
self.check_against_python(context, expression, conditions, objects)
|
||||
|
||||
|
||||
class TestSheerkaRuleManagerRulesCompilationSimplePython(BaseTestSheerkaRuleManagerRulesCompilation):
|
||||
"""
|
||||
Testing Python
|
||||
True
|
||||
False
|
||||
10 + 5
|
||||
'hello world'
|
||||
a + self
|
||||
a + 10
|
||||
a + " world !"
|
||||
a + foo
|
||||
a + twenty one
|
||||
a + my friend
|
||||
"""
|
||||
|
||||
@pytest.mark.parametrize("expression, e_compiled, e_text, e_variables, e_objects, e_result", [
|
||||
(
|
||||
"True",
|
||||
"True",
|
||||
"True",
|
||||
set(),
|
||||
set(),
|
||||
True
|
||||
),
|
||||
(
|
||||
"False",
|
||||
"False",
|
||||
"False",
|
||||
set(),
|
||||
set(),
|
||||
False
|
||||
),
|
||||
(
|
||||
"10 + 5",
|
||||
"__o_00__",
|
||||
"10 + 5",
|
||||
set(),
|
||||
{("__o_00__", 15)},
|
||||
15
|
||||
),
|
||||
(
|
||||
"'hello world'",
|
||||
"__o_00__",
|
||||
"'hello world'",
|
||||
set(),
|
||||
{("__o_00__", 'hello world')},
|
||||
'hello world'
|
||||
),
|
||||
(
|
||||
"a + self",
|
||||
"a + self",
|
||||
"a + self",
|
||||
{("a", 10), ("self", "foo")},
|
||||
set(),
|
||||
15
|
||||
),
|
||||
(
|
||||
"a + 10",
|
||||
"a + 10",
|
||||
"a + 10",
|
||||
{("a", 10)},
|
||||
set(),
|
||||
20
|
||||
),
|
||||
(
|
||||
"a + 'world !'",
|
||||
"a + 'world !'",
|
||||
"a + 'world !'",
|
||||
{("a", "hello ")},
|
||||
set(),
|
||||
"hello world !"
|
||||
),
|
||||
(
|
||||
"a + foo",
|
||||
"a + foo",
|
||||
"a + foo",
|
||||
{("a", 10), ("foo", "foo")},
|
||||
set(),
|
||||
15
|
||||
),
|
||||
(
|
||||
"a + twenty one",
|
||||
"a + __C__twenties__1004__C__",
|
||||
"a + twenty one",
|
||||
{("a", 10)},
|
||||
{"__C__twenties__1004__C__"},
|
||||
31
|
||||
),
|
||||
(
|
||||
"a + my friend",
|
||||
"a + __C__my0friend__1005__C__",
|
||||
"a + my friend",
|
||||
{("a", "hello ")},
|
||||
{'__C__my0friend__1005__C__'},
|
||||
"hello my friend"
|
||||
),
|
||||
])
|
||||
def test_python(self, expression, e_compiled, e_text, e_variables, e_objects, e_result):
|
||||
sheerka, context, foo, one, two, twenties, my_friend = self.init_concepts(
|
||||
Concept("foo", body="5"),
|
||||
Concept("one", body="1"),
|
||||
Concept("two", body="2"),
|
||||
Concept("twenties", definition="'twenty' (one|two)=n", body='20 + n').def_var("n"),
|
||||
Concept("my friend", body="'my friend'"),
|
||||
create_new=True
|
||||
)
|
||||
ensure_evaluated(context, foo, eval_body=True)
|
||||
ensure_evaluated(context, my_friend, eval_body=True)
|
||||
conditions = self.validate_python_test(context,
|
||||
expression,
|
||||
e_compiled,
|
||||
e_text,
|
||||
e_variables,
|
||||
set(),
|
||||
e_objects)
|
||||
|
||||
# check against SheerkaEvaluateRules
|
||||
variables_mapping = {
|
||||
"foo": foo,
|
||||
}
|
||||
namespace = self.get_testing_objects(context, e_variables, variables_mapping)
|
||||
res = self.evaluate_condition(context, expression, conditions[0], namespace)
|
||||
assert res.status
|
||||
assert sheerka.objvalue(res) == e_result
|
||||
|
||||
|
||||
class TestSheerkaRuleManagerRulesCompilationEquality(BaseTestSheerkaRuleManagerRulesCompilation):
|
||||
"""
|
||||
Testing simple equality:
|
||||
@@ -321,6 +456,7 @@ class TestSheerkaRuleManagerRulesCompilationEquality(BaseTestSheerkaRuleManagerR
|
||||
self == sheerka
|
||||
self == BuiltinConcepts.TO_DICT
|
||||
self == hello 'my friend'
|
||||
a == b
|
||||
"""
|
||||
|
||||
@pytest.mark.parametrize("expression, expected_as_list_of_str, expected_variables", [
|
||||
@@ -339,7 +475,12 @@ class TestSheerkaRuleManagerRulesCompilationEquality(BaseTestSheerkaRuleManagerR
|
||||
"#__x_00__|key|'hello __var__0'",
|
||||
"#__x_00__|a|'my friend'"],
|
||||
{("self", "hello_my_friend")}
|
||||
)
|
||||
),
|
||||
# ("a == b",
|
||||
# ["#__x_00__|__name__|'a'",
|
||||
# "#__x_01__|__name__|'b'",
|
||||
# "#__x_00__|__self__|#__x_01__"],
|
||||
# {("a", 10), ("b", 10)}),
|
||||
])
|
||||
def test_rete(self, expression, expected_as_list_of_str, expected_variables):
|
||||
sheerka, context, greetings = self.init_test().with_concepts(
|
||||
@@ -365,23 +506,27 @@ class TestSheerkaRuleManagerRulesCompilationEquality(BaseTestSheerkaRuleManagerR
|
||||
objects = self.get_testing_objects(context, expected_variables, objects_mappings)
|
||||
self.check_against_rete(expression, conditions, objects)
|
||||
|
||||
# KSI: 2021-05-06 The last test done not produce any match because the WME (b, __self__, 10)
|
||||
# is not added to memory.
|
||||
|
||||
@pytest.mark.parametrize("expression, expected_compiled, expected_variables, expected_objects", [
|
||||
("a == 10", "a == __o_00__", {("a", 10)}, {("__o_00__", 10)}),
|
||||
("__ret.status == True", "__ret.status == __o_00__", {"__ret"}, {("__o_00__", True)}),
|
||||
("__ret.status == True", "__ret.status == True", {"__ret"}, set()),
|
||||
("self == 'a'", "self == __o_00__", {("self", 'a')}, {("__o_00__", 'a')}),
|
||||
("self == sheerka", "is_sheerka(self)", {("self", "sheerka")}, {}),
|
||||
(
|
||||
"self == BuiltinConcepts.TO_DICT",
|
||||
"self == __o_00__",
|
||||
"self == BuiltinConcepts.TO_DICT",
|
||||
{("self", BuiltinConcepts.TO_DICT)},
|
||||
{("__o_00__", BuiltinConcepts.TO_DICT)}
|
||||
set()
|
||||
),
|
||||
(
|
||||
"self == hello 'my friend'",
|
||||
"""isinstance(self, Concept) and self.key == 'hello __var__0' and self.a == __o_01__""",
|
||||
{("self", "hello_my_friend")},
|
||||
{("__o_01__", "my friend")}
|
||||
)
|
||||
),
|
||||
("a == b", "a == b", {("a", 10), ("b", 10)}, {}),
|
||||
])
|
||||
def test_python(self, expression, expected_compiled, expected_variables, expected_objects):
|
||||
sheerka, context, greetings = self.init_test().with_concepts(
|
||||
@@ -403,6 +548,176 @@ class TestSheerkaRuleManagerRulesCompilationEquality(BaseTestSheerkaRuleManagerR
|
||||
self.check_against_python(context, expression, conditions, objects)
|
||||
|
||||
|
||||
class TestSheerkaRuleManagerRulesCompilationOtherConditions(BaseTestSheerkaRuleManagerRulesCompilation):
|
||||
"""
|
||||
Testing other conditions than equality
|
||||
a > 10
|
||||
a >= 10
|
||||
a < 10
|
||||
a <= 10
|
||||
a != 10
|
||||
a > 10 and b <= 5
|
||||
|
||||
__ret.value > 10
|
||||
10 > __ret.value
|
||||
|
||||
a + self > 10
|
||||
a + 10 > 10
|
||||
a + " world !" == "hello world !"
|
||||
a + foo > 10
|
||||
a + twenty one > 21
|
||||
a + my friend == 'hello my friend'
|
||||
|
||||
10 < a + self
|
||||
10 < a + 10
|
||||
'hello world !' == a + ' world !'
|
||||
10 < a + foo
|
||||
10 > a + twenty one
|
||||
'hello my friend' == a + my friend
|
||||
"""
|
||||
|
||||
@pytest.mark.parametrize("expression, e_compiled, e_variables, e_objects, e_result", [
|
||||
("a > 10", "a > __o_00__", {("a", 10)}, {("__o_00__", 10)}, False),
|
||||
("a >= 10", "a >= __o_00__", {("a", 10)}, {("__o_00__", 10)}, True),
|
||||
("a < 10", "a < __o_00__", {("a", 10)}, {("__o_00__", 10)}, False),
|
||||
("a <= 10", "a <= __o_00__", {("a", 10)}, {("__o_00__", 10)}, True),
|
||||
("a != 10", "a != __o_00__", {("a", 10)}, {("__o_00__", 10)}, False),
|
||||
(
|
||||
"a > 10 and b <= 5",
|
||||
"a > __o_00__ and b <= __o_01__",
|
||||
{("a", 11), ("b", 4)},
|
||||
{("__o_00__", 10), ("__o_01__", 5)},
|
||||
True
|
||||
),
|
||||
(
|
||||
"__ret.value > 10",
|
||||
"__ret.value > __o_00__",
|
||||
{("__ret", 15)},
|
||||
{("__o_00__", 10)},
|
||||
True
|
||||
),
|
||||
(
|
||||
"10 > __ret.value",
|
||||
"__o_00__ > __ret.value",
|
||||
{("__ret", 15)},
|
||||
{("__o_00__", 10)},
|
||||
False
|
||||
),
|
||||
(
|
||||
"a + self > 10",
|
||||
"a + self > __o_00__",
|
||||
{("a", 6), ("self", "foo")},
|
||||
{("__o_00__", 10)},
|
||||
True
|
||||
),
|
||||
(
|
||||
"a + 10 > 10",
|
||||
"a + 10 > __o_00__",
|
||||
{("a", 5)},
|
||||
{("__o_00__", 10)},
|
||||
True
|
||||
),
|
||||
(
|
||||
"a + 'world !' == 'hello world !'",
|
||||
"a + 'world !' == __o_00__",
|
||||
{("a", "hello ")},
|
||||
{("__o_00__", 'hello world !')},
|
||||
True
|
||||
),
|
||||
(
|
||||
"a + foo > 10",
|
||||
"a + foo > __o_00__",
|
||||
{("a", 6), ("foo", "foo")},
|
||||
{("__o_00__", 10)},
|
||||
True
|
||||
),
|
||||
(
|
||||
"a + twenty one > 21",
|
||||
"a + __C__twenties__1004__C__ > __o_00__",
|
||||
{("a", 5)},
|
||||
{"__C__twenties__1004__C__", ("__o_00__", 21)},
|
||||
True
|
||||
),
|
||||
(
|
||||
"a + my friend == 'hello my friend'",
|
||||
"a + __C__my0friend__1005__C__ == __o_00__",
|
||||
{("a", "hello ")},
|
||||
{"__C__my0friend__1005__C__", ("__o_00__", 'hello my friend')},
|
||||
True
|
||||
),
|
||||
|
||||
(
|
||||
"10 < a + self",
|
||||
"__o_00__ < a + self",
|
||||
{("a", 6), ("self", "foo")},
|
||||
{("__o_00__", 10)},
|
||||
True
|
||||
),
|
||||
(
|
||||
"10 > a + 10",
|
||||
"__o_00__ > a + 10",
|
||||
{("a", 5)},
|
||||
{("__o_00__", 10)},
|
||||
False
|
||||
),
|
||||
(
|
||||
"'hello world !' != a + 'world !'",
|
||||
"__o_00__ != a + 'world !'",
|
||||
{("a", "hello ")},
|
||||
{("__o_00__", 'hello world !')},
|
||||
False
|
||||
),
|
||||
(
|
||||
"10 < a + foo",
|
||||
"__o_00__ < a + foo",
|
||||
{("a", 6), ("foo", "foo")},
|
||||
{("__o_00__", 10)},
|
||||
True
|
||||
),
|
||||
(
|
||||
"21 > a + twenty one",
|
||||
"__o_00__ > a + __C__twenties__1004__C__",
|
||||
{("a", 5)},
|
||||
{"__C__twenties__1004__C__", ("__o_00__", 21)},
|
||||
False
|
||||
),
|
||||
(
|
||||
"'hello my friend' == a + my friend",
|
||||
"__o_00__ == a + __C__my0friend__1005__C__",
|
||||
{("a", "hello ")},
|
||||
{"__C__my0friend__1005__C__", ("__o_00__", 'hello my friend')},
|
||||
True
|
||||
),
|
||||
|
||||
])
|
||||
def test_python(self, expression, e_compiled, e_variables, e_objects, e_result):
|
||||
sheerka, context, foo, one, two, twenties, my_friend = self.init_concepts(
|
||||
Concept("foo", body="5"),
|
||||
Concept("one", body="1"),
|
||||
Concept("two", body="2"),
|
||||
Concept("twenties", definition="'twenty' (one|two)=n", body='20 + n').def_var("n"),
|
||||
Concept("my friend", body="'my friend'"),
|
||||
create_new=True
|
||||
)
|
||||
ensure_evaluated(context, foo, eval_body=True)
|
||||
ensure_evaluated(context, my_friend, eval_body=True)
|
||||
|
||||
conditions = self.validate_python_test(context,
|
||||
expression,
|
||||
e_compiled,
|
||||
expression,
|
||||
e_variables,
|
||||
set(),
|
||||
e_objects)
|
||||
|
||||
# check against SheerkaEvaluateRules
|
||||
variables_mapping = {
|
||||
"foo": foo,
|
||||
}
|
||||
objects = self.get_testing_objects(context, e_variables, variables_mapping)
|
||||
self.check_against_python(context, expression, conditions, objects, expected_result=e_result)
|
||||
|
||||
|
||||
class TestSheerkaRuleManagerRulesCompilationFunctionsCall(BaseTestSheerkaRuleManagerRulesCompilation):
|
||||
"""
|
||||
Testing functions
|
||||
@@ -795,6 +1110,8 @@ class TestSheerkaRuleManagerRulesCompilationEvalQuestionConcept(BaseTestSheerkaR
|
||||
with long concept : the little boy is a human being
|
||||
with long concept + variable : the little boy is a self
|
||||
with long concept + variable : self is a human being
|
||||
with a special symbol : self is a 'human'
|
||||
with a special symbol : the little boy is a 'human'
|
||||
"""
|
||||
|
||||
def test_rete(self):
|
||||
@@ -826,6 +1143,16 @@ class TestSheerkaRuleManagerRulesCompilationEvalQuestionConcept(BaseTestSheerkaR
|
||||
"evaluate_question(__o_00__)",
|
||||
{"self"},
|
||||
),
|
||||
(
|
||||
"self is a 'human'",
|
||||
"evaluate_question(__o_00__)",
|
||||
{"self"},
|
||||
),
|
||||
(
|
||||
"the little boy is a 'human'",
|
||||
"evaluate_question(__o_00__)",
|
||||
set(),
|
||||
),
|
||||
])
|
||||
def test_python(self, expression, expected_compiled, expected_variables):
|
||||
sheerka, context, girl, human, little_boy, human_being, isa = self.init_test().with_concepts(
|
||||
@@ -980,11 +1307,11 @@ class TestSheerkaRuleManagerRulesCompilationEvalConceptMixedWithOther(BaseTestSh
|
||||
expected_objects)
|
||||
|
||||
# check against SheerkaEvaluateRules
|
||||
variable_mapping = {
|
||||
variables_mapping = {
|
||||
"girl": girl,
|
||||
"human being": human_being
|
||||
}
|
||||
testing_objects = self.get_testing_objects(context, expected_variables, variable_mapping)
|
||||
testing_objects = self.get_testing_objects(context, expected_variables, variables_mapping)
|
||||
self.check_against_python(context,
|
||||
expression,
|
||||
conditions,
|
||||
@@ -1005,6 +1332,8 @@ class TestSheerkaRuleManagerRulesCompilationEvalNonQuestionConcept(BaseTestSheer
|
||||
with function: func_identity(twenty two + twenty one)
|
||||
with function: func_identity(twenty two plus one)
|
||||
with function: func_identity(twenty two plus twenty one)
|
||||
with special char : 'one' plus 'two'
|
||||
with special char : twenty two plus 2
|
||||
"""
|
||||
|
||||
def test_rete(self):
|
||||
@@ -1081,6 +1410,20 @@ class TestSheerkaRuleManagerRulesCompilationEvalNonQuestionConcept(BaseTestSheer
|
||||
{"__o_00__"},
|
||||
43
|
||||
),
|
||||
(
|
||||
"'one' plus 'two'",
|
||||
"__o_00__",
|
||||
"'one' plus 'two'",
|
||||
{"__o_00__"},
|
||||
'onetwo'
|
||||
),
|
||||
(
|
||||
"twenty two plus 2",
|
||||
"__o_00__",
|
||||
"twenty two plus 2",
|
||||
{"__o_00__"},
|
||||
24
|
||||
),
|
||||
])
|
||||
def test_python(self, expression, e_compiled, e_text, e_objects, e_result):
|
||||
sheerka, context, one, two, twenties, plus = self.init_test().with_concepts(
|
||||
@@ -1109,7 +1452,7 @@ class TestSheerkaRuleManagerRulesCompilationEvalNonQuestionConcept(BaseTestSheer
|
||||
class TestSheerkaRuleManagerRulesCompilationMultipleSameConcept(BaseTestSheerkaRuleManagerRulesCompilation):
|
||||
"""
|
||||
Test when a concept returns multiple results
|
||||
The compilation should fail : No need to execute a condition if we are not sure of the meaning ?
|
||||
The compilation should fail : No need to execute a condition if we are not sure of the meaning
|
||||
self is a bar
|
||||
"""
|
||||
|
||||
@@ -1156,6 +1499,99 @@ class TestSheerkaRuleManagerRulesCompilationNot(BaseTestSheerkaRuleManagerRulesC
|
||||
Testing not
|
||||
not __ret.status == True
|
||||
not recognize(__ret.body, hello sheerka)
|
||||
not a cat is a pet and not bird is an animal # where x is a y is a concept
|
||||
not a cat is a pet and not x > 5 # concept mixed with python
|
||||
|
||||
"""
|
||||
pass
|
||||
|
||||
|
||||
class TestCompiledCondition(BaseTestSheerkaRuleManagerRulesCompilation):
|
||||
@pytest.mark.parametrize("expression, expected", [
|
||||
("self is a 'foo'", {"x is a y"}),
|
||||
("set self is a 'foo'", set()),
|
||||
])
|
||||
def test_i_can_get_concept_to_reset(self, expression, expected):
|
||||
"""
|
||||
When compiled conditions, sometimes there are concepts to reset between two usages
|
||||
:param expression:
|
||||
:param expected:
|
||||
:return:
|
||||
"""
|
||||
sheerka, context, question, not_a_question = self.init_concepts(
|
||||
Concept("x is a y", pre="is_question()").def_var("x").def_var("y"),
|
||||
Concept("set x is a y").def_var("x").def_var("y"),
|
||||
)
|
||||
|
||||
conditions = self.get_conditions(context, expression)
|
||||
|
||||
assert len(conditions) == 1
|
||||
assert set(c.name for c in conditions[0].concepts_to_reset) == expected
|
||||
|
||||
def test_i_can_reset_concepts_when_multiple_levels(self):
|
||||
"""
|
||||
When compiled conditions, sometimes there are concepts to reset between two usages
|
||||
:return:
|
||||
"""
|
||||
sheerka, context, is_instance, is_int, is_integer = self.init_concepts(
|
||||
Concept("x is an instance of y", pre="is_question()", body="isinstance(x, y)").def_var("x").def_var("y"),
|
||||
Concept("x is a int", pre="is_question()", body="x is an instance of int").def_var("x"),
|
||||
Concept("x is an integer", pre="is_question()", body="x is a int").def_var("x"),
|
||||
)
|
||||
|
||||
expression = "self is an integer"
|
||||
conditions = conditions = self.get_conditions(context, expression)
|
||||
|
||||
assert len(conditions) == 1
|
||||
assert set(c.name for c in conditions[0].concepts_to_reset) == {"x is an instance of y",
|
||||
"x is a int",
|
||||
"x is an integer"}
|
||||
|
||||
# So I can evaluate multiple times
|
||||
res = self.evaluate_condition(context, expression, conditions[0], {'self': 10})
|
||||
assert res.status
|
||||
assert sheerka.objvalue(res.body)
|
||||
|
||||
res = self.evaluate_condition(context, expression, conditions[0], {'self': "string"})
|
||||
assert res.status
|
||||
assert not sheerka.objvalue(res.body)
|
||||
|
||||
def test_i_can_reset_concepts_when_multiple_levels_and_concept_node(self):
|
||||
"""
|
||||
When compiled conditions, sometimes there are concepts to reset between two usages
|
||||
:return:
|
||||
"""
|
||||
# in this example, x + 2 is an int won't be parsed as an ExactNodeConcept, but as a ConceptNode
|
||||
sheerka, context, is_int, is_integer = self.init_concepts(
|
||||
Concept("x is a int", pre="is_question()", body="isinstance(x, int)").def_var("x"),
|
||||
Concept("x is an integer", pre="is_question()", body="x + 2 is a int").def_var("x"),
|
||||
create_new=True
|
||||
)
|
||||
|
||||
expression = "self is an integer"
|
||||
conditions = self.get_conditions(context, expression)
|
||||
|
||||
assert len(conditions) == 1
|
||||
assert set(c.name for c in conditions[0].concepts_to_reset) == {"x is a int",
|
||||
"x is an integer"}
|
||||
|
||||
# So I can evaluate multiple times
|
||||
res = self.evaluate_condition(context, expression, conditions[0], {'self': 10})
|
||||
assert res.status
|
||||
assert sheerka.objvalue(res.body)
|
||||
|
||||
res = self.evaluate_condition(context, expression, conditions[0], {'self': "string"})
|
||||
assert not res.status
|
||||
|
||||
def test_long_name_concept_set_are_not_considered_as_variables(self):
|
||||
sheerka, context, one, number = self.init_concepts(
|
||||
"one",
|
||||
"all numbers",
|
||||
)
|
||||
sheerka.set_isa(context, one, number)
|
||||
|
||||
expression = "all numbers < 5"
|
||||
conditions = self.get_conditions(context, expression)
|
||||
|
||||
assert len(conditions) == 1
|
||||
assert conditions[0].return_value.body.body.source == '__o_00__ < __o_01__'
|
||||
|
||||
@@ -4,6 +4,13 @@ import core.builtin_helpers
|
||||
from core.builtin_concepts import ReturnValueConcept, BuiltinConcepts
|
||||
from core.concept import Concept
|
||||
from core.global_symbols import NotInit
|
||||
from core.sheerka.services.SheerkaExecute import ParserInput
|
||||
from core.tokenizer import Tokenizer
|
||||
from evaluators.BaseEvaluator import BaseEvaluator
|
||||
from evaluators.ValidateConceptEvaluator import ValidateConceptEvaluator
|
||||
from parsers.BaseNodeParser import ConceptNode
|
||||
from parsers.BaseParser import BaseParser
|
||||
from parsers.SyaNodeParser import SyaNodeParser
|
||||
from tests.TestUsingMemoryBasedSheerka import TestUsingMemoryBasedSheerka
|
||||
|
||||
|
||||
@@ -162,6 +169,7 @@ class TestBuiltinHelpers(TestUsingMemoryBasedSheerka):
|
||||
(" is_question ( ) ", True),
|
||||
("context.in_context(BuiltinConcepts.EVAL_QUESTION_REQUESTED)", True),
|
||||
(" context . in_context ( BuiltinConcepts . EVAL_QUESTION_REQUESTED ) ", True),
|
||||
("in_context(BuiltinConcepts.EVAL_QUESTION_REQUESTED)", True),
|
||||
(None, False),
|
||||
("", False),
|
||||
(NotInit, False),
|
||||
@@ -193,6 +201,58 @@ class TestBuiltinHelpers(TestUsingMemoryBasedSheerka):
|
||||
evaluated = [r for r in res if r.status][0].body
|
||||
assert evaluated.body is NotInit
|
||||
|
||||
def test_i_can_evaluate_from_source_with_specific_evaluators(self):
|
||||
sheerka, context, one = self.init_concepts(Concept("foo", body="'hello world'"))
|
||||
|
||||
res = core.builtin_helpers.evaluate_from_source(context, "foo", eval_body=True, evaluators=["Python"])
|
||||
res = self.successful_return_values(res)
|
||||
assert len(res) == 1
|
||||
assert res[0].who.startswith(BaseParser.PREFIX) # Cannot evaluate concept with PythonEvaluator
|
||||
|
||||
res = core.builtin_helpers.evaluate_from_source(context, "foo", eval_body=True, evaluators=["Concept"])
|
||||
res = self.successful_return_values(res)
|
||||
assert len(res) == 1
|
||||
assert res[0].who == BaseEvaluator.PREFIX + "Concept"
|
||||
assert sheerka.isinstance(res[0].body.body,
|
||||
BuiltinConcepts.PARSER_RESULT) # cannot eval 'hello world' without PythonEvaluator
|
||||
|
||||
res = core.builtin_helpers.evaluate_from_source(context, "foo", eval_body=True,
|
||||
evaluators=["Concept", "Python"])
|
||||
res = self.successful_return_values(res)
|
||||
assert len(res) == 1
|
||||
assert res[0].who == BaseEvaluator.PREFIX + "Concept"
|
||||
assert res[0].body.body == "hello world"
|
||||
|
||||
def test_i_can_get_lexer_nodes_after_parsing_validation(self):
|
||||
sheerka, context, the, foo = self.init_concepts(
|
||||
Concept("the x", ret="x", where="isinstance(x, Concept)").def_var("x"),
|
||||
"foo",
|
||||
create_new=True)
|
||||
|
||||
parsed_ret_val = SyaNodeParser().parse(context, ParserInput("the foo"))
|
||||
validated_ret_val = ValidateConceptEvaluator().eval(context, parsed_ret_val)
|
||||
|
||||
res = core.builtin_helpers.get_lexer_nodes([validated_ret_val], 0, list(Tokenizer("the foo", yield_eof=False)))
|
||||
|
||||
assert isinstance(res, list)
|
||||
assert isinstance(res[0][0], ConceptNode)
|
||||
|
||||
def test_ensure_evaluated_returns_the_ret_value(self):
|
||||
"""
|
||||
When a concept has a RET defined, make sure to return it
|
||||
:return:
|
||||
"""
|
||||
|
||||
sheerka, context, foo, bar = self.init_concepts(
|
||||
"foo",
|
||||
Concept("bar", ret="foo")
|
||||
)
|
||||
|
||||
assert core.builtin_helpers.ensure_evaluated(context, bar) == foo
|
||||
|
||||
# a second time, now that bar is already evaluated
|
||||
assert core.builtin_helpers.ensure_evaluated(context, bar) == foo
|
||||
|
||||
# @pytest.mark.parametrize("return_values", [
|
||||
# None,
|
||||
# []
|
||||
|
||||
@@ -75,7 +75,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.get_metadata().is_evaluated
|
||||
assert loaded.get_hints().is_evaluated
|
||||
|
||||
def test_i_cannot_get_when_id_is_not_found(self):
|
||||
sheerka = self.get_sheerka()
|
||||
@@ -85,7 +85,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.get_metadata().is_evaluated
|
||||
assert loaded.get_hints().is_evaluated
|
||||
|
||||
def test_i_can_instantiate_a_builtin_concept_when_it_has_its_own_class(self):
|
||||
sheerka = self.get_sheerka()
|
||||
@@ -192,15 +192,15 @@ class TestSheerkaUsingMemoryBasedSheerka(TestUsingMemoryBasedSheerka):
|
||||
create_new=True).unpack()
|
||||
|
||||
sheerka.evaluate_concept(context, sheerka.get_by_id(template.id))
|
||||
assert template.get_metadata().is_evaluated
|
||||
assert template.get_hints().is_evaluated
|
||||
assert template.body == "foo body"
|
||||
|
||||
new = sheerka.new(template.key)
|
||||
assert not new.get_metadata().is_evaluated
|
||||
assert not new.get_hints().is_evaluated
|
||||
assert new.body == NotInit
|
||||
|
||||
new = sheerka.new((None, template.id))
|
||||
assert not new.get_metadata().is_evaluated
|
||||
assert not new.get_hints().is_evaluated
|
||||
assert new.body == NotInit
|
||||
|
||||
def test_i_cannot_instantiate_an_unknown_concept(self):
|
||||
|
||||
@@ -287,7 +287,7 @@ class TestSheerkaExecuteEvaluators(TestUsingMemoryBasedSheerka):
|
||||
assert groups == {20: [EvaluatorOneWithPriority20()], 15: [EvaluatorAllWithPriority15()]}
|
||||
assert sorted_priorities == [20, 15]
|
||||
|
||||
key = BuiltinConcepts.EVALUATION + "|" + "|".join(evaluators_names)
|
||||
key = (BuiltinConcepts.EVALUATION, "|".join(evaluators_names))
|
||||
assert key in service.grouped_evaluators_cache
|
||||
groups, sorted_priorities = service.grouped_evaluators_cache[key]
|
||||
assert groups == {20: [EvaluatorOneWithPriority20()], 15: [EvaluatorAllWithPriority15()]}
|
||||
@@ -343,7 +343,7 @@ class TestSheerkaExecuteEvaluators(TestUsingMemoryBasedSheerka):
|
||||
assert groups == {99: [EvaluatorAllWithPriority15(99)]}
|
||||
assert sorted_priorities == [99]
|
||||
|
||||
key = BuiltinConcepts.EVALUATION + "|" + "|".join(evaluators_names)
|
||||
key = (BuiltinConcepts.EVALUATION, "|".join(evaluators_names))
|
||||
assert key not in service.grouped_evaluators_cache
|
||||
|
||||
def test_i_can_revert_back_evaluators_alterations(self):
|
||||
@@ -570,7 +570,7 @@ class TestSheerkaExecuteEvaluators(TestUsingMemoryBasedSheerka):
|
||||
|
||||
# grouped evaluator is in cache
|
||||
service = sheerka.services[SheerkaExecute.NAME]
|
||||
assert "__EVALUATION|all_priority10" in service.grouped_evaluators_cache
|
||||
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()
|
||||
|
||||
@@ -1,14 +1,38 @@
|
||||
from core.builtin_concepts import ReturnValueConcept, UserInputConcept, BuiltinConcepts, ParserResultConcept
|
||||
from core.sheerka.services.SheerkaExecute import ParserInput, SheerkaExecute
|
||||
from parsers.BaseParser import BaseParser
|
||||
import pytest
|
||||
|
||||
from core.builtin_concepts import ReturnValueConcept, UserInputConcept, BuiltinConcepts, ParserResultConcept
|
||||
from core.concept import Concept
|
||||
from core.sheerka.services.SheerkaExecute import ParserInput, SheerkaExecute, DEFAULT, PARSE_STEPS
|
||||
from parsers.BaseExpressionParser import ExprNode
|
||||
from parsers.BaseParser import BaseParser
|
||||
from parsers.BnfNodeParser import BnfNodeParser
|
||||
from parsers.SequenceNodeParser import SequenceNodeParser
|
||||
from parsers.SyaNodeParser import SyaNodeParser
|
||||
from tests.TestUsingMemoryBasedSheerka import TestUsingMemoryBasedSheerka
|
||||
|
||||
|
||||
def get_ret_val(text, who="who"):
|
||||
def get_user_input(text, who="who"):
|
||||
return ReturnValueConcept(who, True, UserInputConcept(text, "user_name"))
|
||||
|
||||
|
||||
def check_same_results(result1, result2, user_input):
|
||||
assert len(result1) == len(result2)
|
||||
for previous, current in zip(result1, result2):
|
||||
assert current.parents == user_input
|
||||
assert current.who == previous.who
|
||||
assert current.status == previous.status
|
||||
assert id(current.body) == id(previous.body)
|
||||
|
||||
|
||||
def check_same_values(sheerka, context, ret_val1, ret_val2):
|
||||
previous = sheerka.execute(context, ret_val1, [BuiltinConcepts.EVALUATION])
|
||||
current = sheerka.execute(context, ret_val2, [BuiltinConcepts.EVALUATION])
|
||||
|
||||
assert len(previous) == len(current)
|
||||
for p, c in zip(previous, current):
|
||||
assert p == c
|
||||
|
||||
|
||||
class BaseTestParser(BaseParser):
|
||||
debug_out = []
|
||||
|
||||
@@ -136,12 +160,23 @@ class ListOfNoneParser(BaseTestParser):
|
||||
|
||||
|
||||
class TestSheerkaExecuteParsers(TestUsingMemoryBasedSheerka):
|
||||
default_parsers = None
|
||||
|
||||
@classmethod
|
||||
def setup_class(cls):
|
||||
cls.default_parsers = cls().get_sheerka().parsers
|
||||
|
||||
@classmethod
|
||||
def teardown_class(cls):
|
||||
# At the end of the tests, sheerka singleton instance will be corrupted
|
||||
# Ask for a new one
|
||||
TestUsingMemoryBasedSheerka.sheerka = None
|
||||
|
||||
def reset_parsers(self, sheerka):
|
||||
sheerka.parsers = self.default_parsers
|
||||
service = sheerka.services[SheerkaExecute.NAME]
|
||||
service.reset_registered_parsers()
|
||||
|
||||
def test_i_can_get_parser_when_context_is_not_altered(self):
|
||||
sheerka, context = self.init_concepts()
|
||||
sheerka.parsers = {
|
||||
@@ -152,7 +187,7 @@ class TestSheerkaExecuteParsers(TestUsingMemoryBasedSheerka):
|
||||
service.reset_registered_parsers()
|
||||
|
||||
parsers_key, groups, sorted_priorities = service.get_parsers(context)
|
||||
assert parsers_key == "__default"
|
||||
assert parsers_key == ("__default", "__default")
|
||||
assert groups == {80: [Enabled80FalseParser()], 90: [Enabled90FalseParser()]}
|
||||
assert sorted_priorities == [90, 80]
|
||||
|
||||
@@ -171,13 +206,13 @@ class TestSheerkaExecuteParsers(TestUsingMemoryBasedSheerka):
|
||||
context.preprocess_parsers = parsers_names
|
||||
|
||||
parsers_key, groups, sorted_priorities = service.get_parsers(context)
|
||||
assert parsers_key == "Enabled50True|Enabled70False|Disabled"
|
||||
assert parsers_key == (DEFAULT, "Enabled50True|Enabled70False|Disabled")
|
||||
assert groups == {50: [Enabled50TrueParser()], 70: [Enabled70FalseParser()]}
|
||||
assert sorted_priorities == [70, 50] # Disabled parser does not appear
|
||||
|
||||
key = "|".join(parsers_names)
|
||||
assert key in service.grouped_parsers_cache
|
||||
groups, sorted_priorities = service.grouped_parsers_cache[key]
|
||||
assert (DEFAULT, key) in service.grouped_parsers_cache
|
||||
groups, sorted_priorities = service.grouped_parsers_cache[(DEFAULT, key)]
|
||||
assert groups == {50: [Enabled50TrueParser], 70: [Enabled70FalseParser]}
|
||||
assert sorted_priorities == [70, 50]
|
||||
|
||||
@@ -202,8 +237,8 @@ class TestSheerkaExecuteParsers(TestUsingMemoryBasedSheerka):
|
||||
assert groups == {80: [Enabled50TrueParser()], 70: [Enabled70FalseParser()]}
|
||||
assert sorted_priorities == [80, 70] # Disabled parsers does not appear
|
||||
|
||||
key = "|".join(parsers_names)
|
||||
assert key not in service.grouped_parsers_cache # not saved in cache
|
||||
key = (DEFAULT, "|".join(parsers_names))
|
||||
assert key not in service.grouped_parsers_cache # not saved in cache
|
||||
|
||||
def test_disabled_parsers_are_not_executed(self):
|
||||
sheerka = self.get_sheerka()
|
||||
@@ -214,7 +249,7 @@ class TestSheerkaExecuteParsers(TestUsingMemoryBasedSheerka):
|
||||
service = sheerka.services[SheerkaExecute.NAME]
|
||||
service.reset_registered_parsers()
|
||||
|
||||
user_input = [get_ret_val("hello world")]
|
||||
user_input = [get_user_input("hello world")]
|
||||
BaseTestParser.debug_out = []
|
||||
sheerka.execute(self.get_context(sheerka), user_input, [BuiltinConcepts.PARSING])
|
||||
|
||||
@@ -230,7 +265,7 @@ class TestSheerkaExecuteParsers(TestUsingMemoryBasedSheerka):
|
||||
service = sheerka.services[SheerkaExecute.NAME]
|
||||
service.reset_registered_parsers()
|
||||
|
||||
user_input = [get_ret_val("hello world")]
|
||||
user_input = [get_user_input("hello world")]
|
||||
BaseTestParser.debug_out = []
|
||||
sheerka.execute(self.get_context(sheerka), user_input, [BuiltinConcepts.PARSING])
|
||||
|
||||
@@ -254,7 +289,7 @@ class TestSheerkaExecuteParsers(TestUsingMemoryBasedSheerka):
|
||||
service = sheerka.services[SheerkaExecute.NAME]
|
||||
service.reset_registered_parsers()
|
||||
|
||||
user_input = [get_ret_val("hello world")]
|
||||
user_input = [get_user_input("hello world")]
|
||||
BaseTestParser.debug_out = []
|
||||
sheerka.execute(self.get_context(sheerka), user_input, [BuiltinConcepts.PARSING])
|
||||
|
||||
@@ -279,7 +314,7 @@ class TestSheerkaExecuteParsers(TestUsingMemoryBasedSheerka):
|
||||
service = sheerka.services[SheerkaExecute.NAME]
|
||||
service.reset_registered_parsers()
|
||||
|
||||
user_input = [get_ret_val("hello world")]
|
||||
user_input = [get_user_input("hello world")]
|
||||
BaseTestParser.debug_out = []
|
||||
sheerka.execute(self.get_context(sheerka), user_input, [BuiltinConcepts.PARSING])
|
||||
|
||||
@@ -310,7 +345,7 @@ class TestSheerkaExecuteParsers(TestUsingMemoryBasedSheerka):
|
||||
service = sheerka.services[SheerkaExecute.NAME]
|
||||
service.reset_registered_parsers()
|
||||
|
||||
user_input = [get_ret_val("hello world")]
|
||||
user_input = [get_user_input("hello world")]
|
||||
BaseTestParser.debug_out = []
|
||||
sheerka.execute(self.get_context(sheerka), user_input, [BuiltinConcepts.PARSING])
|
||||
|
||||
@@ -342,7 +377,7 @@ class TestSheerkaExecuteParsers(TestUsingMemoryBasedSheerka):
|
||||
service = sheerka.services[SheerkaExecute.NAME]
|
||||
service.reset_registered_parsers()
|
||||
|
||||
user_input = [get_ret_val("hello world")]
|
||||
user_input = [get_user_input("hello world")]
|
||||
|
||||
res = sheerka.execute(self.get_context(sheerka), user_input, [BuiltinConcepts.PARSING])
|
||||
res_as_tuple = [(str(r.who)[8:], r.status, r.body.body) for r in res]
|
||||
@@ -365,7 +400,7 @@ class TestSheerkaExecuteParsers(TestUsingMemoryBasedSheerka):
|
||||
service = sheerka.services[SheerkaExecute.NAME]
|
||||
service.reset_registered_parsers()
|
||||
|
||||
user_input = [get_ret_val("hello world")]
|
||||
user_input = [get_user_input("hello world")]
|
||||
|
||||
BaseTestParser.debug_out = []
|
||||
res = sheerka.execute(self.get_context(sheerka), user_input, [BuiltinConcepts.PARSING])
|
||||
@@ -391,7 +426,7 @@ class TestSheerkaExecuteParsers(TestUsingMemoryBasedSheerka):
|
||||
service = sheerka.services[SheerkaExecute.NAME]
|
||||
service.reset_registered_parsers()
|
||||
|
||||
user_input = [get_ret_val("hello world")]
|
||||
user_input = [get_user_input("hello world")]
|
||||
BaseTestParser.debug_out = []
|
||||
sheerka.execute(self.get_context(sheerka), user_input, [BuiltinConcepts.PARSING])
|
||||
|
||||
@@ -412,7 +447,7 @@ class TestSheerkaExecuteParsers(TestUsingMemoryBasedSheerka):
|
||||
service = sheerka.services[SheerkaExecute.NAME]
|
||||
service.reset_registered_parsers()
|
||||
|
||||
user_input = [get_ret_val("hello world")]
|
||||
user_input = [get_user_input("hello world")]
|
||||
BaseTestParser.debug_out = []
|
||||
res = sheerka.execute(self.get_context(sheerka), user_input, [BuiltinConcepts.PARSING])
|
||||
|
||||
@@ -432,7 +467,7 @@ class TestSheerkaExecuteParsers(TestUsingMemoryBasedSheerka):
|
||||
('Enabled50True', False, 'Enabled50True:Enabled80MultipleFalse:hello world_2'),
|
||||
]
|
||||
|
||||
def test_i_can_manage_parser_with_multiple_results_and_a_sucess(self):
|
||||
def test_i_can_manage_parser_with_multiple_results_and_a_success(self):
|
||||
sheerka = self.get_sheerka()
|
||||
sheerka.parsers = {
|
||||
"Enabled80MultipleTrue": Enabled80MultipleTrueParser,
|
||||
@@ -441,7 +476,7 @@ class TestSheerkaExecuteParsers(TestUsingMemoryBasedSheerka):
|
||||
service = sheerka.services[SheerkaExecute.NAME]
|
||||
service.reset_registered_parsers()
|
||||
|
||||
user_input = [get_ret_val("hello world")]
|
||||
user_input = [get_user_input("hello world")]
|
||||
BaseTestParser.debug_out = []
|
||||
res = sheerka.execute(self.get_context(sheerka), user_input, [BuiltinConcepts.PARSING])
|
||||
|
||||
@@ -454,3 +489,390 @@ class TestSheerkaExecuteParsers(TestUsingMemoryBasedSheerka):
|
||||
('Enabled80MultipleTrue', True, 'Enabled80MultipleTrue:hello world_1'),
|
||||
('Enabled80MultipleTrue', False, 'Enabled80MultipleTrue:hello world_2'),
|
||||
]
|
||||
|
||||
def test_parser_calls_are_put_in_cache(self):
|
||||
sheerka, context = self.init_test().unpack()
|
||||
service = sheerka.services[SheerkaExecute.NAME]
|
||||
self.reset_parsers(sheerka)
|
||||
|
||||
user_input = [get_user_input("1")]
|
||||
res = sheerka.execute(context, user_input, [BuiltinConcepts.PARSING])
|
||||
|
||||
assert len(res) > 0
|
||||
assert len(service.parsers_cache.cache) == 1
|
||||
assert (('__default', '__default'), '1') in service.parsers_cache
|
||||
|
||||
def test_parser_calls_are_put_in_cache_when_question(self):
|
||||
sheerka, context = self.init_test().unpack()
|
||||
service = sheerka.services[SheerkaExecute.NAME]
|
||||
self.reset_parsers(sheerka)
|
||||
context.add_to_protected_hints(BuiltinConcepts.EVAL_QUESTION_REQUESTED)
|
||||
|
||||
user_input = [get_user_input("1")]
|
||||
res = sheerka.execute(context, user_input, [BuiltinConcepts.PARSING])
|
||||
|
||||
assert len(res) > 0
|
||||
assert len(service.parsers_cache.cache) == 2 # one for EVAL_QUESTION, one to compile the Python
|
||||
assert ((BuiltinConcepts.EVAL_QUESTION_REQUESTED, DEFAULT), '1') in service.parsers_cache
|
||||
|
||||
def test_parser_calls_are_not_put_in_cache_when_preprocess_parsers(self):
|
||||
sheerka, context = self.init_test().unpack()
|
||||
service = sheerka.services[SheerkaExecute.NAME]
|
||||
self.reset_parsers(sheerka)
|
||||
context.preprocess_parsers = [SequenceNodeParser.NAME, BnfNodeParser.NAME, SyaNodeParser.NAME]
|
||||
|
||||
user_input = [get_user_input("1")]
|
||||
res = sheerka.execute(context, user_input, [BuiltinConcepts.PARSING])
|
||||
expected_key = (DEFAULT, "|".join([SequenceNodeParser.NAME, BnfNodeParser.NAME, SyaNodeParser.NAME]))
|
||||
|
||||
assert len(res) == 3
|
||||
assert len(service.parsers_cache.cache) == 1
|
||||
assert (expected_key, '1') in service.parsers_cache
|
||||
|
||||
def test_parser_calls_are_not_put_in_cache_when_preprocess(self):
|
||||
sheerka, context = self.init_test().unpack()
|
||||
service = sheerka.services[SheerkaExecute.NAME]
|
||||
self.reset_parsers(sheerka)
|
||||
context.add_preprocess(BaseParser.PREFIX + "parser_name", some_attribute='some_value')
|
||||
|
||||
user_input = [get_user_input("1")]
|
||||
res = sheerka.execute(context, user_input, [BuiltinConcepts.PARSING])
|
||||
|
||||
assert len(res) > 0
|
||||
assert len(service.parsers_cache.cache) == 0
|
||||
|
||||
def test_i_can_use_parser_memoization_on_python(self):
|
||||
sheerka, context = self.init_test().unpack()
|
||||
self.reset_parsers(sheerka)
|
||||
|
||||
user_input = [get_user_input("1 + 1")]
|
||||
first_request = sheerka.execute(context, user_input, [BuiltinConcepts.PARSING])
|
||||
|
||||
user_input_2 = [get_user_input("1 + 1")]
|
||||
second_request = sheerka.execute(context, user_input, [BuiltinConcepts.PARSING])
|
||||
|
||||
check_same_results(first_request, second_request, user_input_2)
|
||||
check_same_values(sheerka, context, first_request, second_request)
|
||||
|
||||
@pytest.mark.parametrize("concept", {
|
||||
Concept("foo"),
|
||||
Concept("foo", body="1"),
|
||||
})
|
||||
def test_i_can_use_parser_memoization_when_exact_concept(self, concept):
|
||||
sheerka, context, foo = self.init_test(eval_body=True, eval_where=True).with_concepts(concept).unpack()
|
||||
self.reset_parsers(sheerka)
|
||||
|
||||
user_input = [get_user_input("foo")]
|
||||
first_request = sheerka.execute(context, user_input, [BuiltinConcepts.PARSING])
|
||||
|
||||
successful = [r.who for r in first_request if r.status]
|
||||
assert successful == ['parsers.ExactConcept']
|
||||
|
||||
user_input_2 = [get_user_input("foo")]
|
||||
second_request = sheerka.execute(context, user_input, [BuiltinConcepts.PARSING])
|
||||
|
||||
check_same_results(first_request, second_request, user_input_2)
|
||||
check_same_values(sheerka, context, first_request, second_request)
|
||||
|
||||
def test_i_can_use_parser_memoization_when_multiple_results(self):
|
||||
sheerka, context, *foo = self.init_test(eval_body=True, eval_where=True).with_concepts(
|
||||
Concept("foo", body="1"),
|
||||
Concept("foo", body="2")).unpack()
|
||||
self.reset_parsers(sheerka)
|
||||
|
||||
user_input = [get_user_input("foo")]
|
||||
first_request = sheerka.execute(context, user_input, [BuiltinConcepts.PARSING])
|
||||
|
||||
successful = [r.who for r in first_request if r.status]
|
||||
assert successful == ['parsers.ExactConcept', 'parsers.ExactConcept']
|
||||
|
||||
user_input_2 = [get_user_input("foo")]
|
||||
second_request = sheerka.execute(context, user_input, [BuiltinConcepts.PARSING])
|
||||
|
||||
check_same_results(first_request, second_request, user_input_2)
|
||||
check_same_values(sheerka, context, first_request, second_request)
|
||||
|
||||
def test_i_can_use_parser_memoization_when_bnf_node(self):
|
||||
sheerka, context, *concepts = self.init_test(eval_body=True, eval_where=True).with_concepts(
|
||||
Concept("one", body="1"),
|
||||
Concept("two", body="2"),
|
||||
Concept("twenties", definition="'twenty' (one|two)=unit", body="20 + unit").def_var("unit"),
|
||||
create_new=True).unpack()
|
||||
self.reset_parsers(sheerka)
|
||||
|
||||
user_input = [get_user_input("twenty one")]
|
||||
first_request = sheerka.execute(context, user_input, [BuiltinConcepts.PARSING])
|
||||
|
||||
successful = [r.who for r in first_request if r.status]
|
||||
assert successful == ['parsers.Bnf']
|
||||
|
||||
user_input_2 = [get_user_input("twenty one")]
|
||||
second_request = sheerka.execute(context, user_input_2, [BuiltinConcepts.PARSING])
|
||||
|
||||
check_same_results(first_request, second_request, user_input_2)
|
||||
check_same_values(sheerka, context, first_request, second_request)
|
||||
|
||||
def test_i_can_use_parser_memoization_when_sequence_node(self):
|
||||
sheerka, context, *concepts = self.init_test(eval_body=True, eval_where=True).with_concepts(
|
||||
Concept("one", body="1"),
|
||||
Concept("two", body="2"),
|
||||
create_new=True).unpack()
|
||||
self.reset_parsers(sheerka)
|
||||
|
||||
user_input = [get_user_input("one two")]
|
||||
first_request = sheerka.execute(context, user_input, [BuiltinConcepts.PARSING])
|
||||
|
||||
successful = [r.who for r in first_request if r.status]
|
||||
assert successful == ['parsers.Sequence']
|
||||
|
||||
user_input_2 = [get_user_input("one two")]
|
||||
second_request = sheerka.execute(context, user_input_2, [BuiltinConcepts.PARSING])
|
||||
|
||||
check_same_results(first_request, second_request, user_input_2)
|
||||
check_same_values(sheerka, context, first_request, second_request)
|
||||
|
||||
def test_i_can_use_parser_memoization_when_sya_node(self):
|
||||
sheerka, context, *concepts = self.init_test(eval_body=True, eval_where=True).with_concepts(
|
||||
Concept("one", body="1"),
|
||||
Concept("twenty two", body="22"),
|
||||
Concept("a plus b", body="a + b").def_var("a").def_var("b"),
|
||||
create_new=True).unpack()
|
||||
self.reset_parsers(sheerka)
|
||||
|
||||
user_input = [get_user_input("one plus twenty two")]
|
||||
first_request = sheerka.execute(context, user_input, [BuiltinConcepts.PARSING])
|
||||
|
||||
successful = [r.who for r in first_request if r.status]
|
||||
assert successful == ['parsers.Sya']
|
||||
|
||||
user_input_2 = [get_user_input("one plus twenty two")]
|
||||
second_request = sheerka.execute(context, user_input_2, [BuiltinConcepts.PARSING])
|
||||
|
||||
check_same_results(first_request, second_request, user_input_2)
|
||||
check_same_values(sheerka, context, first_request, second_request)
|
||||
|
||||
def test_i_can_use_parser_memoization_when_not_parser_input_from_sequence_node(self):
|
||||
# In the test, 'one two' will be partially parsed by the SequenceNodeParser
|
||||
# We test that the results of the UnrecognizedNodeParser and the PythonWithConceptParser
|
||||
# which both do not used ParsingInput as an input (but a ParserResult)
|
||||
# are added to the list of results
|
||||
|
||||
sheerka, context, *concepts = self.init_test(eval_body=True, eval_where=True).with_concepts(
|
||||
Concept("one", body="1")).unpack()
|
||||
self.reset_parsers(sheerka)
|
||||
|
||||
user_input = [get_user_input("one two")]
|
||||
first_request = sheerka.execute(context, user_input, [BuiltinConcepts.PARSING])
|
||||
|
||||
successful = [r.who for r in first_request if r.status]
|
||||
assert successful == []
|
||||
|
||||
user_input_2 = [get_user_input("one two")]
|
||||
second_request = sheerka.execute(context, user_input_2, [BuiltinConcepts.PARSING])
|
||||
|
||||
check_same_results(first_request, second_request, user_input_2)
|
||||
check_same_values(sheerka, context, first_request, second_request)
|
||||
|
||||
def test_i_can_use_parser_memoization_when_not_parser_input_from_bnf_node(self):
|
||||
# check the comment from test_i_can_use_parser_memoization_when_not_parser_input_from_sequence_node
|
||||
# for more information on this test
|
||||
|
||||
sheerka, context, *concepts = self.init_test(eval_body=True, eval_where=True).with_concepts(
|
||||
Concept("one", body="1"),
|
||||
Concept("two", body="2"),
|
||||
Concept("twenties", definition="'twenty' (one|two)=unit", body="20 + unit"),
|
||||
create_new=True).unpack()
|
||||
self.reset_parsers(sheerka)
|
||||
|
||||
user_input = [get_user_input("twenty two foo")]
|
||||
first_request = sheerka.execute(context, user_input, [BuiltinConcepts.PARSING])
|
||||
|
||||
successful = [r.who for r in first_request if r.status]
|
||||
assert successful == []
|
||||
|
||||
user_input_2 = [get_user_input("twenty two foo")]
|
||||
second_request = sheerka.execute(context, user_input_2, [BuiltinConcepts.PARSING])
|
||||
|
||||
check_same_results(first_request, second_request, user_input_2)
|
||||
check_same_values(sheerka, context, first_request, second_request)
|
||||
|
||||
def test_i_can_use_parser_memoization_when_not_parser_input_from_sy_node(self):
|
||||
# check the comment from test_i_can_use_parser_memoization_when_not_parser_input_from_sequence_node
|
||||
# for more information on this test
|
||||
|
||||
sheerka, context, *concepts = self.init_test(eval_body=True, eval_where=True).with_concepts(
|
||||
Concept("one", body="1"),
|
||||
Concept("twenty two", body="22"),
|
||||
Concept("a plus b", body="a + b").def_var("a").def_var("b"),
|
||||
create_new=True).unpack()
|
||||
self.reset_parsers(sheerka)
|
||||
|
||||
user_input = [get_user_input("twenty two plus one foo")]
|
||||
first_request = sheerka.execute(context, user_input, [BuiltinConcepts.PARSING])
|
||||
|
||||
successful = [r.who for r in first_request if r.status]
|
||||
assert successful == []
|
||||
|
||||
user_input_2 = [get_user_input("twenty two plus one foo")]
|
||||
second_request = sheerka.execute(context, user_input_2, [BuiltinConcepts.PARSING])
|
||||
|
||||
check_same_results(first_request, second_request, user_input_2)
|
||||
check_same_values(sheerka, context, first_request, second_request)
|
||||
|
||||
def test_cache_is_reset_on_concept_creation(self):
|
||||
sheerka, context, *concepts = self.init_test().with_concepts(
|
||||
Concept("foo", body="1"), create_new=True).unpack()
|
||||
self.reset_parsers(sheerka)
|
||||
|
||||
user_input = [get_user_input("foo")]
|
||||
|
||||
res = sheerka.execute(context, user_input, [BuiltinConcepts.PARSING])
|
||||
successful = [r for r in res if r.status]
|
||||
assert len(successful) == 1
|
||||
|
||||
sheerka.create_new_concept(context, Concept("foo", body="2"))
|
||||
res = sheerka.execute(context, user_input, [BuiltinConcepts.PARSING])
|
||||
successful = [r for r in res if r.status]
|
||||
assert len(successful) == 2
|
||||
|
||||
def test_cache_is_reset_on_concept_deletion(self):
|
||||
sheerka, context, foo1, foo2 = self.init_test().with_concepts(
|
||||
Concept("foo", body="1"),
|
||||
Concept("foo", body="2"),
|
||||
create_new=True).unpack()
|
||||
self.reset_parsers(sheerka)
|
||||
|
||||
user_input = [get_user_input("foo")]
|
||||
|
||||
res = sheerka.execute(context, user_input, [BuiltinConcepts.PARSING])
|
||||
successful = [r for r in res if r.status]
|
||||
assert len(successful) == 2
|
||||
|
||||
sheerka.remove_concept(context, foo2)
|
||||
res = sheerka.execute(context, user_input, [BuiltinConcepts.PARSING])
|
||||
successful = [r for r in res if r.status]
|
||||
assert len(successful) == 1
|
||||
|
||||
def test_cache_is_reset_on_concept_modification(self):
|
||||
sheerka, context, foo1, foo2 = self.init_test().with_concepts(
|
||||
Concept("foo", body="1"),
|
||||
Concept("foo", body="2"),
|
||||
create_new=True).unpack()
|
||||
self.reset_parsers(sheerka)
|
||||
|
||||
user_input = [get_user_input("foo")]
|
||||
|
||||
res = sheerka.execute(context, user_input, [BuiltinConcepts.PARSING])
|
||||
successful = [r for r in res if r.status]
|
||||
assert len(successful) == 2
|
||||
|
||||
sheerka.modify_concept(context, foo2, to_add={'meta': {"name": "bar"}})
|
||||
res = sheerka.execute(context, user_input, [BuiltinConcepts.PARSING])
|
||||
successful = [r for r in res if r.status]
|
||||
assert len(successful) == 1
|
||||
|
||||
def test_i_do_not_use_short_term_memory_when_not_requested(self):
|
||||
sheerka, context, foo = self.init_test().with_concepts(
|
||||
Concept("foo"),
|
||||
create_new=True).unpack()
|
||||
self.reset_parsers(sheerka)
|
||||
|
||||
user_input = [get_user_input("foo")]
|
||||
|
||||
# put something is STM
|
||||
context.add_to_short_term_memory("foo", "value")
|
||||
res = sheerka.execute(context, user_input, [BuiltinConcepts.PARSING])
|
||||
assert len(res) == 1
|
||||
assert res[0].body == "value"
|
||||
|
||||
# specify the parsers to use
|
||||
context.preprocess_parsers = ["ExactConcept"]
|
||||
res = sheerka.execute(context, user_input, [BuiltinConcepts.PARSING])
|
||||
assert len(res) == 1
|
||||
assert res[0].body.body == foo
|
||||
|
||||
# I can force STM
|
||||
context.preprocess_parsers = ["ExactConcept", "ShortTermMemory"] # order in not relevant for STM parser
|
||||
res = sheerka.execute(context, user_input, [BuiltinConcepts.PARSING])
|
||||
assert len(res) == 1
|
||||
assert res[0].body == "value"
|
||||
|
||||
def test_i_can_compute_parsers_key(self):
|
||||
sheerka = self.get_sheerka()
|
||||
|
||||
context = self.get_context(sheerka)
|
||||
key = SheerkaExecute.get_parsers_key(context)
|
||||
assert key == (DEFAULT, DEFAULT)
|
||||
|
||||
context = self.get_context(sheerka)
|
||||
context.add_to_private_hints(BuiltinConcepts.EVAL_QUESTION_REQUESTED)
|
||||
key = SheerkaExecute.get_parsers_key(context)
|
||||
assert key == (BuiltinConcepts.EVAL_QUESTION_REQUESTED, DEFAULT)
|
||||
|
||||
context = self.get_context(sheerka)
|
||||
context.preprocess_parsers = ["foo", "bar", "baz"]
|
||||
key = SheerkaExecute.get_parsers_key(context)
|
||||
assert key == (DEFAULT, 'foo|bar|baz')
|
||||
|
||||
context = self.get_context(sheerka)
|
||||
context.preprocess_parsers = ["foo", "bar", "baz"]
|
||||
context.add_to_private_hints(BuiltinConcepts.EVAL_QUESTION_REQUESTED)
|
||||
key = SheerkaExecute.get_parsers_key(context)
|
||||
assert key == (BuiltinConcepts.EVAL_QUESTION_REQUESTED, 'foo|bar|baz')
|
||||
|
||||
context = self.get_context(sheerka)
|
||||
context.add_preprocess(BaseParser.PREFIX + "foo", key="some_value")
|
||||
key = SheerkaExecute.get_parsers_key(context)
|
||||
assert key is None
|
||||
|
||||
context = self.get_context(sheerka)
|
||||
context.add_preprocess(BaseParser.PREFIX + "foo", key="some_value")
|
||||
context.add_to_private_hints(BuiltinConcepts.EVAL_QUESTION_REQUESTED)
|
||||
key = SheerkaExecute.get_parsers_key(context)
|
||||
assert key is None
|
||||
|
||||
context = self.get_context(sheerka)
|
||||
context.add_preprocess("foo", key="some_value")
|
||||
key = SheerkaExecute.get_parsers_key(context)
|
||||
assert key == (DEFAULT, DEFAULT)
|
||||
|
||||
context = self.get_context(sheerka)
|
||||
context.add_preprocess("foo", key="some_value")
|
||||
context.add_to_private_hints(BuiltinConcepts.EVAL_QUESTION_REQUESTED)
|
||||
key = SheerkaExecute.get_parsers_key(context)
|
||||
assert key == (BuiltinConcepts.EVAL_QUESTION_REQUESTED, DEFAULT)
|
||||
|
||||
context = self.get_context(sheerka)
|
||||
context.preprocess_parsers = ["foo", "bar", "baz"]
|
||||
context.add_preprocess("foo", key="some_value")
|
||||
key = SheerkaExecute.get_parsers_key(context)
|
||||
assert key == (DEFAULT, 'foo|bar|baz')
|
||||
|
||||
context = self.get_context(sheerka)
|
||||
context.preprocess_parsers = ["foo", "bar", "baz"]
|
||||
context.add_preprocess("foo", key="some_value")
|
||||
context.add_to_private_hints(BuiltinConcepts.EVAL_QUESTION_REQUESTED)
|
||||
key = SheerkaExecute.get_parsers_key(context)
|
||||
assert key == (BuiltinConcepts.EVAL_QUESTION_REQUESTED, 'foo|bar|baz')
|
||||
|
||||
def test_i_use_expression_parser_when_needed(self):
|
||||
sheerka, context, one, number, isa_q, isa = self.init_concepts(
|
||||
"one",
|
||||
"number",
|
||||
Concept("x is a y ", pre="is_question()").def_var("x").def_var("y"),
|
||||
Concept("x is a y ").def_var("x").def_var("y"),
|
||||
)
|
||||
user_input = get_user_input("one is a number")
|
||||
|
||||
res = sheerka.execute(context, [user_input], PARSE_STEPS)
|
||||
res = self.successful_return_values(res)
|
||||
assert len(res) == 1
|
||||
assert res[0].status
|
||||
assert isinstance(res[0].body.body, Concept)
|
||||
|
||||
context = self.get_context(sheerka)
|
||||
context.add_to_protected_hints(BuiltinConcepts.EVAL_QUESTION_REQUESTED)
|
||||
res = sheerka.execute(context, [user_input], PARSE_STEPS)
|
||||
assert len(res) == 1
|
||||
assert res[0].status
|
||||
assert isinstance(res[0].body.body, ExprNode)
|
||||
|
||||
Reference in New Issue
Block a user