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, "", '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, "", '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