Fixed #68: Implement SheerkaQL

Fixed #70: SheerkaFilterManager : Pipe functions
Fixed #71: SheerkaFilterManager : filter_objects
Fixed #75: SheerkaMemory: Enhance memory() to use the filtering capabilities
Fixed #76: SheerkaEvaluateConcept: Concepts that modify the state of the system must not be evaluated during question
This commit is contained in:
2021-04-26 19:13:47 +02:00
parent bef5f3208c
commit 1059ce25c5
57 changed files with 5759 additions and 1302 deletions
+12 -741
View File
@@ -1,5 +1,3 @@
import ast
import pytest
from core.builtin_concepts import BuiltinConcepts, ReturnValueConcept
@@ -7,26 +5,20 @@ 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.SheerkaEvaluateRules import SheerkaEvaluateRules
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, PythonConditionExprVisitor, \
CompiledCondition
PythonCodeEmitter, FormatAstNode, ReteConditionExprVisitor
from core.tokenizer import Token, TokenKind
from evaluators.PythonEvaluator import Expando
from parsers.BaseParser import ErrorSink
from parsers.ExpressionParser import ExpressionParser
from parsers.PythonParser import PythonNode
from sheerkarete.common import V
from sheerkarete.conditions import Condition, AndConditions, FilterCondition
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
from tests.parsers.parsers_utils import get_rete_conditions, NEGCOND, NCCOND
seq = FormatAstSequence
raw = FormatAstRawText
@@ -188,7 +180,7 @@ class TestSheerkaRuleManager(TestUsingMemoryBasedSheerka):
rule = service.init_rule(context, rule)
assert len(rule.error_sink["when"]) > 0
assert sheerka.is_error(rule.error_sink["when"][0])
assert sheerka.has_error(context, rule.error_sink["when"][0])
assert "print" not in rule.error_sink
assert "then" not in rule.error_sink
assert rule.metadata.is_compiled
@@ -210,7 +202,7 @@ class TestSheerkaRuleManager(TestUsingMemoryBasedSheerka):
other_action_type = ACTION_TYPE_PRINT if action_type == ACTION_TYPE_EXEC else ACTION_TYPE_EXEC
assert sheerka.is_error(rule.error_sink[action_type])
assert sheerka.has_error(context, rule.error_sink[action_type])
assert other_action_type not in rule.error_sink
assert "when" not in rule.error_sink
assert rule.metadata.is_compiled
@@ -282,30 +274,6 @@ class TestSheerkaRuleManager(TestUsingMemoryBasedSheerka):
assert parser.error_sink == expected_error
@pytest.mark.parametrize("text, compiled_text", [
("a == 5", "a == 5"),
("foo > 5", "foo > 5"),
("func() == 5", "func() == 5"),
("not a == 5", "not (a == 5)"),
("not foo > 5", "not (foo > 5)"),
("not func() == 5", "not (func() == 5)"),
])
def test_i_can_compile_predicate_when_pure_python(self, text, compiled_text):
sheerka, context, *concepts = self.init_concepts("foo")
service = sheerka.services[SheerkaRuleManager.NAME]
ast_ = ast.parse(compiled_text, "<source>", 'eval')
expected_python_node = PythonNode(compiled_text, ast_)
compilation_result = service.compile_when(context, "test", text)
res = compilation_result.python_conditions
assert len(res) == 1
assert isinstance(res[0], CompiledCondition)
assert res[0].evaluator_type == PYTHON_EVALUATOR_NAME
assert sheerka.isinstance(res[0].return_value, BuiltinConcepts.RETURN_VALUE)
assert sheerka.objvalue(res[0].return_value) == expected_python_node
assert res[0].concept is None
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()
@@ -499,20 +467,6 @@ isinstance(var, Concept) and var.key == 'hello __var__0'""" + \
res = sheerka.get_exec_rules()
assert res == [r2, r3, r1]
@pytest.mark.skip
def test_i_can_compile_rete_using_name(self):
sheerka, context, *concepts = self.init_test().unpack()
service = sheerka.services[SheerkaRuleManager.NAME]
text = "__ret"
compilation_result = service.compile_when(context, "test", text)
res = compilation_result.rete_disjunctions
assert len(res) == 1
assert isinstance(res[0], AndConditions)
assert res[0].conditions == [Condition(V("__x_00__"), "__name__", "__ret")]
def test_i_can_properly_copy_a_rule(self):
sheerka, context = self.init_test().unpack()
service = sheerka.services[SheerkaRuleManager.NAME]
@@ -525,98 +479,6 @@ isinstance(var, Concept) and var.key == 'hello __var__0'""" + \
for k, v in vars(rule).items():
assert getattr(clone, k) == getattr(rule, k)
@pytest.mark.parametrize("expression, expected_as_str, expected_variables", [
(
"__ret",
["#__x_00__|__name__|'__ret'"],
{"__ret"}
),
(
"__ret.status == True",
["#__x_00__|__name__|'__ret'", "#__x_00__|status|True"],
{"__ret"}
),
(
"__ret.status",
["#__x_00__|__name__|'__ret.status'"],
{"__ret.status"}
),
(
"body",
["#__x_00__|__name__|'body'"],
{"body"}
),
(
"__ret and __ret.status",
["#__x_00__|__name__|'__ret'", "#__x_01__|__name__|'__ret.status'"],
{"__ret", "__ret.status"}
),
])
def test_i_can_get_rete_conditions(self, expression, expected_as_str, expected_variables):
sheerka, context = self.init_test().unpack()
parser = ExpressionParser()
expected = get_rete_conditions(*expected_as_str)
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 = ReteConditionExprVisitor(context)
conditions = visitor.get_conditions(parsed)
assert conditions == [expected]
# check against a Rete network
network = ReteNetwork()
rule = Rule("test", expression, None)
rule.metadata.id = 9999
rule.metadata.is_compiled = True
rule.metadata.is_enabled = True
rule.rete_disjunctions = conditions
network.add_rule(rule)
return_value = ReturnValueConcept("Test", True, None)
if "__ret" in expected_variables:
network.add_obj("__ret", return_value)
if "__ret.status" in expected_variables:
network.add_obj("__ret.status", return_value.status)
if "body" in expected_variables:
network.add_obj("body", return_value.body)
matches = list(network.matches)
assert len(matches) == 1
def test_i_can_get_rete_conditions_when_no_attribute(self):
sheerka, context = self.init_test().unpack()
expression = "a == 10"
expected_as_str = ["#__x_00__|__name__|'a'", "#__x_00__|__self__|10"]
parser = ExpressionParser()
expected = get_rete_conditions(*expected_as_str)
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 = ReteConditionExprVisitor(context)
conditions = visitor.get_conditions(parsed)
assert conditions == [expected]
# check against a Rete network
network = ReteNetwork()
rule = Rule("test", expression, None)
rule.metadata.id = 9999
rule.metadata.is_compiled = True
rule.metadata.is_enabled = True
rule.rete_disjunctions = conditions
network.add_rule(rule)
network.add_obj("a", 10)
matches = list(network.matches)
assert len(matches) == 1
@pytest.mark.skip("No ready yet for SheerkaFilterCondition")
def test_i_can_get_rete_conditions_when_function(self):
sheerka, context, greetings = self.init_test().with_concepts(
@@ -652,235 +514,6 @@ isinstance(var, Concept) and var.key == 'hello __var__0'""" + \
# matches = list(network.matches)
# assert len(matches) == 1
@pytest.mark.parametrize("test_name, expression, variable_name, expected_as_str", [
(
"recognize by name",
"recognize(__ret.body, greetings)",
None,
["#__x_00__|__name__|'__ret'",
"#__x_00__|body|#__x_01__",
"#__x_01__|__is_concept__|True",
"#__x_01__|name|'greetings'"]
),
(
"recognize by id",
"recognize(__ret.body, c:|1001:)",
None,
["#__x_00__|__name__|'__ret'",
"#__x_00__|body|#__x_01__",
"#__x_01__|__is_concept__|True",
"#__x_01__|id|'1001'"]
),
(
"recognize by name using c_str",
"recognize(__ret.body, c:greetings:)",
None,
["#__x_00__|__name__|'__ret'",
"#__x_00__|body|#__x_01__",
"#__x_01__|__is_concept__|True",
"#__x_01__|name|'greetings'"]
),
(
"recognize by name and add other conditions (str)",
"recognize(__ret.body, greetings) and __ret.body.a == 'my friend'",
"my friend",
["#__x_00__|__name__|'__ret'",
"#__x_00__|body|#__x_01__",
"#__x_01__|__is_concept__|True",
"#__x_01__|name|'greetings'",
"#__x_01__|a|'my friend'"]
),
(
"recognize by name and add other conditions (sheerka)",
"recognize(__ret.body, greetings) and __ret.body.a == sheerka",
"sheerka",
["#__x_00__|__name__|'__ret'",
"#__x_00__|body|#__x_01__",
"#__x_01__|__is_concept__|True",
"#__x_01__|name|'greetings'",
"#__x_01__|a|'__sheerka__'"]
),
(
"recognize by name and add other conditions (concept)",
"recognize(__ret.body, greetings) and __ret.body.a == foo",
"foo",
["#__x_00__|__name__|'__ret'",
"#__x_00__|body|#__x_01__",
"#__x_01__|__is_concept__|True",
"#__x_01__|name|'greetings'",
"#__x_01__|a|#__x_02__",
"#__x_02__|__is_concept__|True",
"#__x_02__|key|'foo'"]
),
(
"recognize by instance",
"recognize(__ret.body, hello sheerka)",
"sheerka",
["#__x_00__|__name__|'__ret'",
"#__x_00__|body|#__x_01__",
"#__x_01__|__is_concept__|True",
"#__x_01__|key|'hello __var__0'",
"#__x_01__|a|'__sheerka__'"]
),
(
"recognize by instance",
"recognize(__ret.body, hello 'my friend')",
"my friend",
["#__x_00__|__name__|'__ret'",
"#__x_00__|body|#__x_01__",
"#__x_01__|__is_concept__|True",
"#__x_01__|key|'hello __var__0'",
"#__x_01__|a|'my friend'"]
),
(
"recognize by instance",
"recognize(__ret.body, hello foo)",
"foo",
["#__x_00__|__name__|'__ret'",
"#__x_00__|body|#__x_01__",
"#__x_01__|__is_concept__|True",
"#__x_01__|key|'hello __var__0'",
"#__x_01__|a|#__x_02__",
"#__x_02__|__is_concept__|True",
"#__x_02__|key|'foo'",
]
),
(
"recognize by instance when long concept",
"recognize(__ret.body, hello my best friend)",
"my best friend",
["#__x_00__|__name__|'__ret'",
"#__x_00__|body|#__x_01__",
"#__x_01__|__is_concept__|True",
"#__x_01__|key|'hello __var__0'",
"#__x_01__|a|#__x_02__",
"#__x_02__|__is_concept__|True",
"#__x_02__|key|'my best friend'",
]
),
])
def test_i_can_get_rete_using_recognize_function(self, test_name, expression, variable_name, expected_as_str):
sheerka, context, greetings, foo, my_best_friend = self.init_test().with_concepts(
Concept("greetings", definition="hello a", definition_type=DEFINITION_TYPE_DEF).def_var("a"),
Concept("foo"),
Concept("my best friend"),
create_new=True
).unpack()
parser = ExpressionParser()
expected = get_rete_conditions(*expected_as_str)
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 = ReteConditionExprVisitor(context)
conditions = visitor.get_conditions(parsed)
assert conditions == [expected]
# check against a Rete network
network = ReteNetwork()
rule = Rule("test", expression, None)
rule.metadata.id = 9999
rule.metadata.is_compiled = True
rule.metadata.is_enabled = True
rule.rete_disjunctions = conditions
network.add_rule(rule)
variable_map = {
"foo": foo,
"my best friend": my_best_friend,
"sheerka": sheerka
}
variable = variable_map.get(variable_name, variable_name)
to_recognize = sheerka.new_from_template(greetings, greetings.key, a=variable)
network.add_obj("__ret", ReturnValueConcept("Test", True, to_recognize))
matches = list(network.matches)
assert len(matches) == 1
@pytest.mark.parametrize("expression, variable_name, expected_as_str", [
(
"greetings",
None,
["#__x_00__|__name__|'__ret'",
"#__x_00__|body|#__x_01__",
"#__x_01__|__is_concept__|True",
"#__x_01__|name|'greetings'"]
),
(
"c:|1001:",
None,
["#__x_00__|__name__|'__ret'",
"#__x_00__|body|#__x_01__",
"#__x_01__|__is_concept__|True",
"#__x_01__|id|'1001'"]
),
(
"hello foo",
"foo",
["#__x_00__|__name__|'__ret'",
"#__x_00__|body|#__x_01__",
"#__x_01__|__is_concept__|True",
"#__x_01__|key|'hello __var__0'",
"#__x_01__|a|#__x_02__",
"#__x_02__|__is_concept__|True",
"#__x_02__|key|'foo'",
]
),
(
"hello my best friend",
"my best friend",
["#__x_00__|__name__|'__ret'",
"#__x_00__|body|#__x_01__",
"#__x_01__|__is_concept__|True",
"#__x_01__|key|'hello __var__0'",
"#__x_01__|a|#__x_02__",
"#__x_02__|__is_concept__|True",
"#__x_02__|key|'my best friend'",
]
),
])
def test_i_can_get_rete_when_a_concept_is_recognized(self, expression, variable_name, expected_as_str):
sheerka, context, greetings, foo, my_best_friend = self.init_test().with_concepts(
Concept("greetings", definition="hello a", definition_type=DEFINITION_TYPE_DEF).def_var("a"),
Concept("foo"),
Concept("my best friend"),
create_new=True
).unpack()
parser = ExpressionParser()
expected = get_rete_conditions(*expected_as_str)
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 = ReteConditionExprVisitor(context)
conditions = visitor.get_conditions(parsed)
assert conditions == [expected]
# check against a Rete network
network = ReteNetwork()
rule = Rule("test", expression, None)
rule.metadata.id = 9999
rule.metadata.is_compiled = True
rule.metadata.is_enabled = True
rule.rete_disjunctions = conditions
network.add_rule(rule)
variable_map = {
"foo": foo,
"my best friend": my_best_friend,
"sheerka": sheerka
}
variable = variable_map.get(variable_name, variable_name)
to_recognize = sheerka.new_from_template(greetings, greetings.key, a=variable)
network.add_obj("__ret", ReturnValueConcept("Test", True, to_recognize))
matches = list(network.matches)
assert len(matches) == 1
@pytest.mark.parametrize("expression, bag_key, expected", [
("not __ret", "__other", [NEGCOND("#__x_00__|__name__|'__ret'")]),
("not not __ret", "__ret", ["#__x_00__|__name__|'__ret'"]),
@@ -894,6 +527,10 @@ isinstance(var, Concept) and var.key == 'hello __var__0'""" + \
"#__x_01__|key|'hello __var__0'",
"#__x_01__|a|'__sheerka__'"])]),
("__ret and not __error", "__ret", ["#__x_00__|__name__|'__ret'", NEGCOND("#__x_01__|__name__|'__error'")]),
("not recognize(self, hello sheerka)", "__ret", ["#__x_00__|__name__|'self'",
NCCOND(["#__x_00__|__is_concept__|True",
"#__x_00__|key|'hello __var__0'",
"#__x_00__|a|'__sheerka__'"])]),
])
def test_i_can_get_rete_using_not(self, expression, bag_key, expected):
sheerka, context, greetings, foo = self.init_test().with_concepts(
@@ -914,7 +551,7 @@ isinstance(var, Concept) and var.key == 'hello __var__0'""" + \
assert conditions == [expected_conditions]
@pytest.mark.skip("I am not sure yet of what I want to get")
@pytest.mark.parametrize("expression, expected_as_str", [
@pytest.mark.parametrize("expression, expected_as_list_of_str", [
(
"eval(__ret.body, 'foo' starts with 'f')",
["#__x_00__|__name__|'__ret'",
@@ -926,7 +563,7 @@ isinstance(var, Concept) and var.key == 'hello __var__0'""" + \
"$eval(__x_01__, a, b, c)"]
),
])
def test_i_can_get_rete_conditions_using_eval_function(self, expression, expected_as_str):
def test_i_can_get_rete_conditions_using_eval_function(self, expression, expected_as_list_of_str):
sheerka, context, start_with = self.init_test().with_concepts(
Concept("x starts with y",
pre="is_question",
@@ -935,7 +572,7 @@ isinstance(var, Concept) and var.key == 'hello __var__0'""" + \
).unpack()
parser = ExpressionParser()
expected = get_rete_conditions(*expected_as_str)
expected = get_rete_conditions(*expected_as_list_of_str)
error_sink = ErrorSink()
parser_input = ParserInput(expression)
@@ -961,372 +598,6 @@ isinstance(var, Concept) and var.key == 'hello __var__0'""" + \
matches = list(network.matches)
assert len(matches) == 1
@pytest.mark.parametrize("expression, expected_compiled, expected_variables", [
("__ret", None, {"__ret"}),
("__ret.status == True", "__ret.status == True", {"__ret"}),
("__ret.status", None, {"__ret.status"}),
("body", None, {"body"}),
("__ret and __ret.status", None, {"__ret", "__ret.status"})
])
def test_i_can_get_compiled_conditions(self, expression, expected_compiled, expected_variables):
sheerka, context = self.init_test().unpack()
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)
assert len(conditions) == 1
assert isinstance(conditions[0], CompiledCondition)
if expected_compiled:
ast_ = ast.parse(expected_compiled, "<source>", 'eval')
expected_python_node = PythonNode(expected_compiled, ast_)
assert conditions[0].evaluator_type == PYTHON_EVALUATOR_NAME
assert sheerka.isinstance(conditions[0].return_value, BuiltinConcepts.RETURN_VALUE)
assert sheerka.objvalue(conditions[0].return_value) == expected_python_node
else:
assert conditions[0].evaluator_type is None
assert conditions[0].return_value is None
assert conditions[0].concept is None
assert conditions[0].variables == expected_variables
# check against SheerkaEvaluateRules
evaluate_rules_service = sheerka.services[SheerkaEvaluateRules.NAME]
return_value = ReturnValueConcept("Test", True, None)
bag = {}
if "__ret" in expected_variables:
bag["__ret"] = return_value
if "__ret.status" in expected_variables:
bag["__ret.status"] = return_value.status
if "body" in expected_variables:
bag["body"] = return_value.body
with context.push(BuiltinConcepts.RULES_EVALUATION, bag, desc="Evaluating rules...") as sub_context:
sub_context.sheerka.add_many_to_short_term_memory(sub_context, bag)
rule = Rule(name="test_i_can_get_compiled_conditions", predicate=expression)
rule.compiled_conditions = conditions
res = evaluate_rules_service.evaluate_rule(sub_context, rule, bag)
assert res.status
assert self.sheerka.is_success(self.sheerka.objvalue(res))
def test_i_can_get_compiled_conditions_when_no_attribute(self):
sheerka, context = self.init_test().unpack()
expression = "a == 10"
expected_compiled = "a == 10"
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)
assert len(conditions) == 1
assert isinstance(conditions[0], CompiledCondition)
ast_ = ast.parse(expected_compiled, "<source>", 'eval')
expected_python_node = PythonNode(expected_compiled, ast_)
assert conditions[0].evaluator_type == PYTHON_EVALUATOR_NAME
assert sheerka.isinstance(conditions[0].return_value, BuiltinConcepts.RETURN_VALUE)
assert sheerka.objvalue(conditions[0].return_value) == expected_python_node
assert conditions[0].concept is None
assert conditions[0].variables == {"a"}
# check against SheerkaEvaluateRules
evaluate_rules_service = sheerka.services[SheerkaEvaluateRules.NAME]
bag = {"a": 10}
with context.push(BuiltinConcepts.RULES_EVALUATION, bag, desc="Evaluating rules...") as sub_context:
sub_context.sheerka.add_many_to_short_term_memory(sub_context, bag)
rule = Rule(name="test_i_can_get_compiled_conditions", predicate=expression)
rule.compiled_conditions = conditions
res = evaluate_rules_service.evaluate_rule(sub_context, rule, bag)
assert res.status
assert self.sheerka.is_success(self.sheerka.objvalue(res))
def test_i_can_get_compiled_conditions_when_function(self):
sheerka, context, greetings = self.init_test().with_concepts(
Concept("greetings", definition="hello a", definition_type=DEFINITION_TYPE_DEF).def_var("a"),
).unpack()
expression = "isinstance(a, greetings)"
expected_compiled = "isinstance(a, greetings)"
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)
assert len(conditions) == 1
assert isinstance(conditions[0], CompiledCondition)
ast_ = ast.parse(expected_compiled, "<source>", 'eval')
expected_python_node = PythonNode(expected_compiled, ast_)
assert conditions[0].evaluator_type == PYTHON_EVALUATOR_NAME
assert sheerka.isinstance(conditions[0].return_value, BuiltinConcepts.RETURN_VALUE)
assert sheerka.objvalue(conditions[0].return_value) == expected_python_node
assert conditions[0].concept is None
assert conditions[0].variables == {"a"}
# check against SheerkaEvaluateRules
evaluate_rules_service = sheerka.services[SheerkaEvaluateRules.NAME]
bag = {"a": sheerka.new(greetings, a="my friend")}
with context.push(BuiltinConcepts.RULES_EVALUATION, bag, desc="Evaluating rules...") as sub_context:
sub_context.sheerka.add_many_to_short_term_memory(sub_context, bag)
rule = Rule(name="test_i_can_get_compiled_conditions", predicate=expression)
rule.compiled_conditions = conditions
res = evaluate_rules_service.evaluate_rule(sub_context, rule, bag)
assert res.status
assert self.sheerka.is_success(self.sheerka.objvalue(res))
@pytest.mark.parametrize("expression, variable_name, expected_compiled", [
(
"recognize(__ret.body, greetings)",
None,
"__x_00__ = __ret.body\nisinstance(__x_00__, Concept) and __x_00__.name == 'greetings'"
),
(
"recognize(__ret.body, c:|1001:)",
None,
"__x_00__ = __ret.body\nisinstance(__x_00__, Concept) and __x_00__.id == '1001'"
),
(
"recognize(__ret.body, c:greetings:)",
None,
"__x_00__ = __ret.body\nisinstance(__x_00__, Concept) and __x_00__.name == 'greetings'"
),
(
"recognize(__ret.body, greetings) and __ret.body.a == 'my friend'",
"my friend",
"__x_00__ = __ret.body\nisinstance(__x_00__, Concept) and __x_00__.name == 'greetings' and __x_00__.a == 'my friend'"
),
(
"recognize(__ret.body, greetings) and __ret.body.a == sheerka",
"sheerka",
"""__x_00__ = __ret.body
isinstance(__x_00__, Concept) and __x_00__.name == 'greetings' and is_sheerka(__x_00__.a)"""
),
(
"recognize(__ret.body, greetings) and __ret.body.a == foo",
"foo",
"""__x_00__ = __ret.body
__x_01__ = __x_00__.a
isinstance(__x_00__, Concept) and __x_00__.name == 'greetings' and isinstance(__x_01__, Concept) and __x_01__.key == 'foo'"""
),
(
"recognize(__ret.body, hello sheerka)",
"sheerka",
"""__x_00__ = __ret.body
isinstance(__x_00__, Concept) and __x_00__.key == 'hello __var__0' and is_sheerka(__x_00__.a)"""
),
(
"recognize(__ret.body, hello 'my friend')",
"my friend",
"""__x_00__ = __ret.body
isinstance(__x_00__, Concept) and __x_00__.key == 'hello __var__0' and __x_00__.a == 'my friend'"""
),
(
"recognize(__ret.body, hello foo)",
"foo",
"""__x_00__ = __ret.body
__x_01__ = __x_00__.a
isinstance(__x_00__, Concept) and __x_00__.key == 'hello __var__0' and isinstance(__x_01__, Concept) and __x_01__.key == 'foo'"""
),
(
"recognize(__ret.body, hello my best friend)",
"my best friend",
"""__x_00__ = __ret.body
__x_01__ = __x_00__.a
isinstance(__x_00__, Concept) and __x_00__.key == 'hello __var__0' and isinstance(__x_01__, Concept) and __x_01__.key == 'my best friend'"""
),
])
def test_i_can_get_compiled_using_recognize_function(self, expression, variable_name, expected_compiled):
sheerka, context, greetings, foo, my_best_friend = self.init_test().with_concepts(
Concept("greetings", definition="hello a", definition_type=DEFINITION_TYPE_DEF).def_var("a"),
Concept("foo"),
Concept("my best friend"),
create_new=True
).unpack()
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)
assert len(conditions) == 1
assert isinstance(conditions[0], CompiledCondition)
if expected_compiled:
ast_ = ast.parse(expected_compiled, "<source>", 'exec')
expected_python_node = PythonNode(expected_compiled, ast_, expected_compiled)
assert conditions[0].evaluator_type == PYTHON_EVALUATOR_NAME
assert sheerka.isinstance(conditions[0].return_value, BuiltinConcepts.RETURN_VALUE)
assert sheerka.objvalue(conditions[0].return_value) == expected_python_node
else:
assert conditions[0].evaluator_type is None
assert conditions[0].return_value is None
assert conditions[0].concept is None
assert conditions[0].variables == {"__ret"}
# check against SheerkaEvaluateRules
evaluate_rules_service = sheerka.services[SheerkaEvaluateRules.NAME]
variable_map = {
"foo": foo,
"my best friend": my_best_friend,
"sheerka": Expando("sheerka", {})
}
variable = variable_map.get(variable_name, variable_name)
to_recognize = sheerka.new_from_template(greetings, greetings.key, a=variable)
bag = {"__ret": ReturnValueConcept("Test", True, to_recognize)}
with context.push(BuiltinConcepts.RULES_EVALUATION, bag, desc="Evaluating rules...") as sub_context:
sub_context.sheerka.add_many_to_short_term_memory(sub_context, bag)
rule = Rule(name="test_i_can_get_compiled_using_recognize_function", predicate=expression)
rule.compiled_conditions = conditions
res = evaluate_rules_service.evaluate_rule(sub_context, rule, bag)
assert res.status
assert self.sheerka.is_success(self.sheerka.objvalue(res))
@pytest.mark.parametrize("expression, variable_name, expected_compiled", [
(
"greetings",
None,
"__x_00__ = __ret.body\nisinstance(__x_00__, Concept) and __x_00__.name == 'greetings'"
),
(
"c:|1001:",
None,
"__x_00__ = __ret.body\nisinstance(__x_00__, Concept) and __x_00__.id == '1001'"
),
(
"hello foo",
"foo",
"""__x_00__ = __ret.body
__x_01__ = __x_00__.a
isinstance(__x_00__, Concept) and __x_00__.key == 'hello __var__0' and isinstance(__x_01__, Concept) and __x_01__.key == 'foo'"""
),
(
"hello my best friend",
"my best friend",
"""__x_00__ = __ret.body
__x_01__ = __x_00__.a
isinstance(__x_00__, Concept) and __x_00__.key == 'hello __var__0' and isinstance(__x_01__, Concept) and __x_01__.key == 'my best friend'"""
),
])
def test_i_can_get_compiled_when_a_concept_is_recognized(self, expression, variable_name, expected_compiled):
sheerka, context, greetings, foo, my_best_friend = self.init_test().with_concepts(
Concept("greetings", definition="hello a", definition_type=DEFINITION_TYPE_DEF).def_var("a"),
Concept("foo"),
Concept("my best friend"),
create_new=True
).unpack()
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)
assert len(conditions) == 1
assert isinstance(conditions[0], CompiledCondition)
if expected_compiled:
ast_ = ast.parse(expected_compiled, "<source>", 'exec')
expected_python_node = PythonNode(expected_compiled, ast_, expected_compiled)
assert conditions[0].evaluator_type == PYTHON_EVALUATOR_NAME
assert sheerka.isinstance(conditions[0].return_value, BuiltinConcepts.RETURN_VALUE)
assert sheerka.objvalue(conditions[0].return_value) == expected_python_node
else:
assert conditions[0].evaluator_type is None
assert conditions[0].return_value is None
assert conditions[0].concept is None
assert conditions[0].variables == {"__ret"}
# check against SheerkaEvaluateRules
evaluate_rules_service = sheerka.services[SheerkaEvaluateRules.NAME]
variable_map = {
"foo": foo,
"my best friend": my_best_friend,
"sheerka": Expando("sheerka", {})
}
variable = variable_map.get(variable_name, variable_name)
to_recognize = sheerka.new_from_template(greetings, greetings.key, a=variable)
bag = {"__ret": ReturnValueConcept("Test", True, to_recognize)}
with context.push(BuiltinConcepts.RULES_EVALUATION, bag, desc="Evaluating rules...") as sub_context:
sub_context.sheerka.add_many_to_short_term_memory(sub_context, bag)
rule = Rule(name="test_i_can_get_compiled_using_recognize_function", predicate=expression)
rule.compiled_conditions = conditions
res = evaluate_rules_service.evaluate_rule(sub_context, rule, bag)
assert res.status
assert self.sheerka.is_success(self.sheerka.objvalue(res))
@pytest.mark.parametrize("expression, expected_compiled, variables, not_variables", [
("not __ret", None, set(), {"__ret"}),
("not not __ret", None, {"__ret"}, set()),
("not __ret.status == True", "not (__ret.status == True)", {"__ret"}, set()),
("not __ret.status", None, set(), {"__ret.status"},),
("__ret and not __ret.status", None, {"__ret"}, {"__ret.status"}),
("not recognize(__ret.body, hello sheerka)", """__x_00__ = __ret.body
not (isinstance(__x_00__, Concept) and __x_00__.key == 'hello __var__0' and is_sheerka(__x_00__.a))""", {"__ret"},
set()),
("__ret and not __error", None, {"__ret"}, {"__error"}),
])
def test_i_can_get_compiled_condition_using_not(self, expression, expected_compiled, variables, not_variables):
sheerka, context, greetings, foo = self.init_test().with_concepts(
Concept("greetings", definition="hello a", definition_type=DEFINITION_TYPE_DEF).def_var("a"),
Concept("foo"),
).unpack()
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)
assert len(conditions) == 1
assert isinstance(conditions[0], CompiledCondition)
if expected_compiled:
if "\n" in expected_compiled:
ast_ = ast.parse(expected_compiled, "<source>", 'exec')
else:
ast_ = ast.parse(expected_compiled, "<source>", 'eval')
expected_python_node = PythonNode(expected_compiled, ast_)
assert conditions[0].evaluator_type == PYTHON_EVALUATOR_NAME
assert sheerka.isinstance(conditions[0].return_value, BuiltinConcepts.RETURN_VALUE)
assert sheerka.objvalue(conditions[0].return_value) == expected_python_node
else:
assert conditions[0].evaluator_type is None
assert conditions[0].return_value is None
assert conditions[0].variables == variables
assert conditions[0].not_variables == not_variables
assert conditions[0].concept is None
# check against SheerkaEvaluateRules
evaluate_rules_service = sheerka.services[SheerkaEvaluateRules.NAME]
ret_val_key = "__ret" if "__ret" in conditions[0].variables else "__other"
bag = {ret_val_key: ReturnValueConcept("Test", False, None)}
with context.push(BuiltinConcepts.RULES_EVALUATION, bag, desc="Evaluating rules...") as sub_context:
sub_context.sheerka.add_many_to_short_term_memory(sub_context, bag)
rule = Rule(name="test_i_can_get_compiled_conditions", predicate=expression)
rule.compiled_conditions = conditions
res = evaluate_rules_service.evaluate_rule(sub_context, rule, bag)
assert res.status
assert self.sheerka.is_success(self.sheerka.objvalue(res))
class TestSheerkaRuleManagerUsingFileBasedSheerka(TestUsingFileBasedSheerka):
def test_rules_are_initialized_at_startup(self):