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:
@@ -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):
|
||||
|
||||
Reference in New Issue
Block a user