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:
2021-06-07 21:14:03 +02:00
parent 1059ce25c5
commit 7dcaa9c111
92 changed files with 4263 additions and 1890 deletions
+6 -14
View File
@@ -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()
+28 -3
View File
@@ -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):
+9 -10
View File
@@ -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)
+154 -42
View File
@@ -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
+26 -6
View File
@@ -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"}
+13 -1
View File
@@ -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)
+103 -178
View File
@@ -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__'
+60
View File
@@ -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,
# []
+5 -5
View File
@@ -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):
+3 -3
View File
@@ -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()
+443 -21
View File
@@ -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)