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:
@@ -0,0 +1,198 @@
|
||||
import pytest
|
||||
|
||||
from core.builtin_concepts import ParserResultConcept
|
||||
from core.builtin_concepts_ids import BuiltinConcepts
|
||||
from core.concept import Concept
|
||||
from core.sheerka.services.SheerkaExecute import ParserInput
|
||||
from evaluators.BaseEvaluator import BaseEvaluator
|
||||
from evaluators.ValidateConceptEvaluator import ValidateConceptEvaluator
|
||||
from parsers.BaseNodeParser import ConceptNode
|
||||
from parsers.BaseParser import BaseParser
|
||||
from parsers.BnfNodeParser import BnfNodeParser
|
||||
from parsers.SyaNodeParser import SyaNodeParser
|
||||
from tests.TestUsingMemoryBasedSheerka import TestUsingMemoryBasedSheerka
|
||||
from tests.evaluators.EvaluatorTestsUtils import p_ret_val, pr_ret_val, ret_val
|
||||
|
||||
|
||||
class TestValidateConceptEvaluator(TestUsingMemoryBasedSheerka):
|
||||
|
||||
@pytest.mark.parametrize("return_value, need_validation, expected", [
|
||||
(pr_ret_val(Concept("foo", where="something"), status=True), True, True),
|
||||
(pr_ret_val(Concept("foo", pre="something"), status=True), True, True),
|
||||
(pr_ret_val(Concept("foo", where="something"), status=True), False, False),
|
||||
(pr_ret_val(Concept("foo", pre="something"), status=True), False, False),
|
||||
(pr_ret_val(Concept("foo"), status=True), True, False),
|
||||
(pr_ret_val(Concept("foo"), status=True), True, False),
|
||||
(pr_ret_val(Concept("foo", where=None), status=True), True, False),
|
||||
(pr_ret_val(Concept("foo", pre=None), status=True), True, False),
|
||||
(pr_ret_val(Concept("foo", where=""), status=True), True, False),
|
||||
(pr_ret_val(Concept("foo", pre=""), status=True), True, False),
|
||||
(pr_ret_val(Concept("foo", where="something"), status=False), True, False),
|
||||
(pr_ret_val(Concept("foo", pre="something"), status=False), True, False),
|
||||
(pr_ret_val("Not a concept", status=True), True, False),
|
||||
(pr_ret_val("Not a concept", status=False), True, False),
|
||||
(p_ret_val("Not a parser result", status=True), True, False),
|
||||
(p_ret_val("Not a parser result", status=False), True, False),
|
||||
])
|
||||
def test_i_can_match(self, return_value, need_validation, expected):
|
||||
sheerka, context = self.init_concepts()
|
||||
evaluator = ValidateConceptEvaluator()
|
||||
if (sheerka.isinstance(return_value.body, BuiltinConcepts.PARSER_RESULT) and
|
||||
isinstance(return_value.body.body, Concept)):
|
||||
return_value.body.body.get_hints().need_validation = need_validation
|
||||
|
||||
assert evaluator.matches(context, return_value) == expected
|
||||
|
||||
def test_i_cannot_match_when_the_return_value_is_not_a_direct_parsing_result(self):
|
||||
# I match only if the return_value comes from a parser (not from an after_parsing evaluator)
|
||||
sheerka, context = self.init_concepts()
|
||||
|
||||
concept = Concept("foo", pre="something")
|
||||
parser_result = ParserResultConcept(BaseParser.get_name("parser"), source=concept.name, value=concept)
|
||||
return_value = ret_val(value=parser_result, who="evaluators.something", status=True)
|
||||
return_value.body.body.get_hints().need_validation = True
|
||||
|
||||
evaluator = ValidateConceptEvaluator()
|
||||
assert not evaluator.matches(context, return_value)
|
||||
|
||||
@pytest.mark.parametrize("concept", [
|
||||
Concept("foo", pre="False"),
|
||||
Concept("foo", where="False"),
|
||||
])
|
||||
def test_i_can_eval_when_constraint_is_false(self, concept):
|
||||
sheerka, context, foo = self.init_concepts(concept)
|
||||
|
||||
ret_val = pr_ret_val(foo, status=True)
|
||||
res = ValidateConceptEvaluator().eval(context, ret_val)
|
||||
|
||||
assert not res.status
|
||||
assert res.who == BaseEvaluator.PREFIX + ValidateConceptEvaluator.NAME
|
||||
assert sheerka.isinstance(res.body, BuiltinConcepts.FILTERED)
|
||||
assert res.body.body == foo
|
||||
|
||||
@pytest.mark.parametrize("concept", [
|
||||
Concept("foo"),
|
||||
Concept("foo", pre="True"),
|
||||
Concept("foo", where="True"),
|
||||
])
|
||||
def test_i_can_eval_when_constraint_is_true_or_when_no_constrain(self, concept):
|
||||
sheerka, context, foo = self.init_concepts(concept)
|
||||
|
||||
ret_val = pr_ret_val(foo, status=True)
|
||||
res = ValidateConceptEvaluator().eval(context, ret_val)
|
||||
|
||||
assert res is None
|
||||
|
||||
@pytest.mark.parametrize("concept", [
|
||||
Concept("foo"),
|
||||
Concept("foo", pre="True"),
|
||||
Concept("foo", where="True"),
|
||||
])
|
||||
def test_i_can_eval_when_constraint_is_true_or_when_no_constrain_use_copy(self, concept):
|
||||
sheerka, context, foo = self.init_concepts(concept)
|
||||
|
||||
foo.get_hints().use_copy = True
|
||||
ret_val = pr_ret_val(foo, status=True)
|
||||
res = ValidateConceptEvaluator().eval(context, ret_val)
|
||||
|
||||
assert res.status
|
||||
assert res.who == BaseEvaluator.PREFIX + ValidateConceptEvaluator.NAME
|
||||
assert res.body.body.id == foo.id
|
||||
assert not res.body.body.get_hints().use_copy
|
||||
|
||||
def test_i_can_eval_when_is_question(self):
|
||||
sheerka, context, foo = self.init_concepts(Concept("foo", pre="is_question()"))
|
||||
|
||||
ret_val = pr_ret_val(foo, status=True)
|
||||
|
||||
res = ValidateConceptEvaluator().eval(context, ret_val)
|
||||
assert not res.status
|
||||
|
||||
context.add_to_protected_hints(BuiltinConcepts.EVAL_QUESTION_REQUESTED)
|
||||
res = ValidateConceptEvaluator().eval(context, ret_val)
|
||||
assert res is None
|
||||
|
||||
def test_i_can_eval_when_unknown_variables_but_no_constraint(self):
|
||||
sheerka, context, foo = self.init_concepts(Concept("a plus b").def_var("a").def_var("b"))
|
||||
|
||||
ret_val = pr_ret_val(foo, status=True)
|
||||
|
||||
res = ValidateConceptEvaluator().eval(context, ret_val)
|
||||
assert res is None
|
||||
|
||||
def test_i_can_eval_when_unknown_variables(self):
|
||||
# ValidateConceptEvaluator must filter only if all the variables are known
|
||||
# In this example, 'b' is not set, so the return_value must not be filtered
|
||||
sheerka, context, foo = self.init_concepts(
|
||||
Concept("a plus b", where="isinstance(b, int)").def_var("a", "10").def_var("b"))
|
||||
|
||||
ret_val = pr_ret_val(foo, status=True)
|
||||
|
||||
res = ValidateConceptEvaluator().eval(context, ret_val)
|
||||
assert res is None
|
||||
|
||||
def test_i_can_eval_when_constraint_on_variable_fails(self):
|
||||
sheerka, context, foo = self.init_concepts(
|
||||
Concept("a plus b", where="isinstance(b, int)").def_var("a").def_var("b", "'a string'"))
|
||||
|
||||
ret_val = pr_ret_val(foo, status=True)
|
||||
|
||||
res = ValidateConceptEvaluator().eval(context, ret_val)
|
||||
assert not res.status
|
||||
|
||||
def test_i_can_eval_bnf_concepts(self):
|
||||
sheerka, context, quantify_x = self.init_concepts(
|
||||
Concept("quantify x", definition="('one'|'two') x", where="x != 'one'").def_var("x"),
|
||||
create_new=True)
|
||||
evaluator = ValidateConceptEvaluator()
|
||||
|
||||
# success
|
||||
ret_val = BnfNodeParser().parse(context, ParserInput("one 'two'"))
|
||||
assert evaluator.matches(context, ret_val)
|
||||
res = evaluator.eval(context, ret_val)
|
||||
assert isinstance(res.body.body, list)
|
||||
assert len(res.body.body) == 1
|
||||
assert isinstance(res.body.body[0], ConceptNode)
|
||||
assert res.body.body[0].concept.id == ret_val.body.body[0].concept.id
|
||||
|
||||
# failure
|
||||
ret_val = BnfNodeParser().parse(context, ParserInput("one 'one'"))
|
||||
assert evaluator.matches(context, ret_val)
|
||||
res = evaluator.eval(context, ret_val)
|
||||
assert not res.status
|
||||
assert sheerka.isinstance(res.body, BuiltinConcepts.FILTERED)
|
||||
assert res.body.body == ret_val.body.body
|
||||
|
||||
def test_i_can_eval_sya_concepts(self):
|
||||
sheerka, context, quantify_x = self.init_concepts(
|
||||
Concept("a plus b", where="a < 10").def_var("a").def_var("b"),
|
||||
create_new=True)
|
||||
evaluator = ValidateConceptEvaluator()
|
||||
|
||||
# success
|
||||
ret_val = SyaNodeParser().parse(context, ParserInput("5 plus 3"))
|
||||
assert evaluator.matches(context, ret_val)
|
||||
res = evaluator.eval(context, ret_val)
|
||||
assert isinstance(res.body.body, list)
|
||||
assert len(res.body.body) == 1
|
||||
assert isinstance(res.body.body[0], ConceptNode)
|
||||
assert res.body.body[0].concept.id == ret_val.body.body[0].concept.id
|
||||
|
||||
# failure
|
||||
ret_val = SyaNodeParser().parse(context, ParserInput("15 plus 3"))
|
||||
assert evaluator.matches(context, ret_val)
|
||||
res = evaluator.eval(context, ret_val)
|
||||
assert not res.status
|
||||
assert sheerka.isinstance(res.body, BuiltinConcepts.FILTERED)
|
||||
assert res.body.body == ret_val.body.body
|
||||
|
||||
def test_i_can_manage_infinite_recursion(self):
|
||||
sheerka, context, a_and_b = self.init_concepts(
|
||||
Concept("a and b", where="is_question()", body="a and b").def_var("a").def_var("b"),
|
||||
create_new=True)
|
||||
evaluator = ValidateConceptEvaluator()
|
||||
|
||||
ret_val = pr_ret_val(a_and_b)
|
||||
res = evaluator.eval(context, ret_val)
|
||||
|
||||
assert res is None # infinite recursion detected, res is None to drop the validator
|
||||
Reference in New Issue
Block a user