Files
Sheerka-Old/tests/core/test_SheerkaRuleManagerRulesCompilation.py
T
kodjo 1059ce25c5 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
2021-04-26 19:13:47 +02:00

1162 lines
45 KiB
Python

import ast
import pytest
from core.builtin_concepts import ReturnValueConcept
from core.builtin_concepts_ids import BuiltinConcepts
from core.concept import Concept, DEFINITION_TYPE_DEF
from core.rule import Rule
from core.sheerka.services.SheerkaEvaluateRules import SheerkaEvaluateRules
from core.sheerka.services.SheerkaExecute import ParserInput
from core.sheerka.services.SheerkaRuleManager import ReteConditionExprVisitor, PythonConditionExprVisitor, \
CompiledCondition
from core.sheerka.services.sheerka_service import FailedToCompileError
from evaluators.PythonEvaluator import PythonEvaluator
from parsers.BaseParser import ErrorSink
from parsers.ExpressionParser import ExpressionParser
from parsers.PythonParser import PythonNode
from sheerkapython.python_wrapper import Expando
from sheerkarete.network import ReteNetwork
from tests.TestUsingMemoryBasedSheerka import TestUsingMemoryBasedSheerka
from tests.core.test_SheerkaRuleManager import PYTHON_EVALUATOR_NAME
from tests.parsers.parsers_utils import get_rete_conditions, NEGCOND
class BaseTestSheerkaRuleManagerRulesCompilation(TestUsingMemoryBasedSheerka):
@staticmethod
def check_against_rete(rule_expression, rule_conditions, objects):
"""
:param rule_expression:
:param rule_conditions:
:param objects: list of tuple(name, obj)
:return:
"""
# check against a Rete network
network = ReteNetwork()
rule = Rule("test", rule_expression, None)
rule.metadata.id = 9999
rule.metadata.is_compiled = True
rule.metadata.is_enabled = True
rule.rete_disjunctions = rule_conditions
network.add_rule(rule)
for name, value in objects.items():
network.add_obj(name, value)
matches = list(network.matches)
assert len(matches) == 1
@staticmethod
def check_against_python(context, rule_expression, rule_conditions, objects, expected_result=True):
bag = {}
for name, value in objects.items():
bag[name] = value
evaluate_rules_service = context.sheerka.services[SheerkaEvaluateRules.NAME]
rule = Rule(name="test", predicate=rule_expression)
rule.compiled_conditions = rule_conditions
rule.metadata.is_enabled = True
rule.metadata.is_compiled = True
evaluation = evaluate_rules_service.evaluate_rules(context, [rule], bag, set())
assert expected_result in evaluation and len(evaluation[expected_result]) == 1
@staticmethod
def evaluate_condition(context, expression, condition, objects):
with context.push("Testing conditions SheerkaRuleManagerRulesCompilation", expression) as sub_context:
sub_context.protected_hints.add(BuiltinConcepts.EVAL_BODY_REQUESTED)
sub_context.protected_hints.add(BuiltinConcepts.EVAL_WHERE_REQUESTED)
sub_context.protected_hints.add(BuiltinConcepts.EVAL_UNTIL_SUCCESS_REQUESTED)
sub_context.protected_hints.add(BuiltinConcepts.EVAL_QUESTION_REQUESTED)
sub_context.sheerka.add_many_to_short_term_memory(sub_context, objects)
evaluator = PythonEvaluator()
return evaluator.eval(sub_context, condition.return_value)
@classmethod
def get_testing_objects(cls, context, objects_names, objects_mappings=None):
if objects_names is None:
return {}
result = {}
for name in objects_names:
if isinstance(name, tuple):
name, value = name
if value == "sheerka":
value = context.sheerka
else:
value = None
if objects_mappings and value in objects_mappings:
value = objects_mappings[value]
if name == "__ret":
return_value = ReturnValueConcept("Test", True, value)
result["__ret"] = return_value
elif name == "__ret.status":
return_value = ReturnValueConcept("Test", True, value)
result["__ret.status"] = return_value.status
elif name == "body":
return_value = ReturnValueConcept("Test", True, value)
result["body"] = return_value.body
elif name == "a_string":
result["a_string"] = value or "hello world!"
elif name == "an_int":
result["an_int"] = value or 10
else:
result[name] = value
return result
@staticmethod
def get_variables_names_from_expected_variables(expected_variables):
return {v[0] if isinstance(v, tuple) else v for v in expected_variables}
@staticmethod
def func_true(*args, **kwargs):
return True
@staticmethod
def func_identity(x):
return x
def validate_python_test(self,
context,
expression,
expected_compiled,
expected_text,
expected_variables,
expected_not_variables,
expected_objects):
sheerka = context.sheerka
parser = ExpressionParser()
error_sink = ErrorSink()
parser_input = ParserInput(expression)
parser.reset_parser_input(parser_input, error_sink)
parsed = parser.parse_input(context, parser_input, error_sink)
visitor = PythonConditionExprVisitor(context)
conditions = visitor.get_conditions(parsed)
assert len(conditions) == 1
assert isinstance(conditions[0], CompiledCondition)
if expected_compiled is None:
# manage cases where we only check for variable existence
assert conditions[0].evaluator_type is None
assert conditions[0].return_value is None
else:
# check what was compiled
ast_ = ast.parse(expected_compiled, "<source>", 'exec' if "\n" in expected_compiled else 'eval')
expected_python_node = PythonNode(expected_compiled, ast_, expected_text)
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
# check that variables detected
assert conditions[0].variables == self.get_variables_names_from_expected_variables(expected_variables)
# check that variables that MUST not be present
assert conditions[0].not_variables == expected_not_variables
# check the objects returned
assert len(expected_objects) == len(conditions[0].objects)
for obj in expected_objects:
if isinstance(obj, tuple):
assert conditions[0].objects[obj[0]] == obj[1]
else:
assert obj in conditions[0].objects
return conditions
class TestSheerkaRuleManagerRulesCompilationExists(BaseTestSheerkaRuleManagerRulesCompilation):
"""
Testing variable existence:
__ret (exists)
__ret.status (exists)
body (exists)
__ret and __ret.status (both exist)
"""
@pytest.mark.parametrize("expression, expected_as_list_of_str, expected_variables", [
(
"__ret", ["#__x_00__|__name__|'__ret'"], {"__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_rete(self, expression, expected_as_list_of_str, expected_variables):
sheerka, context = self.init_test().unpack()
parser = ExpressionParser()
expected = get_rete_conditions(*expected_as_list_of_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
objects = self.get_testing_objects(context, expected_variables)
self.check_against_rete(expression, conditions, objects)
@pytest.mark.parametrize("expression, expected_variables", [
("__ret", {"__ret"}),
("__ret.status", {"__ret.status"}),
("body", {"body"}),
("__ret and __ret.status", {"__ret", "__ret.status"})
])
def test_python(self, expression, expected_variables):
sheerka, context = self.init_test().unpack()
conditions = self.validate_python_test(context,
expression,
None,
None,
expected_variables,
set(),
set())
# check against SheerkaEvaluateRules
objects = self.get_testing_objects(context, expected_variables)
self.check_against_python(context, expression, conditions, objects)
class TestSheerkaRuleManagerRulesCompilationNotExists(BaseTestSheerkaRuleManagerRulesCompilation):
"""
Testing NOT existence
not __ret
not not __ret
not __ret.status
not body
not __ret and not __ret.status
__ret and not ret.status
__ret and not __error
"""
@pytest.mark.parametrize("expression, expected_as_list_of_str", [
("not __ret", [NEGCOND("#__x_00__|__name__|'__ret'")]),
("not not __ret", ["#__x_00__|__name__|'__ret'"]),
("not __ret.status", [NEGCOND("#__x_00__|__name__|'__ret.status'")]),
("not body", [NEGCOND("#__x_00__|__name__|'body'")]),
(
"not __ret and not __ret.status",
[NEGCOND("#__x_00__|__name__|'__ret'"), NEGCOND("#__x_01__|__name__|'__ret.status'")]
),
(
"__ret and not __ret.status",
["#__x_00__|__name__|'__ret'", NEGCOND("#__x_01__|__name__|'__ret.status'")]
),
(
"__ret and not __error",
["#__x_00__|__name__|'__ret'", NEGCOND("#__x_01__|__name__|'__error'")]
),
])
def test_rete(self, expression, expected_as_list_of_str):
sheerka, context = self.init_test().unpack()
parser = ExpressionParser()
expected = get_rete_conditions(*expected_as_list_of_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
# objects = self.get_testing_objects(context, expected_variables)
# self.check_against_rete(expression, conditions, objects)
@pytest.mark.parametrize("expression, expected_variables, expected_not_variables", [
("not __ret", set(), {"__ret"}),
("not not __ret", {"__ret"}, set()),
("not __ret.status", set(), {"__ret.status"}),
("not body", set(), {"body"}),
("not __ret and not __ret.status", set(), {"__ret", "__ret.status"}),
("__ret and not __ret.status", {"__ret"}, {"__ret.status"}),
("__ret and not __error", {"__ret"}, {"__error"}),
])
def test_python(self, expression, expected_variables, expected_not_variables):
sheerka, context = self.init_test().unpack()
conditions = self.validate_python_test(context,
expression,
None,
None,
expected_variables,
expected_not_variables,
set())
# check against SheerkaEvaluateRules
objects = self.get_testing_objects(context, expected_variables)
self.check_against_python(context, expression, conditions, objects)
class TestSheerkaRuleManagerRulesCompilationEquality(BaseTestSheerkaRuleManagerRulesCompilation):
"""
Testing simple equality:
a == 10
__ret.status == True
self == 'a'
self == sheerka
self == BuiltinConcepts.TO_DICT
self == hello 'my friend'
"""
@pytest.mark.parametrize("expression, expected_as_list_of_str, expected_variables", [
("a == 10", ["#__x_00__|__name__|'a'", "#__x_00__|__self__|10"], {("a", 10)}),
("__ret.status == True", ["#__x_00__|__name__|'__ret'", "#__x_00__|status|True"], {"__ret"}),
("self == 'a'", ["#__x_00__|__name__|'self'", "#__x_00__|__self__|'a'"], {("self", 'a')}),
("self == sheerka", ["#__x_00__|__name__|'self'", "#__x_00__|__self__|'__sheerka__'"], {("self", "sheerka")}),
(
"self == BuiltinConcepts.TO_DICT",
["#__x_00__|__name__|'self'", "#__x_00__|__self__|BuiltinConcepts.TO_DICT"],
{("self", BuiltinConcepts.TO_DICT)}
),
("self == hello 'my friend'",
["#__x_00__|__name__|'self'",
"#__x_00__|__is_concept__|True",
"#__x_00__|key|'hello __var__0'",
"#__x_00__|a|'my friend'"],
{("self", "hello_my_friend")}
)
])
def test_rete(self, expression, expected_as_list_of_str, expected_variables):
sheerka, context, greetings = self.init_test().with_concepts(
Concept("greetings", definition="hello a", definition_type=DEFINITION_TYPE_DEF).def_var("a"),
create_new=True
).unpack()
parser = ExpressionParser()
expected = get_rete_conditions(*expected_as_list_of_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
objects_mappings = {"hello_my_friend": sheerka.new(greetings, a='my friend')}
objects = self.get_testing_objects(context, expected_variables, objects_mappings)
self.check_against_rete(expression, conditions, objects)
@pytest.mark.parametrize("expression, expected_compiled, expected_variables, expected_objects", [
("a == 10", "a == __o_00__", {("a", 10)}, {("__o_00__", 10)}),
("__ret.status == True", "__ret.status == __o_00__", {"__ret"}, {("__o_00__", True)}),
("self == 'a'", "self == __o_00__", {("self", 'a')}, {("__o_00__", 'a')}),
("self == sheerka", "is_sheerka(self)", {("self", "sheerka")}, {}),
(
"self == BuiltinConcepts.TO_DICT",
"self == __o_00__",
{("self", BuiltinConcepts.TO_DICT)},
{("__o_00__", BuiltinConcepts.TO_DICT)}
),
(
"self == hello 'my friend'",
"""isinstance(self, Concept) and self.key == 'hello __var__0' and self.a == __o_01__""",
{("self", "hello_my_friend")},
{("__o_01__", "my friend")}
)
])
def test_python(self, expression, expected_compiled, expected_variables, expected_objects):
sheerka, context, greetings = self.init_test().with_concepts(
Concept("greetings", definition="hello a", definition_type=DEFINITION_TYPE_DEF).def_var("a"),
create_new=True
).unpack()
conditions = self.validate_python_test(context,
expression,
expected_compiled,
expression,
expected_variables,
set(),
expected_objects)
# check against SheerkaEvaluateRules
objects_mappings = {"hello_my_friend": sheerka.new(greetings, a='my friend')}
objects = self.get_testing_objects(context, expected_variables, objects_mappings)
self.check_against_python(context, expression, conditions, objects)
class TestSheerkaRuleManagerRulesCompilationFunctionsCall(BaseTestSheerkaRuleManagerRulesCompilation):
"""
Testing functions
no var : isinstance('hello', str)
with var: isinstance(a_string, str)
with and : isinstance(a_string, str) and isinstance(an_int, int)
function with concept: isinstance(self, girl)
function with concept: isinstance(self, a little boy)
function with enum: func_true(self, BuiltinConcepts.TO_DICT)
"""
def test_rete(self):
pass
@pytest.mark.parametrize("expression, e_compiled, e_text, e_variables, e_objects", [
(
"isinstance('hello', str)",
"isinstance(__o_00__, str)",
"isinstance('hello', str)",
set(),
{"__o_00__"}
),
(
"isinstance(a_string, str)",
"isinstance(a_string, str)",
"isinstance(a_string, str)",
{"a_string"},
{}
),
(
"not isinstance(an_int, str)",
"not (isinstance(an_int, str))",
"not (isinstance(an_int, str))",
{"an_int"},
{}
),
(
"isinstance(a_string, str) and isinstance(an_int, int)",
"isinstance(a_string, str) and isinstance(an_int, int)",
"isinstance(a_string, str) and isinstance(an_int, int)",
{"an_int", "a_string"},
{}
),
(
"isinstance(self, girl)",
"isinstance(self, __o_00__)",
"isinstance(self, girl)",
{("self", "girl")},
{"__o_00__"}
),
(
"isinstance(self, a little boy)",
"isinstance(self, __o_00__)",
"isinstance(self, a little boy)",
{("self", "a little boy")},
{"__o_00__"}
),
(
"func_true(self, BuiltinConcepts.TO_DICT)",
"func_true(self, BuiltinConcepts.TO_DICT)",
"func_true(self, BuiltinConcepts.TO_DICT)",
{("self", BuiltinConcepts.TO_DICT)},
{}
),
])
def test_python(self, expression, e_compiled, e_text, e_variables, e_objects):
sheerka, context, girl, little_boy = self.init_test().with_concepts(
Concept("girl"),
Concept("a little boy"),
create_new=True
).unpack()
conditions = self.validate_python_test(context,
expression,
e_compiled,
e_text,
e_variables,
set(),
e_objects)
# check against SheerkaEvaluateRules
objects_mappings = {"girl": girl, "a little boy": little_boy}
objects = self.get_testing_objects(context, e_variables, objects_mappings)
objects["func_true"] = self.func_true
self.check_against_python(context, expression, conditions, objects)
class TestSheerkaRuleManagerRulesCompilationRecognizeConcept(BaseTestSheerkaRuleManagerRulesCompilation):
"""
Testing recognize(path, concept)
recognize by name : recognize(__ret.body, greetings)
recognize by id : recognize(__ret.body, c:|1001:)
recognize by name using c_str : recognize(__ret.body, c:greetings:)
recognize by name + str condition : recognize(__ret.body, greetings) and __ret.body.a == 'my friend'
recognize by name + sheerka condition : recognize(__ret.body, greetings) and __ret.body.a == sheerka
recognize by name + concept condition : recognize(__ret.body, greetings) and __ret.body.a == foo
recognize by instance using sheerka : recognize(__ret.body, hello sheerka)
recognize by instance using a string : recognize(__ret.body, hello 'my friend')
recognize by instance using a concept : recognize(__ret.body, hello foo)
recognize by instance using long concept : recognize(__ret.body, hello my best friend)
recognize self : recognize(self, greetings)
"""
@pytest.mark.parametrize("expression, expected_as_list_of_str, expected_variable, greeting_var", [
(
"recognize(__ret.body, greetings)",
["#__x_00__|__name__|'__ret'",
"#__x_00__|body|#__x_01__",
"#__x_01__|__is_concept__|True",
"#__x_01__|name|'greetings'"],
"__ret",
None
),
(
"recognize(__ret.body, c:|1001:)",
["#__x_00__|__name__|'__ret'",
"#__x_00__|body|#__x_01__",
"#__x_01__|__is_concept__|True",
"#__x_01__|id|'1001'"],
"__ret",
None
),
(
"recognize(__ret.body, c:greetings:)",
["#__x_00__|__name__|'__ret'",
"#__x_00__|body|#__x_01__",
"#__x_01__|__is_concept__|True",
"#__x_01__|name|'greetings'"],
"__ret",
None
),
(
"recognize(__ret.body, greetings) and __ret.body.a == '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'"],
"__ret",
"my friend",
),
(
"recognize(__ret.body, greetings) and __ret.body.a == sheerka",
["#__x_00__|__name__|'__ret'",
"#__x_00__|body|#__x_01__",
"#__x_01__|__is_concept__|True",
"#__x_01__|name|'greetings'",
"#__x_01__|a|'__sheerka__'"],
"__ret",
"sheerka",
),
(
"recognize(__ret.body, greetings) and __ret.body.a == 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'"],
"__ret",
"foo",
),
(
"recognize(__ret.body, hello 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__'"],
"__ret",
"sheerka",
),
(
"recognize(__ret.body, hello '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'"],
"__ret",
"my friend",
),
(
"recognize(__ret.body, hello 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'"],
"__ret",
"foo",
),
(
"recognize(__ret.body, hello 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'"],
"__ret",
"my best friend",
),
(
"recognize(self, greetings)",
["#__x_00__|__name__|'self'",
"#__x_00__|__is_concept__|True",
"#__x_00__|name|'greetings'"],
"self",
None,
)
])
def test_rete(self, expression, expected_as_list_of_str, expected_variable, greeting_var):
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_list_of_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
variable_map = {
"foo": foo,
"my best friend": my_best_friend,
"sheerka": sheerka
}
variable = variable_map.get(greeting_var, greeting_var)
to_recognize = sheerka.new_from_template(greetings, greetings.key, a=variable)
objects = self.get_testing_objects(context, [(expected_variable, to_recognize)])
self.check_against_rete(expression, conditions, objects)
@pytest.mark.parametrize("expression, e_compiled, e_text, e_variables, greeting_var, e_objects", [
(
"recognize(__ret.body, greetings)",
"__x_00__ = __ret.body\nisinstance(__x_00__, Concept) and __x_00__.name == 'greetings'",
"__x_00__ = __ret.body\nisinstance(__x_00__, Concept) and __x_00__.name == 'greetings'",
{"__ret"},
None,
set()
),
(
"recognize(__ret.body, c:|1001:)",
"__x_00__ = __ret.body\nisinstance(__x_00__, Concept) and __x_00__.id == '1001'",
"__x_00__ = __ret.body\nisinstance(__x_00__, Concept) and __x_00__.id == '1001'",
{"__ret"},
None,
set()
),
(
"recognize(__ret.body, c:greetings:)",
"__x_00__ = __ret.body\nisinstance(__x_00__, Concept) and __x_00__.name == 'greetings'",
"__x_00__ = __ret.body\nisinstance(__x_00__, Concept) and __x_00__.name == 'greetings'",
{"__ret"},
None,
set()
),
(
"recognize(__ret.body, greetings) and __ret.body.a == 'my friend'",
"__x_00__ = __ret.body\nisinstance(__x_00__, Concept) and __x_00__.name == 'greetings' and __x_00__.a == __o_00__",
"__x_00__ = __ret.body\nisinstance(__x_00__, Concept) and __x_00__.name == 'greetings' and __ret.body.a == 'my friend'",
{"__ret"},
"my friend",
{("__o_00__", "my friend")}
),
(
"recognize(__ret.body, greetings) and __ret.body.a == sheerka",
"""__x_00__ = __ret.body
isinstance(__x_00__, Concept) and __x_00__.name == 'greetings' and is_sheerka(__x_00__.a)""",
"""__x_00__ = __ret.body
isinstance(__x_00__, Concept) and __x_00__.name == 'greetings' and __ret.body.a == sheerka""",
{"__ret"},
"sheerka",
set()
),
(
"recognize(__ret.body, greetings) and __ret.body.a == 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'""",
"""__x_00__ = __ret.body
__x_01__ = __x_00__.a
isinstance(__x_00__, Concept) and __x_00__.name == 'greetings' and __ret.body.a == foo""",
{"__ret"},
"foo",
set()
),
(
"recognize(__ret.body, hello sheerka)",
"""__x_00__ = __ret.body
isinstance(__x_00__, Concept) and __x_00__.key == 'hello __var__0' and is_sheerka(__x_00__.a)""",
"""__x_00__ = __ret.body
isinstance(__x_00__, Concept) and __x_00__.key == 'hello __var__0' and __x_00__.a == sheerka""",
{"__ret"},
"sheerka",
set()
),
(
"recognize(__ret.body, hello 'my friend')",
"""__x_00__ = __ret.body
isinstance(__x_00__, Concept) and __x_00__.key == 'hello __var__0' and __x_00__.a == __o_00__""",
"""__x_00__ = __ret.body
isinstance(__x_00__, Concept) and __x_00__.key == 'hello __var__0' and __x_00__.a == 'my friend'""",
{"__ret"},
"my friend",
{('__o_00__', 'my friend')}
),
(
"recognize(__ret.body, hello 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'""",
"""__x_00__ = __ret.body
__x_01__ = __x_00__.a
isinstance(__x_00__, Concept) and __x_00__.key == 'hello __var__0' and __x_00__.a == c:foo|1002:""",
{"__ret"},
"foo",
{'__o_00__'}
),
(
"recognize(__ret.body, hello 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'""",
"""__x_00__ = __ret.body
__x_01__ = __x_00__.a
isinstance(__x_00__, Concept) and __x_00__.key == 'hello __var__0' and __x_00__.a == c:my best friend|1003:""",
{"__ret"},
"my best friend",
{'__o_00__'}
),
(
"recognize(self, greetings)",
"isinstance(self, Concept) and self.name == 'greetings'",
"isinstance(self, Concept) and self.name == 'greetings'",
{"self"},
None,
set()
)
])
def test_python(self, expression, e_compiled, e_text, e_variables, greeting_var, e_objects):
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()
conditions = self.validate_python_test(context,
expression,
e_compiled,
e_text,
e_variables,
set(),
e_objects)
# check against SheerkaEvaluateRules
variable_map = {
"foo": foo,
"my best friend": my_best_friend,
"sheerka": Expando("sheerka", {})
}
variable = variable_map.get(greeting_var, greeting_var)
to_recognize = sheerka.new_from_template(greetings, greetings.key, a=variable)
expected_variable = next(iter(e_variables))
objects = self.get_testing_objects(context, [(expected_variable, to_recognize)])
self.check_against_python(context, expression, conditions, objects)
class TestSheerkaRuleManagerRulesCompilationEvalQuestionConcept(BaseTestSheerkaRuleManagerRulesCompilation):
"""
Testing question using concepts
with no variable : girl is a human
with variable : self is a human
with long concept : the little boy is a human being
with long concept + variable : the little boy is a self
with long concept + variable : self is a human being
"""
def test_rete(self):
pass # I don't know yet what to do
@pytest.mark.parametrize("expression, expected_compiled, expected_variables", [
(
"girl is a human",
"evaluate_question(__o_00__)",
set(),
),
(
"self is a human",
"evaluate_question(__o_00__)",
{"self"},
),
(
"the little boy is a human being",
"evaluate_question(__o_00__)",
set(),
),
(
"the little boy is a self",
"evaluate_question(__o_00__)",
{"self"},
),
(
"self is a human being",
"evaluate_question(__o_00__)",
{"self"},
),
])
def test_python(self, expression, expected_compiled, expected_variables):
sheerka, context, girl, human, little_boy, human_being, isa = self.init_test().with_concepts(
Concept("girl"),
Concept("human"),
Concept("the little boy"),
Concept("human being"),
Concept("x is a y", pre="is_question()").def_var("x").def_var("y"),
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)
ast_ = ast.parse(expected_compiled, "<source>", 'exec' if "\n" in expected_compiled else 'eval')
expected_python_node = PythonNode(expected_compiled, ast_, expression)
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 "__o_00__" in conditions[0].objects
assert conditions[0].variables == expected_variables
assert len(conditions[0].concepts_to_reset) == 1
assert sheerka.isinstance(next(iter(conditions[0].concepts_to_reset)), isa)
# check against SheerkaEvaluateRules
self.check_against_python(context, expression, conditions,
self.get_testing_objects(context, expected_variables))
class TestSheerkaRuleManagerRulesCompilationEvalQuestionConceptWithNot(BaseTestSheerkaRuleManagerRulesCompilation):
"""
Testing question using concepts mixed with others conditions
using not : not girl is a human
using not : not self is a human
"""
def test_rete(self):
pass
@pytest.mark.parametrize(
"expression, expected_compiled, expected_text, expected_variables", [
(
"not girl is a human",
"not (evaluate_question(__o_00__))",
"not (girl is a human)",
set(),
),
(
"not self is a human",
"not (evaluate_question(__o_00__))",
"not (self is a human)",
{"self"},
),
])
def test_python(self, expression, expected_compiled, expected_text, expected_variables):
sheerka, context, girl, human, little_boy, human_being, isa = self.init_test().with_concepts(
Concept("girl"),
Concept("human"),
Concept("the little boy"),
Concept("human being"),
Concept("x is a y", pre="is_question()").def_var("x").def_var("y"),
create_new=True
).unpack()
conditions = self.validate_python_test(context,
expression,
expected_compiled,
expected_text,
expected_variables,
set(),
{"__o_00__"})
# check against SheerkaEvaluateRules
self.check_against_python(context,
expression,
conditions,
self.get_testing_objects(context, expected_variables),
False)
class TestSheerkaRuleManagerRulesCompilationEvalConceptMixedWithOther(BaseTestSheerkaRuleManagerRulesCompilation):
"""
Testing question using concepts mixed with others conditions
using and with python : girl is a human being and isinstance(a_string, str)
using and with another concept : self is a human being and isinstance(self, girl)
starting with python : isinstance(x, str) and girl is a human being
starting with python : isinstance(self, girl) and self is a human being
multiple python + same variable : self is a human being and isinstance(self, girl) and isinstance(self, girl)
"""
def test_rete(self):
pass # I don't know yet what to do
@pytest.mark.parametrize(
"expression, expected_compiled, expected_variables, expected_objects", [
(
"girl is a human being and isinstance(a_string, str)",
"evaluate_question(__o_00__) and isinstance(a_string, str)",
{"a_string"},
{"__o_00__"}
),
(
"self is a human being and isinstance(self, girl)",
"evaluate_question(__o_00__) and isinstance(self, __o_01__)",
{("self", "girl")},
{"__o_00__", "__o_01__"}
),
(
"isinstance(a_string, str) and girl is a human being",
"isinstance(a_string, str) and evaluate_question(__o_00__)",
{"a_string"},
{"__o_00__"}
),
(
"isinstance(self, girl) and self is a human being",
"isinstance(self, __o_00__) and evaluate_question(__o_01__)",
{("self", "girl")},
{"__o_00__", "__o_01__"}
),
(
"self is a human being and isinstance(self, girl) and isinstance(self, girl)",
"evaluate_question(__o_00__) and isinstance(self, __o_01__) and isinstance(self, __o_02__)",
{("self", "girl")},
{"__o_00__", "__o_01__", "__o_02__"}
),
])
def test_python(self, expression, expected_compiled, expected_variables, expected_objects):
sheerka, context, girl, human_being, isa = self.init_test().with_concepts(
Concept("girl"),
Concept("human being"),
Concept("x is a y", pre="is_question()").def_var("x").def_var("y"),
create_new=True
).unpack()
conditions = self.validate_python_test(context,
expression,
expected_compiled,
expression,
expected_variables,
set(),
expected_objects)
# check against SheerkaEvaluateRules
variable_mapping = {
"girl": girl,
"human being": human_being
}
testing_objects = self.get_testing_objects(context, expected_variables, variable_mapping)
self.check_against_python(context,
expression,
conditions,
testing_objects,
True)
class TestSheerkaRuleManagerRulesCompilationEvalNonQuestionConcept(BaseTestSheerkaRuleManagerRulesCompilation):
"""
Testing complex concepts composition
with BNF : twenty two
additions : twenty two + one
additions : twenty two + twenty one
additions : twenty two plus one
additions : twenty two plus twenty one
with function: func_identity(twenty two)
with function: func_identity(twenty two + one)
with function: func_identity(twenty two + twenty one)
with function: func_identity(twenty two plus one)
with function: func_identity(twenty two plus twenty one)
"""
def test_rete(self):
pass # I don't know yet what to do
@pytest.mark.parametrize("expression, e_compiled, e_text, e_objects, e_result", [
(
"twenty two",
"__o_00__",
"twenty two",
{"__o_00__"},
22
),
(
"twenty two + one",
"__o_00__",
"twenty two + one",
{("__o_00__", 23)},
23
),
(
"twenty two + twenty one",
"__o_00__",
"twenty two + twenty one",
{("__o_00__", 43)},
43
),
(
"twenty two plus one",
"__o_00__",
"twenty two plus one",
{"__o_00__"},
23
),
(
"twenty two plus twenty one",
"__o_00__",
"twenty two plus twenty one",
{"__o_00__"},
43
),
(
"func_identity(twenty two)",
"func_identity(__o_00__)",
"func_identity(twenty two)",
{"__o_00__"},
22
),
(
"func_identity(twenty two + one)",
"func_identity(__o_00__)",
"func_identity(twenty two + one)",
{("__o_00__", 23)},
23
),
(
"func_identity(twenty two + twenty one)",
"func_identity(__o_00__)",
"func_identity(twenty two + twenty one)",
{("__o_00__", 43)},
43
),
(
"func_identity(twenty two plus one)",
"func_identity(__o_00__)",
"func_identity(twenty two plus one)",
{"__o_00__"},
23
),
(
"func_identity(twenty two plus twenty one)",
"func_identity(__o_00__)",
"func_identity(twenty two plus twenty one)",
{"__o_00__"},
43
),
])
def test_python(self, expression, e_compiled, e_text, e_objects, e_result):
sheerka, context, one, two, twenties, plus = self.init_test().with_concepts(
Concept("one", body="1"),
Concept("two", body="2"),
Concept("twenties", definition="'twenty' (one|two)=n", body='20 + n').def_var("n"),
Concept("a plus b", body="a + b").def_var("a").def_var("b"),
create_new=True
).unpack()
conditions = self.validate_python_test(context,
expression,
e_compiled,
e_text,
set(),
set(),
e_objects)
# check against SheerkaEvaluateRules
namespace = {"func_identity": self.func_identity}
res = self.evaluate_condition(context, expression, conditions[0], namespace)
assert res.status
assert sheerka.objvalue(res) == e_result
class TestSheerkaRuleManagerRulesCompilationMultipleSameConcept(BaseTestSheerkaRuleManagerRulesCompilation):
"""
Test when a concept returns multiple results
The compilation should fail : No need to execute a condition if we are not sure of the meaning ?
self is a bar
"""
def test_rete(self):
sheerka, context, bar, isa_1, isa_2 = self.init_test().with_concepts(
Concept("bar"),
Concept("x is a y").def_var("x").def_var("y"),
Concept("u is a v").def_var("u").def_var("v"),
create_new=True
).unpack()
with pytest.raises(FailedToCompileError):
parser = ExpressionParser()
error_sink = ErrorSink()
parser_input = ParserInput("self is a bar")
parser.reset_parser_input(parser_input, error_sink)
parsed = parser.parse_input(context, parser_input, error_sink)
visitor = ReteConditionExprVisitor(context)
visitor.get_conditions(parsed)
def test_python(self):
sheerka, context, bar, isa_1, isa_2 = self.init_test().with_concepts(
Concept("bar"),
Concept("x is a y").def_var("x").def_var("y"),
Concept("u is a v").def_var("u").def_var("v"),
create_new=True
).unpack()
with pytest.raises(FailedToCompileError):
parser = ExpressionParser()
error_sink = ErrorSink()
parser_input = ParserInput("self is a bar")
parser.reset_parser_input(parser_input, error_sink)
parsed = parser.parse_input(context, parser_input, error_sink)
visitor = PythonConditionExprVisitor(context)
visitor.get_conditions(parsed)
class TestSheerkaRuleManagerRulesCompilationNot(BaseTestSheerkaRuleManagerRulesCompilation):
"""
Testing not
not __ret.status == True
not recognize(__ret.body, hello sheerka)
"""
pass