Added first version of DebugManager. Implemented draft of the rule engine

This commit is contained in:
2020-11-20 13:41:45 +01:00
parent cd066881b4
commit 315f8ea09b
156 changed files with 8388 additions and 2852 deletions
@@ -4,17 +4,17 @@ import pytest
from core.builtin_concepts import ReturnValueConcept, ParserResultConcept, BuiltinConcepts
from core.concept import VARIABLE_PREFIX, Concept, DEFINITION_TYPE_BNF, DEFINITION_TYPE_DEF
from core.tokenizer import Tokenizer
from evaluators.AddConceptEvaluator import AddConceptEvaluator
from evaluators.DefConceptEvaluator import DefConceptEvaluator
from parsers.BaseParser import BaseParser
from parsers.BnfNodeParser import Sequence, StrMatch, ZeroOrMore, ConceptExpression
from parsers.BnfParser import BnfParser
from parsers.BnfDefinitionParser import BnfDefinitionParser
from parsers.DefConceptParser import DefConceptNode, NameNode
from parsers.PythonParser import PythonNode, PythonParser
from tests.TestUsingMemoryBasedSheerka import TestUsingMemoryBasedSheerka
class TestAddConceptEvaluator(TestUsingMemoryBasedSheerka):
class TestDefConceptEvaluator(TestUsingMemoryBasedSheerka):
@staticmethod
def get_concept_part(part):
@@ -47,7 +47,7 @@ class TestAddConceptEvaluator(TestUsingMemoryBasedSheerka):
status=True,
value=ParserResultConcept(
source=source,
parser=BnfParser(),
parser=BnfDefinitionParser(),
value=parsing_expression
)
)
@@ -86,7 +86,7 @@ class TestAddConceptEvaluator(TestUsingMemoryBasedSheerka):
])
def test_i_can_match(self, ret_val, expected):
context = self.get_context()
assert AddConceptEvaluator().matches(context, ret_val) == expected
assert DefConceptEvaluator().matches(context, ret_val) == expected
def test_that_the_source_is_correctly_set_for_bnf_concept(self):
context = self.get_context()
@@ -98,21 +98,21 @@ class TestAddConceptEvaluator(TestUsingMemoryBasedSheerka):
body="print('hello' + a)",
ret="a")
evaluated = AddConceptEvaluator().eval(context, def_concept_return_value)
evaluated = DefConceptEvaluator().eval(context, def_concept_return_value)
assert evaluated.status
assert context.sheerka.isinstance(evaluated.body, BuiltinConcepts.NEW_CONCEPT)
created_concept = evaluated.body.body
assert created_concept.metadata.name == "hello a"
assert created_concept.metadata.key == "hello __var__0"
assert created_concept.metadata.where == "isinstance(a, str )"
assert created_concept.metadata.pre == "a is not None"
assert created_concept.metadata.post is None # test that NotInitialized is mapped into None
assert created_concept.metadata.body == "print('hello' + a)"
assert created_concept.metadata.ret == "a"
assert created_concept.metadata.definition == "hello a"
assert created_concept.metadata.definition_type == "bnf"
assert created_concept.get_metadata().name == "hello a"
assert created_concept.get_metadata().key == "hello __var__0"
assert created_concept.get_metadata().where == "isinstance(a, str )"
assert created_concept.get_metadata().pre == "a is not None"
assert created_concept.get_metadata().post is None # test that NotInitialized is mapped into None
assert created_concept.get_metadata().body == "print('hello' + a)"
assert created_concept.get_metadata().ret == "a"
assert created_concept.get_metadata().definition == "hello a"
assert created_concept.get_metadata().definition_type == "bnf"
def test_i_can_add_concept_with_the_correct_variables_when_referencing_other_concepts(self):
context = self.get_context()
@@ -121,13 +121,13 @@ class TestAddConceptEvaluator(TestUsingMemoryBasedSheerka):
where=self.pretval(Concept("u is a v").def_var("u").def_var("v"), source="x is a number"),
body=self.pretval(Concept("add a b").def_var("a").def_var("b"), source="add x y"), )
evaluated = AddConceptEvaluator().eval(context, def_concept_return_value)
evaluated = DefConceptEvaluator().eval(context, def_concept_return_value)
assert evaluated.status
assert context.sheerka.isinstance(evaluated.body, BuiltinConcepts.NEW_CONCEPT)
created_concept = evaluated.body.body
assert created_concept.metadata.variables == [("x", None), ("y", None)]
assert created_concept.get_metadata().variables == [("x", None), ("y", None)]
def test_that_the_source_is_correctly_set_for_concept_with_simple_definition(self):
context = self.get_context()
@@ -138,20 +138,20 @@ class TestAddConceptEvaluator(TestUsingMemoryBasedSheerka):
pre="a is not None",
body="print('hello' + a)")
evaluated = AddConceptEvaluator().eval(context, def_concept_return_value)
evaluated = DefConceptEvaluator().eval(context, def_concept_return_value)
assert evaluated.status
assert context.sheerka.isinstance(evaluated.body, BuiltinConcepts.NEW_CONCEPT)
created_concept = evaluated.body.body
assert created_concept.metadata.name == "greetings"
assert created_concept.metadata.key == "hello __var__0"
assert created_concept.metadata.where == "isinstance(a, str )"
assert created_concept.metadata.pre == "a is not None"
assert created_concept.metadata.post is None
assert created_concept.metadata.body == "print('hello' + a)"
assert created_concept.metadata.definition == "hello a"
assert created_concept.metadata.definition_type == "def"
assert created_concept.get_metadata().name == "greetings"
assert created_concept.get_metadata().key == "hello __var__0"
assert created_concept.get_metadata().where == "isinstance(a, str )"
assert created_concept.get_metadata().pre == "a is not None"
assert created_concept.get_metadata().post is None
assert created_concept.get_metadata().body == "print('hello' + a)"
assert created_concept.get_metadata().definition == "hello a"
assert created_concept.get_metadata().definition_type == "def"
def test_that_the_new_concept_is_correctly_saved_in_db(self):
context = self.get_context()
@@ -166,23 +166,23 @@ class TestAddConceptEvaluator(TestUsingMemoryBasedSheerka):
from_db = context.sheerka.get_by_key("hello " + VARIABLE_PREFIX + "0")
assert context.sheerka.isinstance(from_db, BuiltinConcepts.UNKNOWN_CONCEPT)
AddConceptEvaluator().eval(context, def_concept_return_value)
DefConceptEvaluator().eval(context, def_concept_return_value)
context.sheerka.concepts_cache = {} # reset cache
from_db = context.sheerka.get_by_key("hello " + VARIABLE_PREFIX + "0")
assert from_db.metadata.key == f"hello {VARIABLE_PREFIX}0"
assert from_db.metadata.name == "hello a"
assert from_db.metadata.where == "isinstance(a, str )"
assert from_db.metadata.pre == "a is not None"
assert from_db.metadata.post is None
assert from_db.metadata.body == "print('hello' + a)"
assert from_db.metadata.definition == "hello a"
assert from_db.metadata.definition_type == "bnf"
assert len(from_db.metadata.variables) == 1
assert from_db.metadata.variables[0] == ("a", None)
assert "a" in from_db.values
assert from_db.get_metadata().key == f"hello {VARIABLE_PREFIX}0"
assert from_db.get_metadata().name == "hello a"
assert from_db.get_metadata().where == "isinstance(a, str )"
assert from_db.get_metadata().pre == "a is not None"
assert from_db.get_metadata().post is None
assert from_db.get_metadata().body == "print('hello' + a)"
assert from_db.get_metadata().definition == "hello a"
assert from_db.get_metadata().definition_type == "bnf"
assert len(from_db.get_metadata().variables) == 1
assert from_db.get_metadata().variables[0] == ("a", None)
assert "a" in from_db.values()
assert from_db.compiled == {} # ast is not saved in db
assert from_db.get_compiled() == {} # ast is not saved in db
@pytest.mark.parametrize("expression, name, expected", [
("isinstance(a, str)", "a b", {"a"}),
@@ -195,39 +195,39 @@ class TestAddConceptEvaluator(TestUsingMemoryBasedSheerka):
ret_val = self.get_concept_part(expression)
context = self.get_context()
assert AddConceptEvaluator.get_variables(context.sheerka, ret_val, name.split()) == expected
assert DefConceptEvaluator.get_variables(context.sheerka, ret_val, name.split()) == expected
def test_i_can_get_variables_when_keywords(self):
sheerka, context = self.init_concepts()
def_concept = self.get_def_concept("condition pre").value.value
name_to_use = AddConceptEvaluator.get_name_to_use(def_concept)
name_to_use = DefConceptEvaluator.get_name_to_use(def_concept)
concept_part = self.get_concept_part("pre")
assert AddConceptEvaluator.get_variables(context.sheerka, concept_part, name_to_use) == {"pre"}
assert DefConceptEvaluator.get_variables(context.sheerka, concept_part, name_to_use) == {"pre"}
def test_i_cannot_get_variables_from_python_node_when_name_has_only_one_token(self):
ret_val = self.get_concept_part("isinstance(a, str)")
context = self.get_context()
assert AddConceptEvaluator.get_variables(context.sheerka, ret_val, ["a"]) == []
assert DefConceptEvaluator.get_variables(context.sheerka, ret_val, ["a"]) == []
def test_i_can_get_variables_from_definition(self):
parsing_expression = Sequence(ConceptExpression('mult'),
ZeroOrMore(Sequence(StrMatch("+"), ConceptExpression("add"))))
ret_val = self.get_return_value("mult (('+'|'-') add)?", parsing_expression)
assert AddConceptEvaluator.get_variables(self.get_sheerka(), ret_val, []) == {"add", "mult"}
assert DefConceptEvaluator.get_variables(self.get_sheerka(), ret_val, []) == {"add", "mult"}
def test_concept_that_references_itself_is_correctly_created(self):
context = self.get_context()
def_concept_as_return_value = self.get_def_concept("foo", body="foo")
ret_val = AddConceptEvaluator().eval(context, def_concept_as_return_value)
ret_val = DefConceptEvaluator().eval(context, def_concept_as_return_value)
assert ret_val.status
new_concept = ret_val.body.body
assert new_concept.name == 'foo'
assert new_concept.metadata.body == 'foo'
assert new_concept.values == {}
assert new_concept.metadata.variables == []
assert new_concept.get_metadata().body == 'foo'
assert new_concept.values() == {}
assert new_concept.get_metadata().variables == []
@@ -0,0 +1,51 @@
import pytest
from core.builtin_concepts import ReturnValueConcept, ParserResultConcept, BuiltinConcepts
from core.rule import Rule, RuleMetadata
from core.sheerka.services.SheerkaExecute import ParserInput
from core.tokenizer import Tokenizer
from evaluators.FormatRuleEvaluator import FormatRuleEvaluator
from parsers.FormatRuleParser import FormatRuleNode, FormatRuleParser
from tests.TestUsingMemoryBasedSheerka import TestUsingMemoryBasedSheerka
class TestFormatRuleEvaluator(TestUsingMemoryBasedSheerka):
@staticmethod
def get_ret_val_from_rule(rule_def):
tokens = {k: list(Tokenizer(k.value + " " + v, yield_eof=False)) for k, v in rule_def.items()}
for v in tokens.values():
del v[1]
node = FormatRuleNode(tokens)
return ReturnValueConcept("parsers.FormatRule", True, ParserResultConcept(value=node))
@pytest.mark.parametrize("ret_val, expected", [
(ReturnValueConcept("name", True, ParserResultConcept(value=FormatRuleNode({}))), True),
(ReturnValueConcept("name", True, ParserResultConcept(value="other object")), False),
(ReturnValueConcept("name", False, ParserResultConcept(value=FormatRuleNode({}))), False),
(ReturnValueConcept("name", False, FormatRuleNode({})), False),
])
def test_i_can_match(self, ret_val, expected):
context = self.get_context()
assert FormatRuleEvaluator().matches(context, ret_val) == expected
def test_i_can_eval(self):
sheerka, context = self.init_concepts()
text = "when isinstance(value, __EXPLANATION) print list(value)"
ret_val = FormatRuleParser().parse(context, ParserInput(text))
res = FormatRuleEvaluator().eval(context, ret_val)
assert res.status
assert sheerka.isinstance(res.body, BuiltinConcepts.NEW_RULE)
assert isinstance(res.body.body, Rule)
assert res.body.body.metadata == RuleMetadata("print",
None,
"isinstance(value, __EXPLANATION)",
"list(value)",
id=res.body.body.metadata.id, # no need to compare the id
is_compiled=True,
is_enabled=True)
assert res.body.body.compiled_predicate is not None
assert res.body.body.compiled_action is not None
+2 -2
View File
@@ -69,7 +69,7 @@ class TestLexerNodeEvaluator(TestUsingMemoryBasedSheerka):
assert wrapper.parser == evaluator
assert wrapper.source == "foo"
assert return_value == foo
assert return_value.compiled[ConceptParts.BODY] == DoNotResolve("foo")
assert return_value.get_compiled()[ConceptParts.BODY] == DoNotResolve("foo")
assert result.parents == [ret_val]
def test_concept_python_node_is_returned_when_source_code(self):
@@ -88,5 +88,5 @@ class TestLexerNodeEvaluator(TestUsingMemoryBasedSheerka):
assert wrapper.source == "foo + 1"
assert return_value == PythonNode('foo + 1', ast.parse("__C__foo__C__ + 1", mode="eval"))
assert return_value.concepts == {"__C__foo__C__": foo}
assert return_value.objects == {"__C__foo__C__": foo}
assert result.parents == [ret_val]
+8 -4
View File
@@ -1,13 +1,16 @@
import pytest
from core.builtin_concepts import ReturnValueConcept, BuiltinConcepts
from core.builtin_concepts import ReturnValueConcept, BuiltinConcepts, ParserResultConcept
from core.concept import Concept
from core.rule import Rule
from evaluators.OneSuccessEvaluator import OneSuccessEvaluator
from tests.TestUsingMemoryBasedSheerka import TestUsingMemoryBasedSheerka
def r(value, status=True):
return ReturnValueConcept(value, status, value)
def r(name, status=True, value=None):
if isinstance(value, Rule):
value = ParserResultConcept(name, value=value, try_parsed=value)
return ReturnValueConcept(name, status, value or name)
reduce_requested = ReturnValueConcept("some_name", True, Concept(key=BuiltinConcepts.REDUCE_REQUESTED))
@@ -25,6 +28,7 @@ class TestOneSuccessEvaluator(TestUsingMemoryBasedSheerka):
([r("evaluators.success"), r("evaluators.another success"), reduce_requested], False),
([r("evaluators.one success"), r("other success"), r("failed", False), reduce_requested], True),
([r("evaluators.one success"), r("parsers.success"), reduce_requested], False),
([r("evaluators.one success"), r("parsers.success"), reduce_requested], False),
])
def test_i_can_match(self, return_values, expected):
context = self.get_context()
+82 -48
View File
@@ -2,19 +2,20 @@ import ast
import pytest
from core.builtin_concepts import ReturnValueConcept, ParserResultConcept, BuiltinConcepts
from core.concept import Concept, CB, NotInit
from core.concept import Concept, CB
from core.sheerka.services.SheerkaExecute import ParserInput
from core.tokenizer import Tokenizer
from evaluators.PythonEvaluator import PythonEvaluator, PythonEvalError
from evaluators.PythonEvaluator import PythonEvaluator, PythonEvalError, NamesWithAttributesVisitor
from parsers.BaseNodeParser import SourceCodeNode, SourceCodeWithConceptNode
from parsers.FunctionParser import FunctionParser
from parsers.PythonParser import PythonNode, PythonParser
from parsers.PythonWithConceptsParser import PythonWithConceptsParser
from tests.TestUsingMemoryBasedSheerka import TestUsingMemoryBasedSheerka
def get_concept_name(concept):
return concept.name
def get_obj_name(obj):
return obj.name
def get_source_code_node(source_code, concepts=None):
@@ -36,7 +37,7 @@ def get_source_code_node(source_code, concepts=None):
tokens = list(Tokenizer(source_code, yield_eof=False))
return SourceCodeNode(0, len(tokens), tokens, python_node=python_node)
else:
python_node.concepts = concepts
python_node.objects = concepts
scwcn = SourceCodeWithConceptNode(None, None)
scwcn.python_node = python_node
return scwcn
@@ -62,10 +63,13 @@ class TestPythonEvaluator(TestUsingMemoryBasedSheerka):
assert PythonEvaluator().matches(context, ret_val) == expected
@pytest.mark.parametrize("text, expected", [
("1 + 1", 2),
("test()", "I have access to Sheerka !"),
# ("1 + 1", 2),
# ("test()", "I have access to Sheerka !"),
("sheerka.test()", "I have access to Sheerka !"),
("a=10\na", 10),
("Concept('foo')", Concept('foo')),
("BuiltinConcepts.NOP", BuiltinConcepts.NOP),
("in_context(BuiltinConcepts.EVAL_QUESTION_REQUESTED)", False),
])
def test_i_can_eval(self, text, expected):
context = self.get_context()
@@ -76,6 +80,29 @@ class TestPythonEvaluator(TestUsingMemoryBasedSheerka):
assert evaluated.status
assert evaluated.value == expected
def test_i_can_eval_isinstance(self):
sheerka, context, foo = self.init_concepts("foo")
parsed = PythonParser().parse(context, ParserInput("isinstance('foo', str)"))
evaluated = PythonEvaluator().eval(context, parsed)
assert evaluated.status
assert evaluated.value
parsed = PythonParser().parse(context, ParserInput("isinstance(foo, 'foo')"))
evaluated = PythonEvaluator().eval(context, parsed)
assert evaluated.status
assert evaluated.value
def test_i_can_eval_context_obj_properties(self):
sheerka, context, foo = self.init_concepts(Concept("foo").def_var("a", "hello world!").auto_init())
context = self.get_context()
parsed = PythonParser().parse(context, ParserInput("a"))
context.obj = foo
evaluated = PythonEvaluator().eval(context, parsed)
assert evaluated.status
assert evaluated.value == "hello world!"
@pytest.mark.parametrize("source_code_node, expected", [
(get_source_code_node("1 + 1"), 2),
(get_source_code_node("one + one", {"one": Concept("one", body="1")}), 2)
@@ -89,14 +116,14 @@ class TestPythonEvaluator(TestUsingMemoryBasedSheerka):
assert evaluated.status
assert evaluated.value == expected
def test_i_can_eval_using_context(self):
def test_i_can_eval_a_method_that_requires_the_context(self):
context = self.get_context()
parsed = PythonParser().parse(context, ParserInput("test_using_context('value for param1', 10)"))
parsed = PythonParser().parse(context, ParserInput("test_using_context('value for param')"))
evaluated = PythonEvaluator().eval(context, parsed)
assert evaluated.status
assert evaluated.value.startswith("I have access to Sheerka ! param1='value for param1', param2=10, event=")
assert evaluated.value == "I have access to Sheerka ! param='value for param', event='xxx'."
def test_i_can_eval_using_context_when_self_is_not_sheerka(self):
sheerka, context = self.init_concepts()
@@ -107,21 +134,6 @@ class TestPythonEvaluator(TestUsingMemoryBasedSheerka):
assert evaluated.status
assert sheerka.has_key("foo")
@pytest.mark.parametrize("concept", [
Concept("foo"),
Concept("foo", body="2"),
Concept("foo").def_var("prop", "'a'"),
Concept("foo", body="bar")
])
def test_simple_concepts_are_not_for_me(self, concept):
context = self.get_context()
context.sheerka.add_in_cache(Concept("foo"))
parsed = PythonParser().parse(context, ParserInput("foo"))
evaluated = PythonEvaluator().eval(context, parsed)
assert not evaluated.status
assert context.sheerka.isinstance(evaluated.value, BuiltinConcepts.NOT_FOR_ME)
def test_i_can_eval_ast_expression_that_references_concepts(self):
"""
@@ -167,10 +179,10 @@ class TestPythonEvaluator(TestUsingMemoryBasedSheerka):
def test_i_can_eval_concept_token(self):
context = self.get_context()
context.sheerka.add_in_cache(Concept("foo", body="2"))
context.add_to_short_term_memory("get_obj_name", get_obj_name)
parsed = PythonParser().parse(context, ParserInput("get_concept_name(c:foo:)"))
parsed = PythonParser().parse(context, ParserInput("get_obj_name(c:foo:)"))
python_evaluator = PythonEvaluator()
python_evaluator.globals["get_concept_name"] = get_concept_name
evaluated = python_evaluator.eval(context, parsed)
assert evaluated.status
@@ -210,7 +222,8 @@ class TestPythonEvaluator(TestUsingMemoryBasedSheerka):
evaluated = python_evaluator.eval(context, parsed)
assert evaluated.status
assert sheerka.get_concepts_weights(BuiltinConcepts.PRECEDENCE) == {'1001': 1, '1002': 2}
assert sheerka.get_concepts_weights(BuiltinConcepts.PRECEDENCE) == {'c:__var__0 plus __var__1|1001:': 1,
'c:__var__0 mult __var__1|1002:': 2}
def test_i_can_define_variables(self):
sheerka, context = self.init_concepts()
@@ -261,7 +274,7 @@ class TestPythonEvaluator(TestUsingMemoryBasedSheerka):
evaluated = PythonEvaluator().eval(context, parsed)
assert not evaluated.status
assert context.sheerka.isinstance(evaluated.value, BuiltinConcepts.TOO_MANY_ERRORS)
assert context.sheerka.isinstance(evaluated.value, BuiltinConcepts.ERROR)
error0 = evaluated.body.body[0]
assert isinstance(error0, PythonEvalError)
@@ -275,21 +288,6 @@ class TestPythonEvaluator(TestUsingMemoryBasedSheerka):
assert error1.error.args[0] == 'can only concatenate str (not "int") to str'
assert error1.concepts == {'foo': 'string'}
def test_i_do_not_include_not_initialized_variables_when_evaluating(self):
sheerka, context, foo = self.init_concepts(
Concept("foo a", pre="a == 'True'").def_var("a", "'True'").def_var("b"))
foo.set_value("b", "'Initialized!'")
context.obj = foo
assert foo.get_value("a") == NotInit
assert foo.get_value("b") == "'Initialized!'"
my_globals = {}
PythonEvaluator().update_globals_with_context(my_globals, context)
assert my_globals == {"self": foo, "b": "'Initialized!'"}
def test_i_can_use_sheerka_locals(self):
sheerka, context = self.init_concepts()
@@ -307,11 +305,47 @@ class TestPythonEvaluator(TestUsingMemoryBasedSheerka):
def test_i_can_eval_concept_with_ret(self):
sheerka, context, one, the = self.init_concepts("one", Concept("the a", ret="a").def_var("a"))
ret_val = get_ret_val_from_source_code(context, "test_using_context(one, the one)", {
"the one": self.get_concept_instance(sheerka, the, a="one"),
"one": self.get_concept_instance(sheerka, "one")
ret_val = get_ret_val_from_source_code(context, "test_using_context(the one)", {
"the one": self.get_concept_instance(sheerka, the, a="one")
})
evaluated = PythonEvaluator().eval(context, ret_val)
assert evaluated.status
assert evaluated.value.startswith("I have access to Sheerka ! param1=(1001)one, param2=(1001)one, event=")
assert evaluated.value == "I have access to Sheerka ! param=(1001)one, event='xxx'."
def test_i_can_eval_rules_from_python_parser(self):
sheerka, context = self.init_concepts()
parsed_ret_val = PythonParser().parse(context, ParserInput("r:|1:.id"))
assert parsed_ret_val.status
evaluated = PythonEvaluator().eval(context, parsed_ret_val)
assert evaluated.status
assert evaluated.value == "1"
def test_i_can_eval_rules_from_function_parser(self):
context = self.get_context()
context.add_to_short_term_memory("get_obj_name", get_obj_name)
parsed = FunctionParser().parse(context, ParserInput("get_obj_name(r:|1:)"))
python_evaluator = PythonEvaluator()
evaluated = python_evaluator.eval(context, parsed)
assert evaluated.status
assert evaluated.value == "Print return values"
@pytest.mark.parametrize("text, expected", [
("foo.bar.baz", [["foo", "bar", "baz"]]),
("foo.bar.baz; one.two.three", [["foo", "bar", "baz"]]),
("foo.bar.baz; one.two.three; foo.bar", [["foo", "bar", "baz"], ["foo", "bar"]]),
("one.two.three", []),
("foo", [["foo"]]),
("foo.bar[1].baz", [["foo", "bar", "baz"]]),
("foo[1].bar.baz", [["foo", "bar", "baz"]]),
])
def test_names_with_attributes_visitor(self, text, expected):
ast_ = ast.parse(text, "<src>", mode="exec")
visitor = NamesWithAttributesVisitor()
sequence = visitor.get_sequences(ast_, "foo")
assert sequence == expected
@@ -0,0 +1,50 @@
from core.builtin_concepts import BuiltinConcepts
from core.concept import Concept
from evaluators.ReturnBodyEvaluator import ReturnBodyEvaluator
from tests.TestUsingMemoryBasedSheerka import TestUsingMemoryBasedSheerka
class TestReturnBodyEvaluator(TestUsingMemoryBasedSheerka):
def test_i_can_match(self):
sheerka, root_context = self.init_concepts()
root_context.add_to_global_hints(BuiltinConcepts.RETURN_BODY_REQUESTED)
context = root_context.push(BuiltinConcepts.PROCESSING, None)
sub_context = context.push(BuiltinConcepts.PROCESSING, None)
sub_sub_context = sub_context.push(BuiltinConcepts.PROCESSING, None)
evaluator = ReturnBodyEvaluator()
assert evaluator.matches(root_context, []) # no parent, real root
assert evaluator.matches(context, []) # no BuiltinConcepts.PROCESSING, is root for unit test
assert evaluator.matches(sub_context, []) # only one BuiltinConcepts.PROCESSING, is root in prod
assert not evaluator.matches(sub_sub_context, []) # not a root
def test_i_can_eval_concept(self):
sheerka, root_context = self.init_concepts()
root_context.add_to_global_hints(BuiltinConcepts.RETURN_BODY_REQUESTED)
context = root_context.push(BuiltinConcepts.PROCESSING, None)
evaluator = ReturnBodyEvaluator()
return_values = [
sheerka.ret("Who", True, Concept("foo", body="status -> will be reduce").auto_init()),
sheerka.ret("Who", False, Concept("foo", body="status -> won't be reduced").auto_init()),
sheerka.ret("Who", False, Concept("foo", body="body not init -> won't be reduced")),
]
res = evaluator.eval(context, return_values)
assert res == [sheerka.ret(evaluator.name, True, "status -> will be reduce")]
assert res[0].parents == [return_values[0]]
def test_i_do_not_reduce_containers_concepts(self):
sheerka, root_context = self.init_concepts()
root_context.add_to_global_hints(BuiltinConcepts.RETURN_BODY_REQUESTED)
context = root_context.push(BuiltinConcepts.PROCESSING, None)
evaluator = ReturnBodyEvaluator()
container = sheerka.new(BuiltinConcepts.EXPLANATION, body=[]) # body is initialized
return_values = [sheerka.ret("who", True, container)]
assert evaluator.eval(context, return_values) is None
+70
View File
@@ -0,0 +1,70 @@
import pytest
from core.builtin_concepts import ReturnValueConcept, ParserResultConcept, BuiltinConcepts
from core.rule import Rule, ACTION_TYPE_DEFERRED
from evaluators.RuleEvaluator import RuleEvaluator
from tests.TestUsingMemoryBasedSheerka import TestUsingMemoryBasedSheerka
class TestRuleEvaluator(TestUsingMemoryBasedSheerka):
@pytest.mark.parametrize("ret_val, expected", [
(ReturnValueConcept("some_name", True, ParserResultConcept(value=[Rule()])), True),
(ReturnValueConcept("some_name", True, ParserResultConcept(value="Not a concept")), False),
(ReturnValueConcept("some_name", True, ParserResultConcept(value=[])), False),
(ReturnValueConcept("some_name", True, Rule), False),
(ReturnValueConcept("some_name", False, ParserResultConcept(value=Rule())), False),
(ReturnValueConcept("some_name", False, ParserResultConcept(value=[Rule()])), False),
])
def test_i_can_match(self, ret_val, expected):
context = self.get_context()
assert RuleEvaluator().matches(context, ret_val) == expected
@pytest.mark.parametrize("body, expected", [
([Rule("exec", "rule1")], Rule("exec", "rule1")),
([Rule("exec", "rule1"), Rule("exec", "rule2")], [Rule("exec", "rule1"), Rule("exec", "rule2")]),
])
def test_i_can_evaluate(self, body, expected):
context = self.get_context()
ret_val = ReturnValueConcept("some_name", True, ParserResultConcept(value=body), True)
evaluator = RuleEvaluator()
result = evaluator.eval(context, ret_val)
assert result.who == evaluator.name
assert result.status
assert result.value == expected
assert result.parents == [ret_val]
def test_i_can_evaluate_deferred_rules(self):
context = self.get_context()
rule = Rule().set_id("i")
rule.metadata.action_type = ACTION_TYPE_DEFERRED
ret_val = ReturnValueConcept("some_name", True, ParserResultConcept(value=[rule]), True)
context.add_to_short_term_memory("i", 1)
evaluator = RuleEvaluator()
result = evaluator.eval(context, ret_val)
assert result.who == evaluator.name
assert result.status
assert result.value == context.sheerka.get_rule_by_id("1")
assert result.parents == [ret_val]
def test_i_cannot_evaluate_deferred_rule_if_the_rule_is_unknown(self):
sheerka, context = self.init_concepts()
rule = Rule().set_id("unknown variable")
rule.metadata.action_type = ACTION_TYPE_DEFERRED
ret_val = ReturnValueConcept("some_name", True, ParserResultConcept(value=[rule]), True)
evaluator = RuleEvaluator()
result = evaluator.eval(context, ret_val)
assert result.who == evaluator.name
assert not result.status
assert sheerka.isinstance(result.value, BuiltinConcepts.UNKNOWN_RULE)
assert result.value.body == [('id', 'unknown variable')]
assert result.parents == [ret_val]